11package org .broken .arrow .library .itemcreator .utility ;
22
3+ import org .broken .arrow .library .itemcreator .utility .compound .CompoundTag ;
4+ import org .broken .arrow .library .itemcreator .utility .compound .NbtData ;
35import org .broken .arrow .library .logging .Logging ;
46import org .bukkit .Bukkit ;
57import org .bukkit .Material ;
810
911import javax .annotation .Nonnull ;
1012import javax .annotation .Nullable ;
11- import java .lang .reflect .Constructor ;
1213import java .lang .reflect .InvocationTargetException ;
13- import java .lang .reflect .Method ;
1414
1515public final class UnbreakableUtil {
1616 private static final Logging logger = new Logging (UnbreakableUtil .class );
@@ -40,7 +40,6 @@ public static ItemMeta applyToMeta(@Nullable final ItemMeta meta, final boolean
4040 meta .setUnbreakable (unbreakable );
4141 return meta ;
4242 }
43- if (!NMS_NBT_BRIDGE .isReflectionReady ()) return meta ;
4443
4544 Material original = getMetaType (meta );
4645 if (original == null || original == Material .AIR ) original = Material .STONE ;
@@ -72,8 +71,6 @@ public static ItemStack applyToItem(@Nullable final ItemStack item, final boolea
7271 return item ;
7372 }
7473
75- if (!NMS_NBT_BRIDGE .isReflectionReady ()) return item ;
76-
7774 try {
7875 return NMS_NBT_BRIDGE .applyUnbreakableTag (item , "Unbreakable" , unbreakable );
7976 } catch (InvocationTargetException | IllegalAccessException | InstantiationException t ) {
@@ -98,7 +95,6 @@ public static boolean isUnbreakable(@Nullable final ItemStack item) {
9895 final ItemMeta itemMeta = item .getItemMeta ();
9996 return itemMeta != null && itemMeta .isUnbreakable ();
10097 } else {
101- if (!NMS_NBT_BRIDGE .isReflectionReady ()) return false ;
10298 try {
10399 return NMS_NBT_BRIDGE .hasBooleanTag (item , "Unbreakable" );
104100 } catch (InvocationTargetException | IllegalAccessException | InstantiationException e ) {
@@ -136,17 +132,7 @@ private static Material getMetaType(@Nonnull final ItemMeta meta) {
136132 * <p>Otherwise it dynamically resolves required CraftBukkit and NMS classes
137133 * and methods.</p>
138134 */
139- private static class NmsNbtBridge {
140- private Method asNMSCopyMethod ;
141- private Method asBukkitCopyMethod ;
142- private Method hasTagMethod ;
143- private Method getTagMethod ;
144- private Method setTagMethod ;
145- private Method setBooleanMethod ;
146- private Method getBooleanMethod ;
147- private Constructor <?> nbtTagConstructor ;
148-
149- private boolean reflectionReady ;
135+ public static class NmsNbtBridge {
150136 private boolean modernSupported ;
151137
152138 /**
@@ -162,42 +148,17 @@ private NmsNbtBridge() {
162148 } catch (ClassNotFoundException | NoSuchMethodException ignored ) {
163149 this .modernSupported = false ;
164150 }
165- if (this .modernSupported ) return ;
166- loadLegacyReflection ();
167- }
168-
169- public Method getAsBukkitCopyMethod () {
170- return asBukkitCopyMethod ;
171- }
172-
173- public Method getHasTagMethod () {
174- return hasTagMethod ;
175- }
176-
177- public Method getTagMethod () {
178- return getTagMethod ;
179- }
180-
181- public Method getSetTagMethod () {
182- return setTagMethod ;
183- }
184-
185- public Method getSetBooleanMethod () {
186- return setBooleanMethod ;
187- }
188-
189- public Method getBooleanMethod () {
190- return getBooleanMethod ;
191- }
192-
193- public Constructor <?> getNbtTagConstructor () {
194- return nbtTagConstructor ;
195- }
196-
197- public boolean isReflectionReady () {
198- return reflectionReady ;
199151 }
200152
153+ /**
154+ * Indicates whether the current server version supports the modern
155+ * Bukkit API method {@code ItemMeta#setUnbreakable(boolean)}.
156+ *
157+ * <p>If this returns {@code true}, no reflection or NMS handling is required
158+ * and this bridge will remain inactive.</p>
159+ *
160+ * @return {@code true} if the modern API is available, otherwise {@code false}
161+ */
201162 public boolean isModernSupported () {
202163 return modernSupported ;
203164 }
@@ -212,137 +173,31 @@ public boolean isModernSupported() {
212173 * @return a new Bukkit ItemStack instance with updated NBT
213174 */
214175 public ItemStack applyUnbreakableTag (@ Nonnull final ItemStack item , @ Nonnull final String key , final boolean unbreakable ) throws InvocationTargetException , IllegalAccessException , InstantiationException {
215- Object nmsItem = this .toNmsItemStack (item );
216- this .applyBooleanTag (nmsItem , key , unbreakable );
217- return (ItemStack ) this .getAsBukkitCopyMethod ().invoke (null , nmsItem );
176+ NbtData nms = new NbtData (item );
177+ if (!nms .isReflectionReady ()) return item ;
178+
179+ CompoundTag compound = nms .getOrCreateCompound ();
180+ compound .setBoolean (key ,unbreakable );
181+ return nms .apply (compound );
218182 }
219183
220184 /**
221185 * Checks whether the given Bukkit item contains the specified
222- * boolean NBT key.
186+ * NBT key.
223187 *
224188 * @param item Bukkit ItemStack
225189 * @param key NBT key
226190 * @return {@code true} if the key exists and is set to {@code true}
227191 */
228192 public boolean hasBooleanTag (@ Nonnull final ItemStack item , @ Nonnull String key ) throws InvocationTargetException , IllegalAccessException , InstantiationException {
229- Object nmsItem = this .toNmsItemStack (item );
230- if (!(Boolean ) this .getHasTagMethod ().invoke (nmsItem )) {
231- return false ;
232- }
233- Object tag = this .getOrCreateNbtTag (nmsItem );
234- return (Boolean ) this .getBooleanMethod ().invoke (tag , key );
235- }
236-
237- /**
238- * Applies a boolean tag to an NMS ItemStack.
239- *
240- * @param nmsItem the nms stack.
241- * @param key the key to set
242- * @param unbreakable if it set to {@code true} it will be unbreakable, otherwise the tool can break.
243- */
244- public void applyBooleanTag (@ Nonnull final Object nmsItem , @ Nonnull final String key , final boolean unbreakable ) throws InvocationTargetException , IllegalAccessException , InstantiationException {
245- final Object tag = this .getOrCreateNbtTag (nmsItem );
246- this .setBooleanTag (tag , key , unbreakable );
247- this .applyTagCompound (nmsItem , tag );
248- }
249-
250- /**
251- * Applies an NBT compound to an NMS ItemStack.
252- *
253- * @param nmsItem the nms stack.
254- * @param tag the NBTTagCompound to be set.
255- */
256- public void applyTagCompound (@ Nonnull final Object nmsItem , @ Nonnull final Object tag ) throws InvocationTargetException , IllegalAccessException {
257- getSetTagMethod ().invoke (nmsItem , tag );
258- }
193+ NbtData nms = new NbtData (item );
194+ if (!nms .isReflectionReady ()) return false ;
259195
260- /**
261- * Sets a boolean inside an NBTTagCompound.
262- *
263- * @param tag the NBTTagCompound to be set.
264- * @param key the key to set
265- * @param unbreakable if it shall be true or false.
266- */
267- public void setBooleanTag (@ Nonnull final Object tag , @ Nonnull final String key , final boolean unbreakable ) throws InvocationTargetException , IllegalAccessException {
268- getSetBooleanMethod ().invoke (tag , key , unbreakable );
269- }
270-
271- /**
272- * Returns the existing NBTTagCompound if one is present,
273- * otherwise creates a new one.
274- *
275- * @param nmsItem the nms stack.
276- * @return the NBTTagCompound if exist or create new one.
277- */
278- public Object getOrCreateNbtTag (@ Nonnull final Object nmsItem ) throws InvocationTargetException , IllegalAccessException , InstantiationException {
279- boolean hasTag = (boolean ) hasTagMethod .invoke (nmsItem );
280- return hasTag
281- ? getTagMethod .invoke (nmsItem )
282- : nbtTagConstructor .newInstance ();
283- }
284-
285- /**
286- * Resolves all CraftBukkit and NMS classes and methods using reflection.
287- * This is only required for legacy versions.
288- */
289- private void loadLegacyReflection () {
290- try {
291-
292- String craftPath = getCraftBukkitPath ();
293-
294- final Class <?> craftItemStackClass = Class .forName (craftPath + ".inventory.CraftItemStack" );
295- asNMSCopyMethod = craftItemStackClass .getMethod ("asNMSCopy" , ItemStack .class );
296- asBukkitCopyMethod = craftItemStackClass .getMethod ("asBukkitCopy" , Class .forName (getMinecraftPath () + ".ItemStack" ));
297-
298- final Class <?> nbtTagCompoundClass = Class .forName (getMinecraftPath () + ".NBTTagCompound" );
299-
300- nbtTagConstructor = nbtTagCompoundClass .getConstructor ();
301-
302- Class <?> nmsStackClass = Class .forName (getMinecraftPath () + ".ItemStack" );
303-
304- hasTagMethod = nmsStackClass .getMethod ("hasTag" );
305- getTagMethod = nmsStackClass .getMethod ("getTag" );
306- setTagMethod = nmsStackClass .getMethod ("setTag" , nbtTagCompoundClass );
307- setBooleanMethod = nbtTagCompoundClass .getMethod ("setBoolean" , String .class , boolean .class );
308- getBooleanMethod = nbtTagCompoundClass .getMethod ("getBoolean" , String .class );
309-
310- reflectionReady = true ;
311- } catch (ClassNotFoundException | NoSuchMethodException t ) {
312- logger .logError (t , () -> "Could not resolve the unbreakable tag for this minecraft version" );
313- reflectionReady = false ;
196+ final CompoundTag compound = nms .getCompound ();
197+ if (compound == null ) {
198+ return false ;
314199 }
315- }
316-
317- private String getMinecraftPath () {
318- return "net.minecraft.server."
319- + getPackageVersion ();
320- }
321-
322- private String getCraftBukkitPath () {
323- return "org.bukkit.craftbukkit." + getPackageVersion ();
324- }
325-
326- /**
327- * Extracts the version identifier from the Bukkit server package.
328- * This version will only work on legacy, as the path changed in newer
329- * minecraft versions.
330- * Example: v1_8_R3
331- *
332- * @return it returns for example v1_8_R3
333- */
334- private String getPackageVersion () {
335- return Bukkit .getServer ().getClass ().getPackage ().getName ().split ("\\ ." )[3 ];
336- }
337-
338- /**
339- * Converts a Bukkit ItemStack into its NMS counterpart.
340- *
341- * @param item Bukkit ItemStack to convert.
342- * @return the underlying Nms itemStack.
343- */
344- private Object toNmsItemStack (@ Nonnull final ItemStack item ) throws IllegalAccessException , InvocationTargetException {
345- return this .asNMSCopyMethod .invoke (null , item );
200+ return compound .hasKey (key );
346201 }
347202
348203 }
0 commit comments