Added texture:<base64> to Items.lookup
This commit is contained in:
@@ -5,6 +5,7 @@ import com.willfp.eco.core.recipe.parts.MaterialTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.ModifiedTestableItem;
|
||||
import com.willfp.eco.core.recipe.parts.TestableStack;
|
||||
import com.willfp.eco.util.NamespacedKeyUtils;
|
||||
import com.willfp.eco.util.SkullUtils;
|
||||
import lombok.experimental.UtilityClass;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
@@ -12,6 +13,7 @@ import org.bukkit.enchantments.Enchantment;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.inventory.meta.EnchantmentStorageMeta;
|
||||
import org.bukkit.inventory.meta.ItemMeta;
|
||||
import org.bukkit.inventory.meta.SkullMeta;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -20,6 +22,7 @@ import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Class to manage all custom and vanilla items.
|
||||
@@ -29,7 +32,7 @@ public final class Items {
|
||||
/**
|
||||
* All recipe parts.
|
||||
*/
|
||||
private static final Map<NamespacedKey, CustomItem> REGISTRY = new HashMap<>();
|
||||
private static final Map<NamespacedKey, CustomItem> REGISTRY = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* Register a new recipe part.
|
||||
@@ -111,7 +114,7 @@ public final class Items {
|
||||
|
||||
/*
|
||||
Legacy id:amount format
|
||||
This has been superceded by id amount
|
||||
This has been superseded by id amount
|
||||
*/
|
||||
if (part == null) {
|
||||
Material material = Material.getMaterial(split[0].toUpperCase());
|
||||
@@ -127,7 +130,7 @@ public final class Items {
|
||||
|
||||
/*
|
||||
Legacy namespace:id:amount format
|
||||
This has been superceded by namespace:id amount
|
||||
This has been superseded by namespace:id amount
|
||||
*/
|
||||
if (split.length == 3) {
|
||||
CustomItem part = REGISTRY.get(NamespacedKeyUtils.create(split[0], split[1]));
|
||||
@@ -152,44 +155,80 @@ public final class Items {
|
||||
return new EmptyTestableItem();
|
||||
}
|
||||
|
||||
String[] enchantArgs = Arrays.copyOfRange(args, usingNewStackFormat ? 2 : 1, args.length);
|
||||
ItemStack example = item.getItem();
|
||||
ItemMeta meta = example.getItemMeta();
|
||||
assert meta != null;
|
||||
|
||||
String[] modifierArgs = Arrays.copyOfRange(args, usingNewStackFormat ? 2 : 1, args.length);
|
||||
|
||||
boolean hasModifiers = false;
|
||||
Map<Enchantment, Integer> requiredEnchantments = new HashMap<>();
|
||||
String skullTexture = null;
|
||||
|
||||
for (String enchantArg : enchantArgs) {
|
||||
// Handle skull texture
|
||||
for (String arg : modifierArgs) {
|
||||
String[] argSplit = arg.split(":");
|
||||
if (!argSplit[0].equalsIgnoreCase("texture")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (argSplit.length < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
skullTexture = argSplit[1];
|
||||
hasModifiers = true;
|
||||
}
|
||||
|
||||
if (meta instanceof SkullMeta skullMeta && skullTexture != null) {
|
||||
SkullUtils.setSkullTexture(skullMeta, skullTexture);
|
||||
}
|
||||
|
||||
// Handle enchantment modifiers
|
||||
for (String enchantArg : modifierArgs) {
|
||||
String[] enchantArgSplit = enchantArg.split(":");
|
||||
|
||||
Enchantment enchantment = Enchantment.getByKey(NamespacedKey.minecraft(enchantArgSplit[0].toLowerCase()));
|
||||
if (enchantment == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (enchantArgSplit.length < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
int level = Integer.parseInt(enchantArgSplit[1]);
|
||||
|
||||
requiredEnchantments.put(enchantment, level);
|
||||
hasModifiers = true;
|
||||
}
|
||||
|
||||
ItemStack example = item.getItem();
|
||||
|
||||
if (example.getItemMeta() instanceof EnchantmentStorageMeta storageMeta) {
|
||||
if (meta instanceof EnchantmentStorageMeta storageMeta) {
|
||||
requiredEnchantments.forEach((enchantment, integer) -> storageMeta.addStoredEnchant(enchantment, integer, true));
|
||||
example.setItemMeta(storageMeta);
|
||||
} else {
|
||||
ItemMeta meta = example.getItemMeta();
|
||||
assert meta != null;
|
||||
requiredEnchantments.forEach((enchantment, integer) -> meta.addEnchant(enchantment, integer, true));
|
||||
example.setItemMeta(meta);
|
||||
}
|
||||
|
||||
if (!requiredEnchantments.isEmpty()) {
|
||||
/*
|
||||
The modifiers are then applied.
|
||||
*/
|
||||
|
||||
example.setItemMeta(meta);
|
||||
|
||||
String finalSkullTexture = skullTexture; // I hate this, java.
|
||||
if (hasModifiers) {
|
||||
item = new ModifiedTestableItem(
|
||||
item,
|
||||
itemStack -> {
|
||||
if (!itemStack.hasItemMeta()) {
|
||||
test -> {
|
||||
if (!test.hasItemMeta()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ItemMeta meta = itemStack.getItemMeta();
|
||||
ItemMeta testMeta = test.getItemMeta();
|
||||
|
||||
assert meta != null;
|
||||
assert testMeta != null;
|
||||
|
||||
if (meta instanceof EnchantmentStorageMeta storageMeta) {
|
||||
if (testMeta instanceof EnchantmentStorageMeta storageMeta) {
|
||||
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
|
||||
if (!storageMeta.hasStoredEnchant(entry.getKey())) {
|
||||
return false;
|
||||
@@ -200,15 +239,21 @@ public final class Items {
|
||||
}
|
||||
} else {
|
||||
for (Map.Entry<Enchantment, Integer> entry : requiredEnchantments.entrySet()) {
|
||||
if (!meta.hasEnchant(entry.getKey())) {
|
||||
if (!testMeta.hasEnchant(entry.getKey())) {
|
||||
return false;
|
||||
}
|
||||
if (meta.getEnchantLevel(entry.getKey()) < entry.getValue()) {
|
||||
if (testMeta.getEnchantLevel(entry.getKey()) < entry.getValue()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (testMeta instanceof SkullMeta skullMeta && finalSkullTexture != null) {
|
||||
if (!finalSkullTexture.equalsIgnoreCase(SkullUtils.getSkullTexture(skullMeta))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
example
|
||||
|
||||
@@ -7,6 +7,7 @@ import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Utilities / API methods for player heads.
|
||||
@@ -23,6 +24,11 @@ public class SkullUtils {
|
||||
*/
|
||||
private BiConsumer<SkullMeta, String> metaSetConsumer = null;
|
||||
|
||||
/**
|
||||
* The meta get function.
|
||||
*/
|
||||
private Function<SkullMeta, String> metaGetConsumer = null;
|
||||
|
||||
/**
|
||||
* Set the texture of a skull from base64.
|
||||
*
|
||||
@@ -37,16 +43,32 @@ public class SkullUtils {
|
||||
metaSetConsumer.accept(meta, base64);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the texture of a skull - in base64.
|
||||
*
|
||||
* @param meta The meta to modify.
|
||||
* @return The texture.
|
||||
*/
|
||||
public String getSkullTexture(@NotNull final SkullMeta meta) {
|
||||
Validate.isTrue(initialized, "Must be initialized!");
|
||||
Validate.notNull(metaGetConsumer, "Must be initialized!");
|
||||
|
||||
return metaGetConsumer.apply(meta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the skull texture function.
|
||||
*
|
||||
* @param function The function.
|
||||
* @param function The function.
|
||||
* @param function2 Get function.
|
||||
*/
|
||||
@ApiStatus.Internal
|
||||
public void initialize(@NotNull final BiConsumer<SkullMeta, String> function) {
|
||||
public void initialize(@NotNull final BiConsumer<SkullMeta, String> function,
|
||||
@NotNull final Function<SkullMeta, String> function2) {
|
||||
Validate.isTrue(!initialized, "Already initialized!");
|
||||
|
||||
metaSetConsumer = function;
|
||||
metaGetConsumer = function2;
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,43 @@
|
||||
package com.willfp.eco.proxy.v1_16_R3
|
||||
|
||||
import com.mojang.authlib.GameProfile
|
||||
import com.mojang.authlib.properties.Property
|
||||
import org.bukkit.inventory.meta.SkullMeta
|
||||
import com.willfp.eco.proxy.SkullProxy
|
||||
import org.bukkit.inventory.meta.SkullMeta
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
import java.util.*
|
||||
|
||||
class Skull : SkullProxy {
|
||||
private lateinit var setProfile: Method
|
||||
private lateinit var profile: Field
|
||||
|
||||
override fun setSkullTexture(
|
||||
meta: SkullMeta,
|
||||
base64: String
|
||||
) {
|
||||
try {
|
||||
if (!this::setProfile.isInitialized) {
|
||||
setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java)
|
||||
setProfile.isAccessible = true
|
||||
}
|
||||
val uuid = UUID(
|
||||
base64.substring(base64.length - 20).hashCode().toLong(),
|
||||
base64.substring(base64.length - 10).hashCode().toLong()
|
||||
)
|
||||
val profile = GameProfile(uuid, "eco")
|
||||
profile.properties.put("textures", Property("textures", base64))
|
||||
setProfile.invoke(meta, profile)
|
||||
} catch (e: ReflectiveOperationException) {
|
||||
e.printStackTrace()
|
||||
if (!this::setProfile.isInitialized) {
|
||||
setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java)
|
||||
setProfile.isAccessible = true
|
||||
}
|
||||
val uuid = UUID(
|
||||
base64.substring(base64.length - 20).hashCode().toLong(),
|
||||
base64.substring(base64.length - 10).hashCode().toLong()
|
||||
)
|
||||
val profile = GameProfile(uuid, "eco")
|
||||
profile.properties.put("textures", Property("textures", base64))
|
||||
setProfile.invoke(meta, profile)
|
||||
}
|
||||
|
||||
override fun getSkullTexture(
|
||||
meta: SkullMeta
|
||||
): String? {
|
||||
if (!this::profile.isInitialized) {
|
||||
profile = meta.javaClass.getDeclaredField("profile")
|
||||
profile.isAccessible = true
|
||||
}
|
||||
val profile = profile[meta] as GameProfile?
|
||||
val property = profile?.properties?.get("textures") as Property?
|
||||
return property?.value
|
||||
}
|
||||
}
|
||||
@@ -4,30 +4,40 @@ import com.mojang.authlib.GameProfile
|
||||
import com.mojang.authlib.properties.Property
|
||||
import com.willfp.eco.proxy.SkullProxy
|
||||
import org.bukkit.inventory.meta.SkullMeta
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
import java.util.*
|
||||
|
||||
class Skull : SkullProxy {
|
||||
private lateinit var setProfile: Method
|
||||
private lateinit var profile: Field
|
||||
|
||||
override fun setSkullTexture(
|
||||
meta: SkullMeta,
|
||||
base64: String
|
||||
) {
|
||||
try {
|
||||
if (!this::setProfile.isInitialized) {
|
||||
setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java)
|
||||
setProfile.isAccessible = true
|
||||
}
|
||||
val uuid = UUID(
|
||||
base64.substring(base64.length - 20).hashCode().toLong(),
|
||||
base64.substring(base64.length - 10).hashCode().toLong()
|
||||
)
|
||||
val profile = GameProfile(uuid, "eco")
|
||||
profile.properties.put("textures", Property("textures", base64))
|
||||
setProfile.invoke(meta, profile)
|
||||
} catch (e: ReflectiveOperationException) {
|
||||
e.printStackTrace()
|
||||
if (!this::setProfile.isInitialized) {
|
||||
setProfile = meta.javaClass.getDeclaredMethod("setProfile", GameProfile::class.java)
|
||||
setProfile.isAccessible = true
|
||||
}
|
||||
val uuid = UUID(
|
||||
base64.substring(base64.length - 20).hashCode().toLong(),
|
||||
base64.substring(base64.length - 10).hashCode().toLong()
|
||||
)
|
||||
val profile = GameProfile(uuid, "eco")
|
||||
profile.properties.put("textures", Property("textures", base64))
|
||||
setProfile.invoke(meta, profile)
|
||||
}
|
||||
|
||||
override fun getSkullTexture(
|
||||
meta: SkullMeta
|
||||
): String? {
|
||||
if (!this::profile.isInitialized) {
|
||||
profile = meta.javaClass.getDeclaredField("profile")
|
||||
profile.isAccessible = true
|
||||
}
|
||||
val profile = profile[meta] as GameProfile?
|
||||
val property = profile?.properties?.get("textures") as Property?
|
||||
return property?.value
|
||||
}
|
||||
}
|
||||
@@ -46,7 +46,10 @@ abstract class EcoSpigotPlugin : EcoPlugin(
|
||||
Display.setFinalizeKey(namespacedKeyFactory.create("finalized"))
|
||||
|
||||
val skullProxy = getProxy(SkullProxy::class.java)
|
||||
SkullUtils.initialize { meta: SkullMeta, base64: String -> skullProxy.setSkullTexture(meta, base64) }
|
||||
SkullUtils.initialize(
|
||||
{ meta: SkullMeta, base64: String -> skullProxy.setSkullTexture(meta, base64) },
|
||||
{ meta: SkullMeta -> skullProxy.getSkullTexture(meta) }
|
||||
)
|
||||
|
||||
val blockBreakProxy = getProxy(BlockBreakProxy::class.java)
|
||||
BlockUtils.initialize { player: Player, block: Block -> blockBreakProxy.breakBlock(player, block) }
|
||||
|
||||
@@ -8,4 +8,8 @@ interface SkullProxy : AbstractProxy {
|
||||
meta: SkullMeta,
|
||||
base64: String
|
||||
)
|
||||
|
||||
fun getSkullTexture(
|
||||
meta: SkullMeta
|
||||
): String?
|
||||
}
|
||||
Reference in New Issue
Block a user