diff --git a/dough-items/src/main/java/io/github/bakedlibs/dough/items/nms/ItemNameAdapter.java b/dough-items/src/main/java/io/github/bakedlibs/dough/items/nms/ItemNameAdapter.java index a541f203..a335504a 100644 --- a/dough-items/src/main/java/io/github/bakedlibs/dough/items/nms/ItemNameAdapter.java +++ b/dough-items/src/main/java/io/github/bakedlibs/dough/items/nms/ItemNameAdapter.java @@ -25,6 +25,9 @@ public interface ItemNameAdapter { if (MinecraftVersion.isMocked()) { // Special case for MockBukkit return new ItemNameAdapterMockBukkit(); + }else if(ItemNameAdapterPaper.canUse()) { + //when mcpaper or like are present then rely on paperAPI rather then deep diving into NMS + return new ItemNameAdapterPaper(); } else if (version.isAtLeast(1, 20)) { return new ItemNameAdapter20(); } else if (version.isAtLeast(1, 19)) { diff --git a/dough-items/src/main/java/io/github/bakedlibs/dough/items/nms/ItemNameAdapterPaper.java b/dough-items/src/main/java/io/github/bakedlibs/dough/items/nms/ItemNameAdapterPaper.java new file mode 100644 index 00000000..d93e1413 --- /dev/null +++ b/dough-items/src/main/java/io/github/bakedlibs/dough/items/nms/ItemNameAdapterPaper.java @@ -0,0 +1,33 @@ +package io.github.bakedlibs.dough.items.nms; + +import io.github.bakedlibs.dough.reflection.ReflectionUtils; +import org.bukkit.inventory.ItemStack; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +class ItemNameAdapterPaper implements ItemNameAdapter { + + private final Method getName; + + ItemNameAdapterPaper() { + super(); + + getName = ReflectionUtils.getMethod(ItemStack.class, "getI18NDisplayName"); + } + + public static boolean canUse() { + try { + ReflectionUtils.getMethod(ItemStack.class, "getI18NDisplayName"); + return true; + } catch (Exception e) { + return false; + } + } + + @Override + public String getName(ItemStack item) throws IllegalAccessException, InvocationTargetException { + return (String) getName.invoke(item); + } + +} \ No newline at end of file diff --git a/dough-skins/src/main/java/io/github/bakedlibs/dough/skins/nms/PlayerHeadAdapter.java b/dough-skins/src/main/java/io/github/bakedlibs/dough/skins/nms/PlayerHeadAdapter.java index 957571d9..e0d1adb4 100644 --- a/dough-skins/src/main/java/io/github/bakedlibs/dough/skins/nms/PlayerHeadAdapter.java +++ b/dough-skins/src/main/java/io/github/bakedlibs/dough/skins/nms/PlayerHeadAdapter.java @@ -1,29 +1,23 @@ package io.github.bakedlibs.dough.skins.nms; -import java.lang.reflect.InvocationTargetException; -import java.util.logging.Level; - -import javax.annotation.Nullable; -import javax.annotation.ParametersAreNonnullByDefault; - -import org.bukkit.block.Block; - import com.mojang.authlib.GameProfile; - import io.github.bakedlibs.dough.common.DoughLogger; import io.github.bakedlibs.dough.versions.MinecraftVersion; +import org.bukkit.block.Block; -public interface PlayerHeadAdapter { - - @ParametersAreNonnullByDefault - @Nullable - Object getTileEntity(Block block) throws IllegalAccessException, InvocationTargetException, InstantiationException; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Level; - @ParametersAreNonnullByDefault - void setGameProfile(Object tileEntity, GameProfile profile) throws IllegalAccessException, InvocationTargetException; +public interface PlayerHeadAdapter { public static @Nullable PlayerHeadAdapter get() { try { + if (PlayerHeadAdapterPaper.canApply()) { + return new PlayerHeadAdapterPaper(); + } + MinecraftVersion version = MinecraftVersion.get(); if (version.isAtLeast(1, 18)) { @@ -43,4 +37,11 @@ public interface PlayerHeadAdapter { } } + + @ParametersAreNonnullByDefault + @Nullable + Object getTileEntity(Block block) throws IllegalAccessException, InvocationTargetException, InstantiationException; + + @ParametersAreNonnullByDefault + void setGameProfile(Object tileEntity, GameProfile profile) throws IllegalAccessException, InvocationTargetException; } diff --git a/dough-skins/src/main/java/io/github/bakedlibs/dough/skins/nms/PlayerHeadAdapterPaper.java b/dough-skins/src/main/java/io/github/bakedlibs/dough/skins/nms/PlayerHeadAdapterPaper.java new file mode 100644 index 00000000..c4a9ba3d --- /dev/null +++ b/dough-skins/src/main/java/io/github/bakedlibs/dough/skins/nms/PlayerHeadAdapterPaper.java @@ -0,0 +1,74 @@ +package io.github.bakedlibs.dough.skins.nms; + +import com.mojang.authlib.GameProfile; +import com.mojang.authlib.properties.Property; +import io.github.bakedlibs.dough.reflection.ReflectionUtils; +import io.github.bakedlibs.dough.versions.UnknownServerVersionException; +import org.bukkit.Bukkit; +import org.bukkit.block.Block; +import org.bukkit.block.Skull; + +import javax.annotation.Nullable; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Collection; + +public class PlayerHeadAdapterPaper implements PlayerHeadAdapter { + + private static final String PROPERTY_KEY = "textures"; + private final Method createPaperGameProfile; + private final Method paperGameProfileSetProperty; + private final Constructor createProperty; + private final Method setGameProfile; + + + public PlayerHeadAdapterPaper() throws NoSuchMethodException, SecurityException, ClassNotFoundException, UnknownServerVersionException { + Class paperGameProfile = Class.forName("com.destroystokyo.paper.profile.PlayerProfile"); + Class paperProperty = Class.forName("com.destroystokyo.paper.profile.ProfileProperty"); + createPaperGameProfile = ReflectionUtils.getMethod(Bukkit.class, "createProfile"); + paperGameProfileSetProperty = ReflectionUtils.getMethod(paperGameProfile, "setProperty", paperProperty); + createProperty = ReflectionUtils.getConstructor(paperProperty, String.class, String.class); + setGameProfile = ReflectionUtils.getMethod(Skull.class, "setPlayerProfile", paperGameProfile); + } + + public static boolean canApply() { + try { + Class.forName("com.destroystokyo.paper.profile.PlayerProfile"); + return true; + } catch (ClassNotFoundException e) { + return false; + } + + } + + @Nullable + @Override + public Object getTileEntity(Block block) throws IllegalAccessException, InvocationTargetException, InstantiationException { + return block.getState(); + } + + @Override + public void setGameProfile(Object tileEntity, GameProfile profile) throws IllegalAccessException, InvocationTargetException { + if (!(tileEntity instanceof Skull)) { + throw new IllegalArgumentException("tileEntity must be BukkitAPI Skull tile entity. Provided " + tileEntity.getClass().getName()); + } + Skull skull = (Skull) tileEntity; + Collection properties = profile.getProperties().get(PROPERTY_KEY); + if (properties.isEmpty()) { + return; + } + String texture = properties.iterator().next().getValue(); + + Object paperGameProfile = createPaperGameProfile.invoke(null, profile.getId()); + Object property; + try { + property = createProperty.newInstance(PROPERTY_KEY, texture); + } catch (InstantiationException e) { + //shouldnt fail if it got this far + throw new InvocationTargetException(e); + } + paperGameProfileSetProperty.invoke(paperGameProfile, property); + setGameProfile.invoke(skull, paperGameProfile); + } +}