diff --git a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java index dca134c01e..4c603fd063 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/Denizen.java +++ b/plugin/src/main/java/com/denizenscript/denizen/Denizen.java @@ -18,6 +18,7 @@ import com.denizenscript.denizen.tags.core.NPCTagBase; import com.denizenscript.denizen.tags.core.ServerTagBase; import com.denizenscript.denizen.utilities.*; +import com.denizenscript.denizen.utilities.blocks.FullBlockData; import com.denizenscript.denizen.utilities.command.*; import com.denizenscript.denizen.utilities.command.manager.CommandManager; import com.denizenscript.denizen.utilities.command.manager.Injector; @@ -371,6 +372,7 @@ else if (javaVersion.startsWith("17")) { exCommand.enableFor(getCommand("ex")); ExSustainedCommandHandler exsCommand = new ExSustainedCommandHandler(); exsCommand.enableFor(getCommand("exs")); + FullBlockData.init(); // Load script files without processing. DenizenCore.preloadScripts(); // Load the saves.yml into memory diff --git a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/InventoryScriptContainer.java b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/InventoryScriptContainer.java index f2a3490af6..695c70ee45 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/InventoryScriptContainer.java +++ b/plugin/src/main/java/com/denizenscript/denizen/scripts/containers/core/InventoryScriptContainer.java @@ -53,7 +53,7 @@ public class InventoryScriptContainer extends ScriptContainer { // inventory: inventory type // // # The title can be anything you wish. Use color tags to make colored titles. - // # Note that titles only work for some inventory types, including CHEST, DISPENSER, FURNACE, ENCHANTING, and HOPPER. + // # Note that titles only work for some inventory types, including ANVIL, CHEST, DISPENSER, FURNACE, ENCHANTING, HOPPER, WORKBENCH // # | MOST inventory scripts should have this key! // title: custom title // diff --git a/plugin/src/main/java/com/denizenscript/denizen/utilities/blocks/FullBlockData.java b/plugin/src/main/java/com/denizenscript/denizen/utilities/blocks/FullBlockData.java index 10e4484fa1..c643d7fd10 100644 --- a/plugin/src/main/java/com/denizenscript/denizen/utilities/blocks/FullBlockData.java +++ b/plugin/src/main/java/com/denizenscript/denizen/utilities/blocks/FullBlockData.java @@ -3,22 +3,68 @@ import com.denizenscript.denizen.nms.NMSHandler; import com.denizenscript.denizen.nms.util.jnbt.CompoundTag; import com.denizenscript.denizen.objects.LocationTag; +import com.denizenscript.denizen.utilities.debugging.Debug; import com.denizenscript.denizencore.flags.MapTagBasedFlagTracker; import com.denizenscript.denizencore.objects.ObjectTag; import com.denizenscript.denizencore.objects.core.MapTag; import com.denizenscript.denizencore.utilities.CoreUtilities; import com.denizenscript.denizencore.utilities.text.StringHolder; import org.bukkit.Axis; +import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.data.*; import org.bukkit.block.data.type.RedstoneWire; import org.bukkit.block.data.type.Wall; +import java.lang.reflect.Method; +import java.util.HashMap; +import java.util.HashSet; import java.util.Map; public class FullBlockData { + public static void init() { + HashSet> classesHandled = new HashSet<>(); + for (Material material : Material.values()) { + if (!material.isBlock() || material.isLegacy()) { + continue; + } + BlockData data = material.createBlockData(); + if (classesHandled.add(data.getClass())) { + initBlockDataClass(data); + } + } + } + + /** Trigger a bunch of pointless block data changes, to cause the enum class cache CraftBlockData.ENUM_VALUES to be filled in, thus making it probably safe for async usage. */ + private static void initBlockDataClass(BlockData data) { + try { + Class dataClass = data.getClass(); + HashMap setMethods = new HashMap<>(); + for (Method m : dataClass.getMethods()) { + if (m.getName().startsWith("set") && m.getParameterCount() == 1 && m.getReturnType() == void.class) { + setMethods.put(m.getName(), m); + } + } + for (Method m : dataClass.getMethods()) { + if (m.getName().startsWith("get") && m.getParameterCount() == 0 && m.getReturnType().isEnum()) { + Method setter = setMethods.get("set" + m.getName().substring("get".length())); + if (setter != null && setter.getParameterTypes()[0] == m.getReturnType()) { + setter.setAccessible(true); + m.setAccessible(true); + Object curVal = m.invoke(data); + setter.invoke(data, curVal); + } + } + } + } + catch (Throwable ex) { + Debug.echoError("Errored while trying to pre-load BlockData class '" + data.getClass().getName() + "'"); + Debug.echoError(ex); + } + } + public FullBlockData(Block block, boolean copyFlags) { this(block); if (copyFlags) {