From b0514d475fadce4e3eaf1e20fa758677ef1620db Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sun, 27 Apr 2025 02:49:30 +0800 Subject: [PATCH 1/2] =?UTF-8?q?skript=E5=85=BC=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BukkitCompatibilityManager.java | 27 ++--- .../compatibility/skript/SkriptHook.java | 12 +- .../skript/clazz/CraftEngineClasses.java | 55 +++++++++ .../skript/condition/CondIsCustomItem.java | 41 +++++++ .../skript/effect/EffRemoveFurniture.java | 3 - .../skript/event/EvtCustomBlock.java | 24 ++-- .../skript/event/EvtCustomClick.java | 112 ++++++++++++++++++ .../skript/event/EvtCustomFurniture.java | 58 +++++++++ .../expression/ExprBlockCustomBlockID.java | 2 +- .../expression/ExprBlockCustomBlockState.java | 2 +- .../skript/expression/ExprCustomItem.java | 56 +++++++++ .../expression/ExprEntityFurnitureID.java | 8 +- .../expression/ExprItemCustomItemID.java | 65 ++++++++++ .../api/event/CustomBlockInteractEvent.java | 13 +- .../bukkit/item/ItemEventListener.java | 3 +- .../plugin/injector/BukkitInjector.java | 23 +++- .../core/block/BlockStateHolder.java | 7 +- .../core/block/BlockStateMatcher.java | 108 +++++++++++++++++ .../core/block/UnsafeBlockStateMatcher.java | 98 +++++++++++++++ .../core/block/properties/Property.java | 5 + .../momirealms/craftengine/core/util/Key.java | 3 +- 21 files changed, 671 insertions(+), 54 deletions(-) create mode 100644 bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/condition/CondIsCustomItem.java create mode 100644 bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomClick.java create mode 100644 bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomFurniture.java create mode 100644 bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprCustomItem.java create mode 100644 bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprItemCustomItemID.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/block/BlockStateMatcher.java create mode 100644 core/src/main/java/net/momirealms/craftengine/core/block/UnsafeBlockStateMatcher.java diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java index 40143b6e8..4de975ecd 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/BukkitCompatibilityManager.java @@ -15,7 +15,6 @@ import net.momirealms.craftengine.bukkit.compatibility.viaversion.ViaVersionUtil import net.momirealms.craftengine.bukkit.compatibility.worldedit.WorldEditBlockRegister; import net.momirealms.craftengine.bukkit.font.BukkitFontManager; import net.momirealms.craftengine.bukkit.item.BukkitItemManager; -import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.core.entity.furniture.AbstractExternalModel; import net.momirealms.craftengine.core.entity.player.Player; @@ -25,7 +24,6 @@ import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.WorldManager; import org.bukkit.Bukkit; import org.bukkit.plugin.Plugin; -import org.bukkit.scheduler.BukkitTask; import java.util.UUID; @@ -55,18 +53,19 @@ public class BukkitCompatibilityManager implements CompatibilityManager { SkriptHook.register(); logHook("Skript"); Plugin skriptPlugin = getPlugin("Skript"); - for (BukkitTask task : Bukkit.getScheduler().getPendingTasks()) { - if (task.getOwner() == skriptPlugin) { - task.cancel(); - if (VersionHelper.isFolia()) { - Bukkit.getGlobalRegionScheduler().run(skriptPlugin, (t) -> { - FastNMS.INSTANCE.getBukkitTaskRunnable(task).run(); - }); - } else { - Bukkit.getScheduler().runTask(skriptPlugin, FastNMS.INSTANCE.getBukkitTaskRunnable(task)); - } - } - } + // This can cause bugs, needs to find a better way +// for (BukkitTask task : Bukkit.getScheduler().getPendingTasks()) { +// if (task.getOwner() == skriptPlugin) { +// task.cancel(); +// if (VersionHelper.isFolia()) { +// Bukkit.getGlobalRegionScheduler().run(skriptPlugin, (t) -> { +// FastNMS.INSTANCE.getBukkitTaskRunnable(task).run(); +// }); +// } else { +// Bukkit.getScheduler().runTask(skriptPlugin, FastNMS.INSTANCE.getBukkitTaskRunnable(task)); +// } +// } +// } } } diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/SkriptHook.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/SkriptHook.java index 4318e2f29..3e010e30c 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/SkriptHook.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/SkriptHook.java @@ -2,24 +2,30 @@ package net.momirealms.craftengine.bukkit.compatibility.skript; import net.momirealms.craftengine.bukkit.compatibility.skript.clazz.CraftEngineClasses; import net.momirealms.craftengine.bukkit.compatibility.skript.condition.CondIsCustomBlock; +import net.momirealms.craftengine.bukkit.compatibility.skript.condition.CondIsCustomItem; import net.momirealms.craftengine.bukkit.compatibility.skript.condition.CondIsFurniture; import net.momirealms.craftengine.bukkit.compatibility.skript.effect.EffPlaceCustomBlock; import net.momirealms.craftengine.bukkit.compatibility.skript.effect.EffPlaceFurniture; import net.momirealms.craftengine.bukkit.compatibility.skript.effect.EffRemoveFurniture; import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomBlock; -import net.momirealms.craftengine.bukkit.compatibility.skript.expression.ExprBlockCustomBlockID; -import net.momirealms.craftengine.bukkit.compatibility.skript.expression.ExprBlockCustomBlockState; -import net.momirealms.craftengine.bukkit.compatibility.skript.expression.ExprEntityFurnitureID; +import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomClick; +import net.momirealms.craftengine.bukkit.compatibility.skript.event.EvtCustomFurniture; +import net.momirealms.craftengine.bukkit.compatibility.skript.expression.*; public class SkriptHook { public static void register() { CraftEngineClasses.register(); EvtCustomBlock.register(); + EvtCustomFurniture.register(); + EvtCustomClick.register(); CondIsCustomBlock.register(); CondIsFurniture.register(); + CondIsCustomItem.register(); ExprBlockCustomBlockID.register(); + ExprItemCustomItemID.register(); ExprBlockCustomBlockState.register(); + ExprCustomItem.register(); ExprEntityFurnitureID.register(); EffPlaceCustomBlock.register(); EffPlaceFurniture.register(); diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/clazz/CraftEngineClasses.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/clazz/CraftEngineClasses.java index bae36a43d..97579439a 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/clazz/CraftEngineClasses.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/clazz/CraftEngineClasses.java @@ -8,6 +8,7 @@ import ch.njol.skript.registrations.Classes; import ch.njol.yggdrasil.Fields; import net.momirealms.craftengine.core.block.BlockStateParser; import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.UnsafeBlockStateMatcher; import org.jetbrains.annotations.Nullable; import java.io.StreamCorruptedException; @@ -68,5 +69,59 @@ public class CraftEngineClasses { } }) ); + + Classes.registerClass(new ClassInfo<>(UnsafeBlockStateMatcher.class, "unsafeblockstatematcher") + .user("unsafe block state matcher") + .name("Unsafe Block State Matcher") + .serializer(new Serializer<>() { + @Override + public Fields serialize(UnsafeBlockStateMatcher o) { + Fields f = new Fields(); + f.putObject("unsafeblockstatematcher", o.toString()); + return f; + } + + @Override + public void deserialize(UnsafeBlockStateMatcher o, Fields f) { + } + + @Override + public UnsafeBlockStateMatcher deserialize(Fields f) throws StreamCorruptedException { + String data = f.getObject("unsafeblockstatematcher", String.class); + assert data != null; + try { + return UnsafeBlockStateMatcher.deserialize(data); + } catch (IllegalArgumentException ex) { + throw new StreamCorruptedException("Invalid block matcher: " + data); + } + } + + @Override + public boolean mustSyncDeserialization() { + return true; + } + + @Override + protected boolean canBeInstantiated() { + return false; + } + }) + .parser(new Parser<>() { + @Override + public String toString(UnsafeBlockStateMatcher o, int flags) { + return o.toString(); + } + + @Override + public String toVariableNameString(UnsafeBlockStateMatcher o) { + return "unsafeblockstatematcher:" + o.toString(); + } + + @Override + public @Nullable UnsafeBlockStateMatcher parse(String s, ParseContext context) { + return UnsafeBlockStateMatcher.deserialize(s); + } + }) + ); } } diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/condition/CondIsCustomItem.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/condition/CondIsCustomItem.java new file mode 100644 index 000000000..b293e710f --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/condition/CondIsCustomItem.java @@ -0,0 +1,41 @@ +package net.momirealms.craftengine.bukkit.compatibility.skript.condition; + +import ch.njol.skript.Skript; +import ch.njol.skript.conditions.base.PropertyCondition; +import ch.njol.skript.lang.Condition; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.SkriptParser; +import ch.njol.util.Kleenean; +import net.momirealms.craftengine.bukkit.api.CraftEngineItems; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; + +public class CondIsCustomItem extends Condition { + + public static void register() { + Skript.registerCondition(CondIsCustomItem.class, + "%itemstacks% (is|are) custom item(s)", + "%itemstacks% (is|are)(n't| not) custom item(s)"); + } + + private Expression items; + + @Override + public boolean check(Event event) { + return items.check(event, CraftEngineItems::isCustomItem, isNegated()); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return PropertyCondition.toString(this, PropertyCondition.PropertyType.BE, event, debug, items, "itemstack"); + } + + @SuppressWarnings("unchecked") + @Override + public boolean init(Expression[] expressions, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) { + items = (Expression) expressions[0]; + setNegated(matchedPattern > 1); + return true; + } +} diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java index 7458e21c8..750dd937c 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/effect/EffRemoveFurniture.java @@ -4,12 +4,9 @@ import ch.njol.skript.Skript; import ch.njol.skript.lang.Effect; import ch.njol.skript.lang.Expression; import ch.njol.skript.lang.SkriptParser; -import ch.njol.skript.util.Direction; import ch.njol.util.Kleenean; import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture; import net.momirealms.craftengine.bukkit.entity.furniture.LoadedFurniture; -import net.momirealms.craftengine.core.util.Key; -import org.bukkit.Location; import org.bukkit.entity.Entity; import org.bukkit.event.Event; import org.jetbrains.annotations.Nullable; diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomBlock.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomBlock.java index 8c7febf4f..e5510c23d 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomBlock.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomBlock.java @@ -4,10 +4,11 @@ import ch.njol.skript.Skript; import ch.njol.skript.lang.Literal; import ch.njol.skript.lang.SkriptEvent; import ch.njol.skript.lang.SkriptParser; -import ch.njol.util.StringUtils; import net.momirealms.craftengine.bukkit.api.event.CustomBlockBreakEvent; import net.momirealms.craftengine.bukkit.api.event.CustomBlockPlaceEvent; import net.momirealms.craftengine.bukkit.util.BlockStateUtils; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.UnsafeBlockStateMatcher; import net.momirealms.craftengine.core.entity.player.InteractionHand; import org.bukkit.event.Event; import org.jetbrains.annotations.Nullable; @@ -18,21 +19,21 @@ import java.util.Arrays; public class EvtCustomBlock extends SkriptEvent { public static void register() { - Skript.registerEvent("Break Custom Block", EvtCustomBlock.class, CustomBlockBreakEvent.class, "[customblock] (break[ing]|1¦min(e|ing)) [[of] %-strings%]") + Skript.registerEvent("Break Custom Block", EvtCustomBlock.class, CustomBlockBreakEvent.class, "(break[ing]|1¦min(e|ing)) [[of] %-unsafeblockstatematchers%]") .description("Called when a custom block is broken by a player. If you use 'on mine', only events where the broken block dropped something will call the trigger."); - Skript.registerEvent("Place Custom Block", EvtCustomBlock.class, CustomBlockPlaceEvent.class, "[customblock] (plac(e|ing)|build[ing]) [[of] %-strings%]") + Skript.registerEvent("Place Custom Block", EvtCustomBlock.class, CustomBlockPlaceEvent.class, "(plac(e|ing)|build[ing]) [[of] %-unsafeblockstatematchers%]") .description("Called when a player places a custom block."); } @Nullable - private Literal blocks; - private String[] blockArray; + private Literal blocks; + private UnsafeBlockStateMatcher[] blockArray; private boolean mine = false; @Override public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parser) { if (args[0] != null) { - blocks = ((Literal) args[0]); + blocks = ((Literal) args[0]); blockArray = blocks.getAll(); } mine = parser.mark == 1; @@ -49,19 +50,16 @@ public class EvtCustomBlock extends SkriptEvent { if (blocks == null) return true; - String blockType; - String blockState; + ImmutableBlockState state; if (event instanceof CustomBlockBreakEvent customBlockBreakEvent) { - blockType = customBlockBreakEvent.customBlock().id().toString(); - blockState = customBlockBreakEvent.blockState().toString(); + state = customBlockBreakEvent.blockState(); } else if (event instanceof CustomBlockPlaceEvent customBlockPlaceEvent) { - blockType = customBlockPlaceEvent.customBlock().id().toString(); - blockState = customBlockPlaceEvent.blockState().toString(); + state = customBlockPlaceEvent.blockState(); } else { return false; } - return Arrays.stream(blockArray).anyMatch(block -> StringUtils.equals(blockType, block, true) || StringUtils.equals(blockState, block, true)); + return Arrays.stream(blockArray).anyMatch(block -> block.matches(state)); } @Override diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomClick.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomClick.java new file mode 100644 index 000000000..a2a162a11 --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomClick.java @@ -0,0 +1,112 @@ +package net.momirealms.craftengine.bukkit.compatibility.skript.event; + +import ch.njol.skript.Skript; +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.bukkitutil.ClickEventTracker; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser; +import net.momirealms.craftengine.bukkit.api.event.CustomBlockInteractEvent; +import net.momirealms.craftengine.bukkit.api.event.FurnitureInteractEvent; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.UnsafeBlockStateMatcher; +import net.momirealms.craftengine.core.entity.player.InteractionHand; +import org.bukkit.event.Event; +import org.bukkit.inventory.EquipmentSlot; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Predicate; + +public class EvtCustomClick extends SkriptEvent { + + private final static int RIGHT = 1, LEFT = 2, ANY = RIGHT | LEFT; + public final static ClickEventTracker interactTracker = new ClickEventTracker(Skript.getInstance()); + + public static void register() { + Skript.registerEvent("Interact Custom Block Furniture", EvtCustomClick.class, new Class[]{CustomBlockInteractEvent.class, FurnitureInteractEvent.class}, + "[(" + RIGHT + ":right|" + LEFT + ":left)(| |-)][mouse(| |-)]click[ing] [on %-unsafeblockstatematchers/strings%] [(with|using|holding) %-itemtype%]", + "[(" + RIGHT + ":right|" + LEFT + ":left)(| |-)][mouse(| |-)]click[ing] (with|using|holding) %itemtype% on %unsafeblockstatematchers/strings%"); + } + + private @Nullable Literal type; + private @Nullable Literal tools; + private int click = ANY; + + @Override + public boolean check(Event event) { + ImmutableBlockState block; + String furnitureId; + if (event instanceof CustomBlockInteractEvent interactEvent) { + furnitureId = null; + CustomBlockInteractEvent.Action action = interactEvent.action(); + int click; + switch (action) { + case LEFT_CLICK -> click = LEFT; + case RIGHT_CLICK -> click = RIGHT; + default -> { + return false; + } + } + if ((this.click & click) == 0) + return false; + EquipmentSlot hand = interactEvent.hand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND; + if (!interactTracker.checkEvent(interactEvent.getPlayer(), interactEvent, hand)) { + return false; + } + block = interactEvent.blockState(); + } else if (event instanceof FurnitureInteractEvent interactEvent) { + furnitureId = interactEvent.furniture().id().toString(); + block = null; + if ((this.click & RIGHT) == 0) + return false; + } else { + return false; + } + + System.out.println(furnitureId); + + Predicate checker = itemType -> { + if (event instanceof CustomBlockInteractEvent event1) { + return itemType.isOfType(event1.item()); + } else if (event instanceof FurnitureInteractEvent event1) { + return itemType.isOfType(event1.player().getInventory().getItem(event1.hand() == InteractionHand.MAIN_HAND ? EquipmentSlot.HAND : EquipmentSlot.OFF_HAND)); + } else { + return false; + } + }; + + if (tools != null && !tools.check(event, checker)) + return false; + + if (type != null) { + return type.check(event, (Predicate) object -> { + if (object instanceof String id && furnitureId != null) { + return id.equals(furnitureId); + } else if (object instanceof UnsafeBlockStateMatcher matcher && block != null) { + return matcher.matches(block); + } + return false; + }); + } + return true; + } + + @SuppressWarnings("unchecked") + @Override + public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parseResult) { + click = parseResult.mark == 0 ? ANY : parseResult.mark; + type = args[matchedPattern]; + tools = (Literal) args[1 - matchedPattern]; + return true; + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return switch (click) { + case LEFT -> "left"; + case RIGHT -> "right"; + default -> ""; + } + "click" + (type != null ? " on " + type.toString(event, debug) : "") + + (tools != null ? " holding " + tools.toString(event, debug) : ""); + } +} diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomFurniture.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomFurniture.java new file mode 100644 index 000000000..081b72f85 --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomFurniture.java @@ -0,0 +1,58 @@ +package net.momirealms.craftengine.bukkit.compatibility.skript.event; + +import ch.njol.skript.Skript; +import ch.njol.skript.lang.Literal; +import ch.njol.skript.lang.SkriptEvent; +import ch.njol.skript.lang.SkriptParser; +import net.momirealms.craftengine.bukkit.api.event.FurnitureBreakEvent; +import net.momirealms.craftengine.bukkit.api.event.FurniturePlaceEvent; +import org.bukkit.event.Event; +import org.jetbrains.annotations.Nullable; + +import java.util.Arrays; + +@SuppressWarnings({"unchecked"}) +public class EvtCustomFurniture extends SkriptEvent { + + public static void register() { + Skript.registerEvent("Break Furniture", EvtCustomFurniture.class, FurnitureBreakEvent.class, "(break[ing]) [[of] %-strings%]") + .description("Called when a furniture is broken by a player."); + Skript.registerEvent("Place Furniture", EvtCustomFurniture.class, FurniturePlaceEvent.class, "(plac(e|ing)|build[ing]) [[of] %-strings%]") + .description("Called when a player places a furniture."); + } + + @Nullable + private Literal ids; + private String[] idArray; + + @Override + public boolean init(Literal[] args, int matchedPattern, SkriptParser.ParseResult parser) { + if (args[0] != null) { + ids = ((Literal) args[0]); + idArray = ids.getAll(); + } + return true; + } + + @Override + public boolean check(Event event) { + if (ids == null) + return true; + + String id; + if (event instanceof FurnitureBreakEvent e) { + id = e.furniture().id().toString(); + } else if (event instanceof FurniturePlaceEvent e) { + id = e.furniture().id().toString(); + } else { + return false; + } + + return Arrays.asList(idArray).contains(id); + } + + @Override + public String toString(@Nullable Event event, boolean debug) { + return "break/place" + (ids != null ? " of " + ids.toString(event, debug) : ""); + } +} diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprBlockCustomBlockID.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprBlockCustomBlockID.java index 391318bec..db116d731 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprBlockCustomBlockID.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprBlockCustomBlockID.java @@ -13,7 +13,7 @@ import java.util.Optional; public class ExprBlockCustomBlockID extends SimplePropertyExpression { public static void register() { - register(ExprBlockCustomBlockID.class, String.class, "block[ ]custom block id", "blocks/blockdata/customblockstates"); + register(ExprBlockCustomBlockID.class, String.class, "custom block id", "blocks/blockdata/customblockstates"); } @Override diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprBlockCustomBlockState.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprBlockCustomBlockState.java index 36865e7f0..04874c3c3 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprBlockCustomBlockState.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprBlockCustomBlockState.java @@ -10,7 +10,7 @@ import org.jetbrains.annotations.Nullable; public class ExprBlockCustomBlockState extends SimplePropertyExpression { public static void register() { - register(ExprBlockCustomBlockState.class, ImmutableBlockState.class, "block[ ]custom block state", "blocks/blockdata"); + register(ExprBlockCustomBlockState.class, ImmutableBlockState.class, "custom block[ ]state", "blocks/blockdata"); } @Override diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprCustomItem.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprCustomItem.java new file mode 100644 index 000000000..2c3557a47 --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprCustomItem.java @@ -0,0 +1,56 @@ +package net.momirealms.craftengine.bukkit.compatibility.skript.expression; + +import ch.njol.skript.Skript; +import ch.njol.skript.lang.Expression; +import ch.njol.skript.lang.ExpressionType; +import ch.njol.skript.lang.SkriptParser; +import ch.njol.skript.lang.util.SimpleExpression; +import ch.njol.util.Kleenean; +import net.momirealms.craftengine.bukkit.api.CraftEngineItems; +import net.momirealms.craftengine.core.item.ItemBuildContext; +import net.momirealms.craftengine.core.util.Key; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.Objects; + +public class ExprCustomItem extends SimpleExpression { + + public static void register() { + Skript.registerExpression(ExprCustomItem.class, ItemStack.class, ExpressionType.SIMPLE, "[(the|a)] custom item [with id] %string%"); + } + + private Expression itemId; + + @Override + @SuppressWarnings("unchecked") + public boolean init(Expression[] exprs, int matchedPattern, Kleenean isDelayed, SkriptParser.ParseResult parseResult) { + itemId = (Expression) exprs[0]; + return true; + } + + @Override + @Nullable + protected ItemStack[] get(Event e) { + String itemId = this.itemId.getSingle(e); + if (itemId == null) + return null; + return new ItemStack[] {Objects.requireNonNull(CraftEngineItems.byId(Key.of(itemId))).buildItemStack(ItemBuildContext.EMPTY)}; + } + + @Override + public boolean isSingle() { + return true; + } + + @Override + public Class getReturnType() { + return ItemStack.class; + } + + @Override + public String toString(@Nullable Event e, boolean debug) { + return "the custom item with id " + itemId.toString(e, debug); + } +} diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprEntityFurnitureID.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprEntityFurnitureID.java index cae8fea3f..f11a78ac1 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprEntityFurnitureID.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprEntityFurnitureID.java @@ -1,22 +1,16 @@ package net.momirealms.craftengine.bukkit.compatibility.skript.expression; import ch.njol.skript.expressions.base.SimplePropertyExpression; -import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks; import net.momirealms.craftengine.bukkit.api.CraftEngineFurniture; -import net.momirealms.craftengine.core.block.CustomBlock; -import net.momirealms.craftengine.core.block.ImmutableBlockState; -import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; import org.bukkit.entity.Entity; import org.jetbrains.annotations.Nullable; import java.util.Objects; -import java.util.Optional; public class ExprEntityFurnitureID extends SimplePropertyExpression { public static void register() { - register(ExprEntityFurnitureID.class, String.class, "entity[ ]furniture id", "entities"); + register(ExprEntityFurnitureID.class, String.class, "furniture id", "entities"); } @Override diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprItemCustomItemID.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprItemCustomItemID.java new file mode 100644 index 000000000..e9531c7b2 --- /dev/null +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/expression/ExprItemCustomItemID.java @@ -0,0 +1,65 @@ +package net.momirealms.craftengine.bukkit.compatibility.skript.expression; + +import ch.njol.skript.aliases.ItemType; +import ch.njol.skript.classes.Changer; +import ch.njol.skript.expressions.base.SimplePropertyExpression; +import ch.njol.util.coll.CollectionUtils; +import net.momirealms.craftengine.bukkit.api.CraftEngineItems; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.util.Key; +import org.bukkit.event.Event; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.Optional; + +public class ExprItemCustomItemID extends SimplePropertyExpression { + + public static void register() { + register(ExprItemCustomItemID.class, String.class, "custom item id", "itemstacks/itemtypes"); + } + + @Override + public @Nullable String convert(Object object) { + if (object instanceof ItemStack itemStack) + return Optional.ofNullable(CraftEngineItems.byItemStack(itemStack)).map(it -> it.id().toString()).orElse(null); + if (object instanceof ItemType itemType) { + ItemStack itemStack = new ItemStack(itemType.getMaterial()); + itemStack.setItemMeta(itemType.getItemMeta()); + return Optional.ofNullable(CraftEngineItems.byItemStack(itemStack)).map(it -> it.id().toString()).orElse(null); + } + return null; + } + + @Override + protected String getPropertyName() { + return "custom item id"; + } + + @Override + public Class getReturnType() { + return String.class; + } + + @Override + public Class[] acceptChange(Changer.ChangeMode mode) { + return CollectionUtils.array(String.class); + } + + @Override + public void change(Event e, @Nullable Object[] delta, Changer.ChangeMode mode) { + Key id = Key.of((String) delta[0]); + for (Object item : getExpr().getArray(e)) { + if (item instanceof ItemStack itemStack) { + Item item1 = BukkitItemManager.instance().wrap(itemStack); + Item item2 = BukkitItemManager.instance().createWrappedItem(id, null); + item1.merge(item2); + item1.load(); + } else if (item instanceof ItemType itemType) { + Item item2 = BukkitItemManager.instance().createWrappedItem(id, null); + itemType.setItemMeta(item2.load().getItemMeta()); + } + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/CustomBlockInteractEvent.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/CustomBlockInteractEvent.java index 71e55cb5d..f9c9eccf2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/CustomBlockInteractEvent.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/event/CustomBlockInteractEvent.java @@ -10,6 +10,8 @@ import org.bukkit.entity.Player; import org.bukkit.event.Cancellable; import org.bukkit.event.HandlerList; import org.bukkit.event.player.PlayerEvent; +import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.ApiStatus; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -24,6 +26,7 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable private final InteractionHand hand; private final Action action; private final BlockFace clickedFace; + private final ItemStack item; public CustomBlockInteractEvent(@NotNull Player player, @NotNull Location location, @@ -32,7 +35,8 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable @NotNull Block bukkitBlock, @NotNull BlockFace clickedFace, @NotNull InteractionHand hand, - @NotNull Action action) { + @NotNull Action action, + @Nullable ItemStack item) { super(player); this.customBlock = state.owner().value(); this.bukkitBlock = bukkitBlock; @@ -42,6 +46,7 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable this.hand = hand; this.action = action; this.clickedFace = clickedFace; + this.item = item; } @NotNull @@ -89,6 +94,12 @@ public class CustomBlockInteractEvent extends PlayerEvent implements Cancellable return this.state; } + @ApiStatus.Experimental + @NotNull + public ItemStack item() { + return this.item; + } + @NotNull public static HandlerList getHandlerList() { return HANDLER_LIST; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java index 27319d9ba..a23cf371a 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/ItemEventListener.java @@ -70,7 +70,8 @@ public class ItemEventListener implements Listener { block, event.getBlockFace(), event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND, - action.isRightClick() ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK + action.isRightClick() ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK, + event.getItem() ); if (EventUtils.fireAndCheckCancel(interactEvent)) { event.setCancelled(true); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java index 157345804..1b9b0bbf3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/injector/BukkitInjector.java @@ -368,11 +368,28 @@ public class BukkitInjector { } } - public synchronized static void injectLevelChunkSection(Object targetSection, CESection ceSection, CEWorld ceWorld, SectionPos pos) { +// public synchronized static void injectLevelChunkSection(Object targetSection, CESection ceSection, CEWorld ceWorld, SectionPos pos) { +// try { +// Object container = FastNMS.INSTANCE.field$LevelChunkSection$states(targetSection); +// if (!(container instanceof InjectedPalettedContainerHolder)) { +// InjectedPalettedContainerHolder injectedObject = FastNMS.INSTANCE.createInjectedPalettedContainerHolder(container); +// injectedObject.ceSection(ceSection); +// injectedObject.ceWorld(ceWorld); +// injectedObject.cePos(pos); +// Reflections.varHandle$PalettedContainer$data.setVolatile(injectedObject, Reflections.varHandle$PalettedContainer$data.get(container)); +// Reflections.field$LevelChunkSection$states.set(targetSection, injectedObject); +// } +// } catch (Exception e) { +// CraftEngine.instance().logger().severe("Failed to inject chunk section", e); +// } +// } + + public static void injectLevelChunkSection(Object targetSection, CESection ceSection, CEWorld ceWorld, SectionPos pos) { try { Object container = FastNMS.INSTANCE.field$LevelChunkSection$states(targetSection); - if (!(container instanceof InjectedPalettedContainerHolder)) { - InjectedPalettedContainerHolder injectedObject = FastNMS.INSTANCE.createInjectedPalettedContainerHolder(container); + if (!clazz$InjectedPalettedContainer.isInstance(container)) { + InjectedPalettedContainerHolder injectedObject = (InjectedPalettedContainerHolder) Reflections.UNSAFE.allocateInstance(clazz$InjectedPalettedContainer); + varHandle$InjectedPalettedContainer$target.set(injectedObject, container); injectedObject.ceSection(ceSection); injectedObject.ceWorld(ceWorld); injectedObject.cePos(pos); diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateHolder.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateHolder.java index feb5535cb..7d9c265b3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateHolder.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateHolder.java @@ -48,16 +48,11 @@ public class BlockStateHolder { return propertyMap.entrySet().stream() .map(entry -> { Property property = entry.getKey(); - return property.name() + "=" + formatValue(property, entry.getValue()); + return property.name() + "=" + Property.formatValue(property, entry.getValue()); }) .collect(Collectors.joining(",")); } - @SuppressWarnings("unchecked") - private static > String formatValue(Property property, Comparable value) { - return property.valueName((T) value); - } - public Collection> getProperties() { return Collections.unmodifiableSet(propertyMap.keySet()); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateMatcher.java b/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateMatcher.java new file mode 100644 index 000000000..3886220dc --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/block/BlockStateMatcher.java @@ -0,0 +1,108 @@ +package net.momirealms.craftengine.core.block; + +import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.registry.Holder; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.Pair; +import net.momirealms.craftengine.core.util.StringReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +public class BlockStateMatcher { + private final List, Comparable>> properties; + private final Key id; + + public BlockStateMatcher(Key id, List, Comparable>> properties) { + this.properties = properties; + this.id = id; + } + + public boolean matches(ImmutableBlockState state) { + if (!state.owner().value().id.equals(this.id)) { + return false; + } + for (Pair, Comparable> pair : this.properties) { + if (!state.get(pair.left()).equals(pair.right())) { + return false; + } + } + return true; + } + + @Override + public String toString() { + if (properties.isEmpty()) { + return id.toString(); + } + return id + "[" + getPropertiesAsString() + "]"; + } + + public String getPropertiesAsString() { + return properties.stream() + .map(entry -> { + Property property = entry.left(); + return property.name() + "=" + Property.formatValue(property, entry.right()); + }) + .collect(Collectors.joining(",")); + } + + @SuppressWarnings("DuplicatedCode") + @Nullable + public static BlockStateMatcher deserialize(@NotNull String data) { + StringReader reader = StringReader.simple(data); + String blockIdString = reader.readUnquotedString(); + if (reader.canRead() && reader.peek() == ':') { + reader.skip(); + blockIdString = blockIdString + ":" + reader.readUnquotedString(); + } + Optional> optional = BuiltInRegistries.BLOCK.get(Key.from(blockIdString)); + if (optional.isEmpty()) { + return null; + } + Holder holder = optional.get(); + List, Comparable>> properties = new ArrayList<>(); + if (reader.canRead() && reader.peek() == '[') { + reader.skip(); + while (reader.canRead()) { + reader.skipWhitespace(); + if (reader.peek() == ']') break; + String propertyName = reader.readUnquotedString(); + reader.skipWhitespace(); + if (!reader.canRead() || reader.peek() != '=') { + return null; + } + reader.skip(); + reader.skipWhitespace(); + String propertyValue = reader.readUnquotedString(); + Property property = holder.value().getProperty(propertyName); + if (property != null) { + Optional optionalValue = property.optional(propertyValue); + if (optionalValue.isEmpty()) { + return null; + } else { + properties.add(Pair.of(property, (Comparable) optionalValue.get())); + } + } else { + return null; + } + reader.skipWhitespace(); + if (reader.canRead() && reader.peek() == ',') { + reader.skip(); + } + } + reader.skipWhitespace(); + if (reader.canRead() && reader.peek() == ']') { + reader.skip(); + } else { + return null; + } + } + return new BlockStateMatcher(holder.value().id(), properties); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/UnsafeBlockStateMatcher.java b/core/src/main/java/net/momirealms/craftengine/core/block/UnsafeBlockStateMatcher.java new file mode 100644 index 000000000..00b9d4b49 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/block/UnsafeBlockStateMatcher.java @@ -0,0 +1,98 @@ +package net.momirealms.craftengine.core.block; + +import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.registry.BuiltInRegistries; +import net.momirealms.craftengine.core.registry.Holder; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.util.Pair; +import net.momirealms.craftengine.core.util.StringReader; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +public class UnsafeBlockStateMatcher { + private final List> matchers; + private final Key id; + + public UnsafeBlockStateMatcher(Key id, List> matchers) { + this.id = id; + this.matchers = matchers; + } + + public boolean matches(ImmutableBlockState state) { + if (!state.owner().value().id.equals(this.id)) { + return false; + } + CustomBlock customBlock = state.owner().value(); + for (Pair matcher : matchers) { + Property property = customBlock.getProperty(matcher.left()); + if (property == null) { + return false; + } + Comparable value = state.get(property); + String valueStr = Property.formatValue(property, value); + if (!matcher.right().equals(valueStr)) { + return false; + } + } + return true; + } + + @Override + public String toString() { + if (matchers.isEmpty()) { + return id.toString(); + } + return id + "[" + matchers.stream() + .map(entry -> entry.left() + "=" + entry.right()) + .collect(Collectors.joining(",")) + "]"; + } + + @SuppressWarnings("DuplicatedCode") + @Nullable + public static UnsafeBlockStateMatcher deserialize(@NotNull String data) { + StringReader reader = StringReader.simple(data); + String blockIdString = reader.readUnquotedString(); + if (reader.canRead() && reader.peek() == ':') { + reader.skip(); + blockIdString = blockIdString + ":" + reader.readUnquotedString(); + } + Optional> optional = BuiltInRegistries.BLOCK.get(Key.from(blockIdString)); + if (optional.isEmpty()) { + return null; + } + Holder holder = optional.get(); + List> properties = new ArrayList<>(); + if (reader.canRead() && reader.peek() == '[') { + reader.skip(); + while (reader.canRead()) { + reader.skipWhitespace(); + if (reader.peek() == ']') break; + String propertyName = reader.readUnquotedString(); + reader.skipWhitespace(); + if (!reader.canRead() || reader.peek() != '=') { + return null; + } + reader.skip(); + reader.skipWhitespace(); + String propertyValue = reader.readUnquotedString(); + properties.add(new Pair<>(propertyName, propertyValue)); + reader.skipWhitespace(); + if (reader.canRead() && reader.peek() == ',') { + reader.skip(); + } + } + reader.skipWhitespace(); + if (reader.canRead() && reader.peek() == ']') { + reader.skip(); + } else { + return null; + } + } + return new UnsafeBlockStateMatcher(holder.value().id(), properties); + } +} diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java b/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java index 83b45f7fb..a61d33e00 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/properties/Property.java @@ -162,4 +162,9 @@ public abstract class Property> { .map(it -> it.apply(property)) .orElse(((context, state) -> ImmutableBlockState.with(state, property, property.defaultValue()))); } + + @SuppressWarnings("unchecked") + public static > String formatValue(Property property, Comparable value) { + return property.valueName((T) value); + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/Key.java b/core/src/main/java/net/momirealms/craftengine/core/util/Key.java index bd0a211bc..f536fa5ba 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/Key.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/Key.java @@ -43,7 +43,8 @@ public record Key(String namespace, String value) { return false; } if (!(obj instanceof Key key)) return false; - return this.namespace.equals(key.namespace()) && this.value.equals(key.value()); + // 先比value命中率高 + return this.value.equals(key.value()) && this.namespace.equals(key.namespace()); } @Override From f2599c4b3bf662c8b30b558576303305394aead5 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Sun, 27 Apr 2025 02:55:26 +0800 Subject: [PATCH 2/2] 0.0.51 --- .../bukkit/compatibility/skript/event/EvtCustomClick.java | 2 -- gradle.properties | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomClick.java b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomClick.java index a2a162a11..68bcdb48b 100644 --- a/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomClick.java +++ b/bukkit/compatibility/src/main/java/net/momirealms/craftengine/bukkit/compatibility/skript/event/EvtCustomClick.java @@ -63,8 +63,6 @@ public class EvtCustomClick extends SkriptEvent { return false; } - System.out.println(furnitureId); - Predicate checker = itemType -> { if (event instanceof CustomBlockInteractEvent event1) { return itemType.isOfType(event1.item()); diff --git a/gradle.properties b/gradle.properties index 008212c9c..a38fd2bdd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1G # Project settings # Rule: [major update].[feature update].[bug fix] -project_version=0.0.51-beta.3 +project_version=0.0.51 config_version=30 lang_version=7 project_group=net.momirealms