diff --git a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/MinecartWatcher.java b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/MinecartWatcher.java index 01fa4468..b96eceb1 100644 --- a/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/MinecartWatcher.java +++ b/src/main/java/me/libraryaddict/disguise/disguisetypes/watchers/MinecartWatcher.java @@ -3,8 +3,11 @@ package me.libraryaddict.disguise.disguisetypes.watchers; import me.libraryaddict.disguise.disguisetypes.Disguise; import me.libraryaddict.disguise.disguisetypes.FlagWatcher; import me.libraryaddict.disguise.disguisetypes.MetaIndex; +import me.libraryaddict.disguise.utilities.reflection.NmsAddedIn; +import me.libraryaddict.disguise.utilities.reflection.NmsVersion; import me.libraryaddict.disguise.utilities.reflection.ReflectionManager; import org.bukkit.Material; +import org.bukkit.block.data.BlockData; import org.bukkit.inventory.ItemStack; public class MinecartWatcher extends FlagWatcher { @@ -13,6 +16,7 @@ public class MinecartWatcher extends FlagWatcher { super(disguise); } + @Deprecated public ItemStack getBlockInCart() { if (!hasValue(MetaIndex.MINECART_BLOCK)) { return new ItemStack(Material.AIR); @@ -21,6 +25,27 @@ public class MinecartWatcher extends FlagWatcher { return ReflectionManager.getItemStackByCombinedId(getData(MetaIndex.MINECART_BLOCK)); } + @Deprecated + public void setBlockInCart(ItemStack item) { + setData(MetaIndex.MINECART_BLOCK, ReflectionManager.getCombinedIdByItemStack(item)); + setData(MetaIndex.MINECART_BLOCK_VISIBLE, item != null && item.getType() != Material.AIR); + + sendData(MetaIndex.MINECART_BLOCK, MetaIndex.MINECART_BLOCK_VISIBLE); + } + + @NmsAddedIn(NmsVersion.v1_13) + public BlockData getBlockData() { + return ReflectionManager.getBlockDataByCombinedId(getData(MetaIndex.MINECART_BLOCK)); + } + + @NmsAddedIn(NmsVersion.v1_13) + public void setBlockData(BlockData data) { + setData(MetaIndex.MINECART_BLOCK, ReflectionManager.getCombinedIdByBlockData(data)); + setData(MetaIndex.MINECART_BLOCK_VISIBLE, data != null && data.getMaterial() != Material.AIR); + + sendData(MetaIndex.MINECART_BLOCK, MetaIndex.MINECART_BLOCK_VISIBLE); + } + @Deprecated public int getBlockYOffset() { return getData(MetaIndex.MINECART_BLOCK_Y); @@ -30,22 +55,15 @@ public class MinecartWatcher extends FlagWatcher { return getData(MetaIndex.MINECART_BLOCK_Y); } - public boolean isViewBlockInCart() { - return getData(MetaIndex.MINECART_BLOCK_VISIBLE); - } - - public void setBlockInCart(ItemStack item) { - setData(MetaIndex.MINECART_BLOCK, ReflectionManager.getCombinedIdByItemStack(item)); - setData(MetaIndex.MINECART_BLOCK_VISIBLE, item != null && item.getType() != Material.AIR); - - sendData(MetaIndex.MINECART_BLOCK, MetaIndex.MINECART_BLOCK_VISIBLE); - } - public void setBlockOffset(int i) { setData(MetaIndex.MINECART_BLOCK_Y, i); sendData(MetaIndex.MINECART_BLOCK_Y); } + public boolean isViewBlockInCart() { + return getData(MetaIndex.MINECART_BLOCK_VISIBLE); + } + public void setViewBlockInCart(boolean viewBlock) { setData(MetaIndex.MINECART_BLOCK_VISIBLE, viewBlock); sendData(MetaIndex.MINECART_BLOCK_VISIBLE); diff --git a/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java b/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java index d45e5a31..12561fa2 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/params/ParamInfoTypes.java @@ -79,7 +79,7 @@ public class ParamInfoTypes { "The different particles of Minecraft", Particle.values(), getMaterials())); paramInfos.add(new ParamInfoEnum(TropicalFish.Pattern.class, "Pattern", "Patterns of a tropical fish")); paramInfos.add(new ParamInfoBlockData(BlockData.class, "BlockData", - "The block data states, barrel[facing=north,open=false] as example")); + "The block data states, barrel[facing=north,open=false] as example", getMaterials())); } else { paramInfos.add(new ParamInfoEnum(Particle.class, "Particle", "The different particles of Minecraft")); } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/params/types/custom/ParamInfoBlockData.java b/src/main/java/me/libraryaddict/disguise/utilities/params/types/custom/ParamInfoBlockData.java index 8096b2cd..386eca66 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/params/types/custom/ParamInfoBlockData.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/params/types/custom/ParamInfoBlockData.java @@ -1,16 +1,57 @@ package me.libraryaddict.disguise.utilities.params.types.custom; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import me.libraryaddict.disguise.utilities.params.ParamInfo; import me.libraryaddict.disguise.utilities.parser.DisguiseParseException; +import me.libraryaddict.disguise.utilities.reflection.NmsVersion; import org.bukkit.Bukkit; +import org.bukkit.Material; import org.bukkit.block.data.BlockData; +import org.bukkit.block.data.type.Stairs; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.TimeUnit; /** * Created by libraryaddict on 12/08/2020. */ public class ParamInfoBlockData extends ParamInfo { - public ParamInfoBlockData(Class paramClass, String name, String description) { - super(paramClass, name, description); + private Material[] materials; + private Cache> blockDatas = CacheBuilder.newBuilder() + .expireAfterAccess(30, TimeUnit.MINUTES).maximumSize(20).build(); + + public ParamInfoBlockData(Class paramClass, String name, String description, Material[] possibleValues) { + super(paramClass, name, "BlockData[State=Something]", description); + + materials = Arrays.stream(possibleValues).filter(m -> { + switch (m) { + case CHEST: + case TRAPPED_CHEST: + return false; + default: + break; + } + + if (!m.isBlock()) { + return false; + } else if (NmsVersion.v1_13.isSupported()) { + return true; + } + + switch (m) { + case CAKE: + case FLOWER_POT: + case CAULDRON: + case BREWING_STAND: + return false; + default: + return true; + } + }).toArray(Material[]::new); } @Override @@ -35,4 +76,49 @@ public class ParamInfoBlockData extends ParamInfo { public boolean isParam(Class paramClass) { return getParamClass().isAssignableFrom(paramClass); } + + private Material getMaterial(String name) { + return Material.matchMaterial(name, false); + } + + public Set getEnums(String tabComplete) { + String s = tabComplete.toLowerCase(); + HashSet returns = new HashSet<>(); + + if (s.matches("[a-z_:]+\\[.*")) { + s = s.substring(0, s.indexOf("[")); + } else if (tabComplete.matches("[a-z:_]+")) { + for (Material m : materials) { + if (m.isLegacy() || !m.isBlock()) { + continue; + } + + if (!m.name().toLowerCase().startsWith(s) && !m.getKey().toString().startsWith(s)) { + continue; + } + + if (m.name().toLowerCase().startsWith(s)) { + returns.add(m.name()); + } else { + returns.add(m.getKey().toString()); + } + } + } else { + return returns; + } + + Material mat = getMaterial(s); + + if (mat == null) { + return returns; + } + + // TODO Maybe auto complete blockstate states + // Then again, it means I need to get the block states on a new IBlockData + // Then call toBukkit with the block states then turn them into strings + // Then handle the edge cases where they are not enums.. Idk, I think I'm going to ignore this. + // No one cares about auto completion of this either + + return returns; + } } diff --git a/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java b/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java index 893f1f45..d2d6663d 100644 --- a/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java +++ b/src/main/java/me/libraryaddict/disguise/utilities/reflection/ReflectionManager.java @@ -1505,6 +1505,25 @@ public class ReflectionManager { return 0; } + public static BlockData getBlockDataByCombinedId(int id) { + try { + Method idMethod = getNmsMethod("Block", "getByCombinedId", int.class); + Object iBlockData = idMethod.invoke(null, id); + Class iBlockClass = getNmsClass("IBlockData"); + + Method getBlock = getNmsMethod(iBlockClass, "getBlock"); + Object block = getBlock.invoke(iBlockData); + + return (BlockData) getCraftMethod("block.data.type.CraftBlockData", "fromData", iBlockClass) + .invoke(null, block); + } + catch (Exception ex) { + ex.printStackTrace(); + } + + return null; + } + public static ItemStack getItemStackByCombinedId(int id) { try { Method idMethod = getNmsMethod("Block", "getByCombinedId", int.class);