From 80ca2d18d9bbfa24875b02f4ac282d80f012a4f0 Mon Sep 17 00:00:00 2001 From: XiaoMoMi Date: Fri, 14 Feb 2025 18:34:41 +0800 Subject: [PATCH] Implement Strippable Block --- .../default/configuration/palm_tree.yml | 4 +- .../bukkit/item/BukkitCustomItem.java | 3 +- .../bukkit/item/BukkitItemManager.java | 40 ++++ .../bukkit/item/DebugStickListener.java | 127 +++++++++++++ .../bukkit/item/ItemEventListener.java | 178 +++++------------- .../bukkit/item/behavior/AxeItemBehavior.java | 98 ++++++++++ .../item/behavior/BukkitItemBehaviors.java | 2 + .../item/factory/BukkitItemFactory.java | 5 + .../plugin/network/PacketConsumers.java | 2 +- .../plugin/user/BukkitServerPlayer.java | 4 +- .../bukkit/util/BlockStateUtils.java | 15 +- .../craftengine/bukkit/util/ItemTags.java | 3 + .../craftengine/bukkit/util/Reflections.java | 43 +++++ .../core/block/ImmutableBlockState.java | 2 +- .../core/entity/player/Player.java | 2 + .../craftengine/core/item/AbstractItem.java | 16 ++ .../craftengine/core/item/CustomItem.java | 2 + .../craftengine/core/item/Item.java | 7 + .../craftengine/core/item/ItemFactory.java | 2 + .../craftengine/core/item/ItemKeys.java | 6 + .../craftengine/core/item/ItemManager.java | 3 + .../core/item/behavior/ItemBehavior.java | 4 +- 22 files changed, 426 insertions(+), 142 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/DebugStickListener.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/AxeItemBehavior.java diff --git a/bukkit-loader/src/main/resources/resources/default/configuration/palm_tree.yml b/bukkit-loader/src/main/resources/resources/default/configuration/palm_tree.yml index 0bb316516..2538029f4 100644 --- a/bukkit-loader/src/main/resources/resources/default/configuration/palm_tree.yml +++ b/bukkit-loader/src/main/resources/resources/default/configuration/palm_tree.yml @@ -54,7 +54,7 @@ blocks: loot: template: loot_table:normal arguments: - item: default:palm_log + item: default:stripped_palm_log settings: template: block_settings:log overrides: @@ -107,7 +107,7 @@ blocks: loot: template: loot_table:normal arguments: - item: default:palm_wood + item: default:stripped_palm_wood settings: template: block_settings:log overrides: diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java index 287e6f2ad..f325f5729 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitCustomItem.java @@ -11,6 +11,7 @@ import net.momirealms.craftengine.core.item.modifier.ItemModifier; import net.momirealms.craftengine.core.util.Key; import org.bukkit.Material; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; @@ -70,7 +71,7 @@ public class BukkitCustomItem implements CustomItem { } @Override - public ItemBehavior behavior() { + public @NotNull ItemBehavior behavior() { return this.behavior; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java index ea468b1b6..b86bf063e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/BukkitItemManager.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.bukkit.item; +import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior; import net.momirealms.craftengine.bukkit.item.factory.BukkitItemFactory; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.util.ItemUtils; @@ -7,6 +8,7 @@ import net.momirealms.craftengine.bukkit.util.MaterialUtils; import net.momirealms.craftengine.bukkit.util.Reflections; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.*; +import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.behavior.ItemBehaviors; import net.momirealms.craftengine.core.item.modifier.CustomModelDataModifier; import net.momirealms.craftengine.core.item.modifier.IdModifier; @@ -35,12 +37,25 @@ import java.nio.file.Path; import java.util.*; public class BukkitItemManager extends AbstractItemManager { + private static final Map VANILLA_ITEM_EXTRA_BEHAVIORS = new HashMap<>(); + + static { + registerVanillaItemExtraBehavior(AxeItemBehavior.INSTANCE, ItemKeys.WOODEN_AXE, ItemKeys.STONE_AXE, ItemKeys.IRON_AXE, ItemKeys.GOLDEN_AXE, ItemKeys.DIAMOND_AXE, ItemKeys.NETHERITE_AXE); + } + + private static void registerVanillaItemExtraBehavior(ItemBehavior behavior, Key... items) { + for (Key key : items) { + VANILLA_ITEM_EXTRA_BEHAVIORS.put(key, behavior); + } + } + private static BukkitItemManager instance; private final BukkitItemFactory factory; private final Map> legacyOverrides; private final Map> modernOverrides; private final BukkitCraftEngine plugin; private final ItemEventListener itemEventListener; + private final DebugStickListener debugStickListener; private final Map>> vanillaItemTags; private final Map>> customItemTags; private final Map> cmdConflictChecker; @@ -55,6 +70,7 @@ public class BukkitItemManager extends AbstractItemManager { this.customItemTags = new HashMap<>(); this.cmdConflictChecker = new HashMap<>(); this.itemEventListener = new ItemEventListener(plugin); + this.debugStickListener = new DebugStickListener(plugin); this.registerAllVanillaItems(); instance = this; } @@ -100,6 +116,7 @@ public class BukkitItemManager extends AbstractItemManager { public void load() { super.load(); Bukkit.getPluginManager().registerEvents(this.itemEventListener, plugin.bootstrap()); + Bukkit.getPluginManager().registerEvents(this.debugStickListener, plugin.bootstrap()); } @Override @@ -109,6 +126,7 @@ public class BukkitItemManager extends AbstractItemManager { this.modernOverrides.clear(); this.customItemTags.clear(); HandlerList.unregisterAll(this.itemEventListener); + HandlerList.unregisterAll(this.debugStickListener); this.cmdConflictChecker.clear(); } @@ -168,6 +186,28 @@ public class BukkitItemManager extends AbstractItemManager { return wrapped.id(); } + @Override + public Optional> getItemBehavior(Key key) { + Optional> customItemOptional = getCustomItem(key); + if (customItemOptional.isPresent()) { + CustomItem customItem = customItemOptional.get(); + Key vanillaMaterial = customItem.material(); + ItemBehavior behavior = VANILLA_ITEM_EXTRA_BEHAVIORS.get(vanillaMaterial); + if (behavior != null) { + return Optional.of(List.of(behavior, customItem.behavior())); + } else { + return Optional.of(List.of(customItem.behavior())); + } + } else { + ItemBehavior behavior = VANILLA_ITEM_EXTRA_BEHAVIORS.get(key); + if (behavior != null) { + return Optional.of(List.of(behavior)); + } else { + return Optional.empty(); + } + } + } + @Override public Collection items() { return new ArrayList<>(customItems.keySet()); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/DebugStickListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/DebugStickListener.java new file mode 100644 index 000000000..a295de28b --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/DebugStickListener.java @@ -0,0 +1,127 @@ +package net.momirealms.craftengine.bukkit.item; + +import net.kyori.adventure.text.Component; +import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks; +import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; +import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; +import net.momirealms.craftengine.bukkit.util.BlockStateUtils; +import net.momirealms.craftengine.bukkit.util.ComponentUtils; +import net.momirealms.craftengine.bukkit.util.Reflections; +import net.momirealms.craftengine.core.block.CustomBlock; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.UpdateOption; +import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.util.MCUtils; +import net.momirealms.craftengine.core.util.MiscUtils; +import org.bukkit.Material; +import org.bukkit.block.Block; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.block.Action; +import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.inventory.EquipmentSlot; +import org.bukkit.inventory.ItemStack; + +import javax.annotation.Nullable; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; + +public class DebugStickListener implements Listener { + private final BukkitCraftEngine plugin; + + public DebugStickListener(BukkitCraftEngine plugin) { + this.plugin = plugin; + } + + @EventHandler(ignoreCancelled = true) + public void onUseDebugStick(PlayerInteractEvent event) { + Block clickedBlock = event.getClickedBlock(); + if (clickedBlock == null) return; + ItemStack itemInHand = event.getItem(); + if (itemInHand == null) return; + Material material = itemInHand.getType(); + if (material != Material.DEBUG_STICK) return; + Player bukkitPlayer = event.getPlayer(); + BukkitServerPlayer player = this.plugin.adapt(bukkitPlayer); + if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) { + return; + } + if (event.getHand() == EquipmentSlot.OFF_HAND) { + int currentTicks = player.gameTicks(); + if (!player.updateLastSuccessfulInteractionTick(currentTicks)) { + event.setCancelled(true); + return; + } + } + Object blockState = BlockStateUtils.blockDataToBlockState(clickedBlock.getBlockData()); + int stateId = BlockStateUtils.blockStateToId(blockState); + if (!BlockStateUtils.isVanillaBlock(stateId)) { + event.setCancelled(true); + boolean update = event.getAction() == Action.RIGHT_CLICK_BLOCK; + ImmutableBlockState clickedCustomBlock = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId); + CustomBlock block = clickedCustomBlock.owner().value(); + Collection> properties = block.properties(); + String blockId = block.id().toString(); + try { + if (properties.isEmpty()) { + Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance( + ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(blockId))), true); + player.sendPacket(systemChatPacket, false); + } else { + Item wrapped = BukkitItemManager.instance().wrap(itemInHand); + Object storedData = wrapped.getTag("craftengine:debug_stick_state"); + if (storedData == null) storedData = new HashMap<>(); + if (storedData instanceof Map map) { + Map data = MiscUtils.castToMap(map, false); + String currentPropertyName = (String) data.get(blockId); + Property currentProperty = block.getProperty(currentPropertyName); + if (currentProperty == null) { + currentProperty = properties.iterator().next(); + } + if (update) { + ImmutableBlockState nextState = cycleState(clickedCustomBlock, currentProperty, player.isSecondaryUseActive()); + CraftEngineBlocks.place(clickedBlock.getLocation(), nextState, new UpdateOption.Builder().updateClients().updateKnownShape().build()); + Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance( + ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.update") + .arguments( + Component.text(currentProperty.name()), + Component.text(getNameHelper(nextState, currentProperty)) + )), true); + player.sendPacket(systemChatPacket, false); + } else { + currentProperty = getRelative(properties, currentProperty, player.isSecondaryUseActive()); + data.put(blockId, currentProperty.name()); + wrapped.setTag(data, "craftengine:debug_stick_state"); + wrapped.load(); + Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance( + ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.select") + .arguments( + Component.text(currentProperty.name()), + Component.text(getNameHelper(clickedCustomBlock, currentProperty)) + )), true); + player.sendPacket(systemChatPacket, false); + } + } + } + } catch (ReflectiveOperationException e) { + plugin.logger().warn("Failed to send system chat packet", e); + } + } + } + + private static > ImmutableBlockState cycleState(ImmutableBlockState state, Property property, boolean inverse) { + return state.with(property, getRelative(property.possibleValues(), state.get(property), inverse)); + } + + private static T getRelative(Iterable elements, @Nullable T current, boolean inverse) { + return inverse ? MCUtils.findPreviousInIterable(elements, current) : MCUtils.findNextInIterable(elements, current); + } + + private static > String getNameHelper(ImmutableBlockState state, Property property) { + return property.valueName(state.get(property)); + } +} 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 31c8213c5..a80d0928d 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 @@ -2,31 +2,25 @@ package net.momirealms.craftengine.bukkit.item; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.format.NamedTextColor; -import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks; import net.momirealms.craftengine.bukkit.api.event.CustomBlockInteractEvent; import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; import net.momirealms.craftengine.bukkit.item.behavior.BlockItemBehavior; import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; import net.momirealms.craftengine.bukkit.util.*; -import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; -import net.momirealms.craftengine.core.block.UpdateOption; -import net.momirealms.craftengine.core.block.properties.Property; import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.InteractionResult; -import net.momirealms.craftengine.core.item.CustomItem; import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.context.UseOnContext; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.Key; -import net.momirealms.craftengine.core.util.MCUtils; -import net.momirealms.craftengine.core.util.MiscUtils; import net.momirealms.craftengine.core.world.BlockHitResult; import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.Vec3d; +import org.bukkit.GameMode; import org.bukkit.Location; -import org.bukkit.Material; import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.entity.Player; @@ -39,7 +33,6 @@ import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; -import javax.annotation.Nullable; import java.util.*; public class ItemEventListener implements Listener { @@ -62,26 +55,28 @@ public class ItemEventListener implements Listener { return; } - InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND; + // it's breaking the block + if (action == Action.LEFT_CLICK_BLOCK && event.getPlayer().getGameMode() == GameMode.CREATIVE) { + return; + } + CustomBlockInteractEvent interactEvent = new CustomBlockInteractEvent( event.getPlayer(), block.getLocation(), event.getInteractionPoint(), BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId), - hand, + event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND, action == Action.RIGHT_CLICK_BLOCK ? CustomBlockInteractEvent.Action.RIGHT_CLICK : CustomBlockInteractEvent.Action.LEFT_CLICK ); if (EventUtils.fireAndCheckCancel(interactEvent)) { event.setCancelled(true); - return; } } @EventHandler(priority = EventPriority.HIGHEST) public void onInteractAtBlock(PlayerInteractEvent event) { if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; - if (event.useItemInHand() == Event.Result.DENY) return; - if (event.useInteractedBlock() == Event.Result.DENY) return; + if (event.useItemInHand() == Event.Result.DENY || event.useInteractedBlock() == Event.Result.DENY) return; Location interactionPoint = event.getInteractionPoint(); if (interactionPoint == null) return; Player bukkitPlayer = event.getPlayer(); @@ -90,49 +85,58 @@ public class ItemEventListener implements Listener { InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND; if (hand == InteractionHand.OFF_HAND) { int currentTicks = player.gameTicks(); + // The client will send multiple packets to the server if the client thinks it should + // However, if the main hand item interaction is successful, the off-hand item should be blocked. if (!player.updateLastSuccessfulInteractionTick(currentTicks)) { event.setCancelled(true); return; } } + // Gets the item in hand Item itemInHand = player.getItemInHand(hand); if (itemInHand == null) return; - Optional> customItem = itemInHand.getCustomItem(); + Optional> optionalItemBehaviors = itemInHand.getItemBehavior(); - Material material = itemInHand.getItem().getType(); - // is custom item - if (customItem.isPresent()) { - if (material.isBlock()) { + // has custom item behavior + if (optionalItemBehaviors.isPresent()) { + // do not allow to place block if it's a vanilla block + if (itemInHand.isBlockItem() && itemInHand.isCustomItem()) { event.setCancelled(true); } - CustomItem item = customItem.get(); - BlockPos pos = LocationUtils.toBlockPos(clickedBlock.getLocation()); - Vec3d vec3d = new Vec3d(interactionPoint.getX(), interactionPoint.getY(), interactionPoint.getZ()); - Direction direction = DirectionUtils.toDirection(event.getBlockFace()); - BlockHitResult hitResult = new BlockHitResult(vec3d, direction, pos, false); - if (!player.isSecondaryUseActive()) { - if (InteractUtils.isInteractable(BlockStateUtils.getRealBlockId(clickedBlock), bukkitPlayer, clickedBlock.getBlockData(), hitResult, itemInHand)) return; + for (ItemBehavior itemBehavior : optionalItemBehaviors.get()) { + BlockPos pos = LocationUtils.toBlockPos(clickedBlock.getLocation()); + Vec3d vec3d = new Vec3d(interactionPoint.getX(), interactionPoint.getY(), interactionPoint.getZ()); + Direction direction = DirectionUtils.toDirection(event.getBlockFace()); + BlockHitResult hitResult = new BlockHitResult(vec3d, direction, pos, false); + if (!player.isSecondaryUseActive()) { + // if it's interactable on server, cancel the behaviors + if (InteractUtils.isInteractable(BlockStateUtils.getBlockOwnerId(clickedBlock), bukkitPlayer, clickedBlock.getBlockData(), hitResult, itemInHand)) return; + } + InteractionResult result = itemBehavior.useOnBlock(new UseOnContext(player, hand, hitResult)); + int maxY = player.level().worldHeight().getMaxBuildHeight() - 1; + if (direction == Direction.UP + && result != InteractionResult.SUCCESS + && pos.y() >= maxY + && itemBehavior instanceof BlockItemBehavior + ) { + player.sendActionBar(Component.translatable("build.tooHigh").arguments(Component.text(maxY)).color(NamedTextColor.RED)); + } + if (result != InteractionResult.PASS) { + return; + } } - InteractionResult result = item.behavior().useOnBlock(new UseOnContext(player, hand, hitResult)); - int maxY = player.level().worldHeight().getMaxBuildHeight() - 1; - if (direction == Direction.UP - && result != InteractionResult.SUCCESS - && pos.y() >= maxY - && item.behavior() instanceof BlockItemBehavior - ) { - player.sendActionBar(Component.translatable("build.tooHigh").arguments(Component.text(maxY)).color(NamedTextColor.RED)); - } - } else if (material.isBlock()) { - // vanilla item + return; + } + + // it's a vanilla block + if (itemInHand.isBlockItem() && !itemInHand.isCustomItem()) { // client won't have sounds if the fake block is interactable + // so we should check and resend sounds on interact Object blockState = BlockStateUtils.blockDataToBlockState(clickedBlock.getBlockData()); int stateId = BlockStateUtils.blockStateToId(blockState); - if (BlockStateUtils.isVanillaBlock(stateId)) { - return; - } - ImmutableBlockState againCustomBlock = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId); - if (againCustomBlock.isEmpty()) { + ImmutableBlockState againCustomBlock = BukkitBlockManager.instance().getImmutableBlockState(stateId); + if (againCustomBlock == null || againCustomBlock.isEmpty()) { return; } BlockPos pos = LocationUtils.toBlockPos(clickedBlock.getLocation()); @@ -140,7 +144,7 @@ public class ItemEventListener implements Listener { Direction direction = DirectionUtils.toDirection(event.getBlockFace()); BlockHitResult hitResult = new BlockHitResult(vec3d, direction, pos, false); try { - BlockData craftBlockData = (BlockData) Reflections.method$CraftBlockData$createData.invoke(null, againCustomBlock.vanillaBlockState().handle()); + BlockData craftBlockData = BlockStateUtils.createBlockData(againCustomBlock.vanillaBlockState().handle()); if (InteractUtils.isInteractable(Key.of(clickedBlock.getType().getKey().asString()), bukkitPlayer, craftBlockData, hitResult, itemInHand)) { if (!player.isSecondaryUseActive()) { player.setResendSound(); @@ -155,92 +159,4 @@ public class ItemEventListener implements Listener { } } } - - @EventHandler(ignoreCancelled = true) - public void onUseDebugStick(PlayerInteractEvent event) { - Block clickedBlock = event.getClickedBlock(); - if (clickedBlock == null) return; - ItemStack itemInHand = event.getItem(); - if (itemInHand == null) return; - Material material = itemInHand.getType(); - if (material != Material.DEBUG_STICK) return; - Player bukkitPlayer = event.getPlayer(); - BukkitServerPlayer player = this.plugin.adapt(bukkitPlayer); - if (!(player.canInstabuild() && player.hasPermission("minecraft.debugstick")) && !player.hasPermission("minecraft.debugstick.always")) { - return; - } - if (event.getHand() == EquipmentSlot.OFF_HAND) { - int currentTicks = player.gameTicks(); - if (!player.updateLastSuccessfulInteractionTick(currentTicks)) { - event.setCancelled(true); - return; - } - } - Object blockState = BlockStateUtils.blockDataToBlockState(clickedBlock.getBlockData()); - int stateId = BlockStateUtils.blockStateToId(blockState); - if (!BlockStateUtils.isVanillaBlock(stateId)) { - event.setCancelled(true); - boolean update = event.getAction() == Action.RIGHT_CLICK_BLOCK; - ImmutableBlockState clickedCustomBlock = BukkitBlockManager.instance().getImmutableBlockStateUnsafe(stateId); - CustomBlock block = clickedCustomBlock.owner().value(); - Collection> properties = block.properties(); - String blockId = block.id().toString(); - try { - if (properties.isEmpty()) { - Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance( - ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.empty").arguments(Component.text(blockId))), true); - player.sendPacket(systemChatPacket, false); - } else { - Item wrapped = BukkitItemManager.instance().wrap(itemInHand); - Object storedData = wrapped.getTag("craftengine:debug_stick_state"); - if (storedData == null) storedData = new HashMap<>(); - if (storedData instanceof Map map) { - Map data = MiscUtils.castToMap(map, false); - String currentPropertyName = (String) data.get(blockId); - Property currentProperty = block.getProperty(currentPropertyName); - if (currentProperty == null) { - currentProperty = properties.iterator().next(); - } - if (update) { - ImmutableBlockState nextState = cycleState(clickedCustomBlock, currentProperty, player.isSecondaryUseActive()); - CraftEngineBlocks.place(clickedBlock.getLocation(), nextState, new UpdateOption.Builder().updateClients().updateKnownShape().build()); - Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance( - ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.update") - .arguments( - Component.text(currentProperty.name()), - Component.text(getNameHelper(nextState, currentProperty)) - )), true); - player.sendPacket(systemChatPacket, false); - } else { - currentProperty = getRelative(properties, currentProperty, player.isSecondaryUseActive()); - data.put(blockId, currentProperty.name()); - wrapped.setTag(data, "craftengine:debug_stick_state"); - wrapped.load(); - Object systemChatPacket = Reflections.constructor$ClientboundSystemChatPacket.newInstance( - ComponentUtils.adventureToMinecraft(Component.translatable("item.minecraft.debug_stick.select") - .arguments( - Component.text(currentProperty.name()), - Component.text(getNameHelper(clickedCustomBlock, currentProperty)) - )), true); - player.sendPacket(systemChatPacket, false); - } - } - } - } catch (ReflectiveOperationException e) { - plugin.logger().warn("Failed to send system chat packet", e); - } - } - } - - private static > ImmutableBlockState cycleState(ImmutableBlockState state, Property property, boolean inverse) { - return state.with(property, getRelative(property.possibleValues(), state.get(property), inverse)); - } - - private static T getRelative(Iterable elements, @Nullable T current, boolean inverse) { - return inverse ? MCUtils.findPreviousInIterable(elements, current) : MCUtils.findNextInIterable(elements, current); - } - - private static > String getNameHelper(ImmutableBlockState state, Property property) { - return property.valueName(state.get(property)); - } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/AxeItemBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/AxeItemBehavior.java new file mode 100644 index 000000000..e7288ebf3 --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/AxeItemBehavior.java @@ -0,0 +1,98 @@ +package net.momirealms.craftengine.bukkit.item.behavior; + +import net.momirealms.craftengine.bukkit.api.CraftEngineBlocks; +import net.momirealms.craftengine.bukkit.block.BukkitBlockManager; +import net.momirealms.craftengine.bukkit.block.behavior.StrippableBlockBehavior; +import net.momirealms.craftengine.bukkit.util.BlockStateUtils; +import net.momirealms.craftengine.bukkit.util.EventUtils; +import net.momirealms.craftengine.bukkit.util.MaterialUtils; +import net.momirealms.craftengine.bukkit.util.Reflections; +import net.momirealms.craftengine.bukkit.world.BukkitWorldBlock; +import net.momirealms.craftengine.core.block.CustomBlock; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.UpdateOption; +import net.momirealms.craftengine.core.entity.player.InteractionHand; +import net.momirealms.craftengine.core.entity.player.InteractionResult; +import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.item.Item; +import net.momirealms.craftengine.core.item.ItemKeys; +import net.momirealms.craftengine.core.item.behavior.ItemBehavior; +import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory; +import net.momirealms.craftengine.core.item.context.UseOnContext; +import net.momirealms.craftengine.core.plugin.CraftEngine; +import net.momirealms.craftengine.core.util.Key; +import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.sparrow.nbt.CompoundTag; +import org.bukkit.GameEvent; +import org.bukkit.Material; +import org.bukkit.Statistic; +import org.bukkit.block.Block; +import org.bukkit.event.entity.EntityChangeBlockEvent; +import org.bukkit.inventory.ItemStack; +import org.bukkit.util.Vector; + +import java.util.Map; +import java.util.Optional; + +public class AxeItemBehavior extends ItemBehavior { + public static final Factory FACTORY = new Factory(); + public static final AxeItemBehavior INSTANCE = new AxeItemBehavior(); + private static final Key AXE_STRIP_SOUND = Key.of("minecraft:item.axe.strip"); + + @Override + public InteractionResult useOnBlock(UseOnContext context) { + BukkitWorldBlock clicked = (BukkitWorldBlock) context.getLevel().getBlockAt(context.getClickedPos()); + Block block = clicked.block(); + ImmutableBlockState state = BukkitBlockManager.instance().getImmutableBlockState(BlockStateUtils.blockDataToId(block.getBlockData())); + if (state == null || state.isEmpty()) return InteractionResult.PASS; + + if (!(state.behavior() instanceof StrippableBlockBehavior blockBehavior)) { + return InteractionResult.PASS; + } + + Player player = context.getPlayer(); + @SuppressWarnings("unchecked") + Item offHandItem = (Item) player.getItemInHand(InteractionHand.OFF_HAND); + // is using a shield + if (context.getHand() == InteractionHand.MAIN_HAND && offHandItem != null && offHandItem.vanillaId().equals(ItemKeys.SHIELD) && !player.isSecondaryUseActive()) { + return InteractionResult.PASS; + } + + Optional optionalNewCustomBlock = BukkitBlockManager.instance().getBlock(blockBehavior.stripped()); + if (optionalNewCustomBlock.isEmpty()) { + CraftEngine.instance().logger().warn("stripped block " + blockBehavior.stripped() + " does not exist"); + return InteractionResult.FAIL; + } + CustomBlock newCustomBlock = optionalNewCustomBlock.get(); + CompoundTag compoundTag = state.propertiesNbt(); + ImmutableBlockState newState = newCustomBlock.getBlockState(compoundTag); + + org.bukkit.entity.Player bukkitPlayer = ((org.bukkit.entity.Player) player.platformPlayer()); + // Call bukkit event + EntityChangeBlockEvent event = new EntityChangeBlockEvent(bukkitPlayer, block, BlockStateUtils.createBlockData(newState.customBlockState().handle())); + if (EventUtils.fireAndCheckCancel(event)) { + return InteractionResult.PASS; + } + + BlockPos pos = context.getClickedPos(); + context.getLevel().playBlockSound(Vec3d.atCenterOf(pos), AXE_STRIP_SOUND, 1, 1); + CraftEngineBlocks.place(block.getLocation(), newState, UpdateOption.UPDATE_ALL_IMMEDIATE); + block.getWorld().sendGameEvent(bukkitPlayer, GameEvent.BLOCK_CHANGE, new Vector(pos.x(), pos.y(), pos.z())); + Item item = context.getItem(); + Material material = MaterialUtils.getMaterial(item.vanillaId()); + bukkitPlayer.setStatistic(Statistic.USE_ITEM, material, bukkitPlayer.getStatistic(Statistic.USE_ITEM, material) + 1); + + ItemStack itemStack = (ItemStack) item.getItem(); + itemStack.damage(1, bukkitPlayer); + return InteractionResult.SUCCESS; + } + + public static class Factory implements ItemBehaviorFactory { + + @Override + public ItemBehavior create(Key id, Map arguments) { + return INSTANCE; + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BukkitItemBehaviors.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BukkitItemBehaviors.java index 1695aa0ad..cb0e6a100 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BukkitItemBehaviors.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/behavior/BukkitItemBehaviors.java @@ -8,10 +8,12 @@ public class BukkitItemBehaviors extends ItemBehaviors { public static final Key EMPTY = Key.from("craftengine:empty"); public static final Key BLOCK_ITEM = Key.from("craftengine:block_item"); public static final Key FURNITURE_ITEM = Key.from("craftengine:furniture_item"); + public static final Key AXE_ITEM = Key.from("craftengine:axe_item"); public static void init() { register(EMPTY, (args, id) -> EmptyItemBehavior.INSTANCE); register(BLOCK_ITEM, BlockItemBehavior.FACTORY); register(FURNITURE_ITEM, FurnitureItemBehavior.FACTORY); + register(AXE_ITEM, AxeItemBehavior.FACTORY); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java index 23b538d6b..30e4d7f08 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/item/factory/BukkitItemFactory.java @@ -50,6 +50,11 @@ public abstract class BukkitItemFactory extends ItemFactory item) { + return item.getItem().getType().isBlock(); + } + @Override protected Key vanillaId(ItemWrapper item) { return Key.of(item.getItem().getType().getKey().asString()); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index a446c23e6..32d629e1d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -316,7 +316,7 @@ public class PacketConsumers { Key itemId = state.settings().itemId(); // no item available if (itemId == null) return; - BlockData data = (BlockData) Reflections.method$CraftBlockData$createData.invoke(null, state.vanillaBlockState().handle()); + BlockData data = BlockStateUtils.createBlockData(state.vanillaBlockState().handle()); // compare item if (data == null || !data.getMaterial().equals(item.getType())) return; ItemStack itemStack = BukkitCraftEngine.instance().itemManager().buildCustomItemStack(itemId, (BukkitServerPlayer) user); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java index a0acc9767..ea147c682 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/user/BukkitServerPlayer.java @@ -28,6 +28,7 @@ import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.PlayerInventory; import org.bukkit.util.RayTraceResult; +import org.jetbrains.annotations.Nullable; import java.lang.ref.Reference; import java.lang.ref.WeakReference; @@ -360,7 +361,7 @@ public class BukkitServerPlayer extends Player { if (canInstabuild() && (itemMaterial == Material.DEBUG_STICK || itemMaterial == Material.TRIDENT || (VersionHelper.isVersionNewerThan1_20_5() && itemMaterial == MaterialUtils.MACE) - || item.is(Key.of("minecraft:swords")))) { + || item.is(ItemTags.SWORDS))) { return; } } @@ -482,6 +483,7 @@ public class BukkitServerPlayer extends Player { return DirectionUtils.toDirection(platformPlayer().getFacing()); } + @Nullable @Override public Item getItemInHand(InteractionHand hand) { PlayerInventory inventory = platformPlayer().getInventory(); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java index 4ed7b854b..01c24eb9d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/BlockStateUtils.java @@ -8,6 +8,7 @@ import org.bukkit.block.Block; import org.bukkit.block.data.BlockData; import org.bukkit.event.block.BlockPhysicsEvent; +import java.lang.reflect.InvocationTargetException; import java.util.IdentityHashMap; public class BlockStateUtils { @@ -23,6 +24,14 @@ public class BlockStateUtils { hasInit = true; } + public static BlockData createBlockData(Object blockState) { + try { + return (BlockData) Reflections.method$CraftBlockData$createData.invoke(null, blockState); + } catch (InvocationTargetException | IllegalAccessException e) { + throw new RuntimeException(e); + } + } + public static int blockDataToId(BlockData blockData) { try { Object blockState = Reflections.field$CraftBlockData$data.get(blockData); @@ -32,13 +41,13 @@ public class BlockStateUtils { } } - public static Key getRealBlockId(Block block) { + public static Key getBlockOwnerId(Block block) { BlockData data = block.getBlockData(); Object blockState = blockDataToBlockState(data); - return getRealBlockIdFromState(blockState); + return getBlockOwnerIdFromState(blockState); } - public static Key getRealBlockIdFromState(Object blockState) { + public static Key getBlockOwnerIdFromState(Object blockState) { String id = blockState.toString(); int first = id.indexOf('{'); int last = id.indexOf('}'); diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemTags.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemTags.java index 4b6667aa1..029ee94c2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemTags.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/ItemTags.java @@ -8,6 +8,9 @@ import java.util.Map; public class ItemTags { private static final Map CACHE = new HashMap<>(); + public static final Key AXES = Key.of("minecraft:axes"); + public static final Key SWORDS = Key.of("minecraft:swords"); + public static Object getOrCreate(Key key) { Object value = CACHE.get(key); if (value == null) { diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java index e7cfba887..f36261218 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/Reflections.java @@ -2689,6 +2689,42 @@ public class Reflections { } } + public static final Class clazz$EquipmentSlot = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.entity.EquipmentSlot"), + BukkitReflectionUtils.assembleMCClass("world.entity.EnumItemSlot") + ) + ); + + public static final Method method$EquipmentSlot$values = requireNonNull( + ReflectionUtils.getStaticMethod( + clazz$EquipmentSlot, clazz$EquipmentSlot.arrayType() + ) + ); + + public static final Object instance$EquipmentSlot$MAINHAND; + public static final Object instance$EquipmentSlot$OFFHAND; + public static final Object instance$EquipmentSlot$FEET; + public static final Object instance$EquipmentSlot$LEGS; + public static final Object instance$EquipmentSlot$CHEST; + public static final Object instance$EquipmentSlot$HEAD; +// public static final Object instance$EquipmentSlot$BODY; + + static { + try { + Object[] values = (Object[]) method$EquipmentSlot$values.invoke(null); + instance$EquipmentSlot$MAINHAND = values[0]; + instance$EquipmentSlot$OFFHAND = values[1]; + instance$EquipmentSlot$FEET = values[2]; + instance$EquipmentSlot$LEGS = values[3]; + instance$EquipmentSlot$CHEST = values[4]; + instance$EquipmentSlot$HEAD = values[5]; +// instance$EquipmentSlot$BODY = values[6]; + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } + } + public static final Method method$Block$defaultBlockState = requireNonNull( ReflectionUtils.getMethod( clazz$Block, clazz$BlockState @@ -4124,4 +4160,11 @@ public class Reflections { clazz$CraftInventoryCrafting, clazz$Container, 0 ) ); + + public static final Class clazz$LivingEntity = requireNonNull( + ReflectionUtils.getClazz( + BukkitReflectionUtils.assembleMCClass("world.entity.LivingEntity"), + BukkitReflectionUtils.assembleMCClass("world.entity.EntityLiving") + ) + ); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java b/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java index c3dfe43f4..6a4f2ae9e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/ImmutableBlockState.java @@ -97,7 +97,7 @@ public class ImmutableBlockState extends BlockStateHolder { this.vanillaBlockState = vanillaBlockState; } - private CompoundTag propertiesNbt() { + public CompoundTag propertiesNbt() { CompoundTag properties = new CompoundTag(); for (Property property : getProperties()) { Comparable value = get(property); diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java index 9fe9a5a67..9ca0e44d8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/player/Player.java @@ -5,11 +5,13 @@ import net.momirealms.craftengine.core.entity.Entity; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.network.NetWorkUser; import net.momirealms.craftengine.core.world.BlockPos; +import org.jetbrains.annotations.Nullable; public abstract class Player extends Entity implements NetWorkUser { public abstract boolean isSecondaryUseActive(); + @Nullable public abstract Item getItemInHand(InteractionHand hand); @Override diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java index 4945216ba..e3edb3355 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/AbstractItem.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.core.item; +import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.util.Key; import java.util.List; @@ -42,6 +43,21 @@ public class AbstractItem, I> implements Item { return ((ItemManager) factory.plugin.itemManager()).getCustomItem(id()); } + @Override + public Optional> getItemBehavior() { + return factory.plugin.itemManager().getItemBehavior(id()); + } + + @Override + public boolean isCustomItem() { + return factory.plugin.itemManager().getCustomItem(id()).isPresent(); + } + + @Override + public boolean isBlockItem() { + return factory.isBlockItem(item); + } + @Override public Key id() { return this.factory.id(this.item); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java b/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java index 4934e5938..5c73adbe8 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/CustomItem.java @@ -4,6 +4,7 @@ import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.item.modifier.ItemModifier; import net.momirealms.craftengine.core.util.Key; +import org.jetbrains.annotations.NotNull; import java.util.List; @@ -23,6 +24,7 @@ public interface CustomItem extends BuildableItem { Item buildItem(Player player); + @NotNull ItemBehavior behavior(); interface Builder { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/Item.java b/core/src/main/java/net/momirealms/craftengine/core/item/Item.java index 61564aa14..478f741b3 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/Item.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/Item.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.core.item; +import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.util.Key; import java.util.List; @@ -16,6 +17,12 @@ public interface Item { Optional> getCustomItem(); + Optional> getItemBehavior(); + + boolean isCustomItem(); + + boolean isBlockItem(); + Key id(); Key vanillaId(); diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java index 311633530..5a497afd4 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemFactory.java @@ -102,4 +102,6 @@ public abstract class ItemFactory

, I> protected abstract void maxStackSize(ItemWrapper item, Integer maxStackSize); protected abstract boolean is(ItemWrapper item, Key itemTag); + + protected abstract boolean isBlockItem(ItemWrapper item); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemKeys.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemKeys.java index f7bb2225a..7dbcfee8b 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemKeys.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemKeys.java @@ -11,4 +11,10 @@ public class ItemKeys { public static final Key FISHING_ROD = Key.of("minecraft:fishing_rod"); public static final Key ELYTRA = Key.of("minecraft:elytra"); public static final Key GOAT_HORN = Key.of("minecraft:goat_horn"); + public static final Key WOODEN_AXE = Key.of("minecraft:wooden_axe"); + public static final Key STONE_AXE = Key.of("minecraft:stone_axe"); + public static final Key IRON_AXE = Key.of("minecraft:iron_axe"); + public static final Key GOLDEN_AXE = Key.of("minecraft:golden_axe"); + public static final Key DIAMOND_AXE = Key.of("minecraft:diamond_axe"); + public static final Key NETHERITE_AXE = Key.of("minecraft:netherite_axe"); } diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java b/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java index ae3821399..fb92973b4 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/ItemManager.java @@ -1,6 +1,7 @@ package net.momirealms.craftengine.core.item; import net.momirealms.craftengine.core.entity.player.Player; +import net.momirealms.craftengine.core.item.behavior.ItemBehavior; import net.momirealms.craftengine.core.pack.LegacyOverridesModel; import net.momirealms.craftengine.core.pack.LoadingSequence; import net.momirealms.craftengine.core.pack.generator.ModelGenerator; @@ -42,6 +43,8 @@ public interface ItemManager extends Reloadable, ModelGenerator, ConfigSectio Optional> getCustomItem(Key key); + Optional> getItemBehavior(Key key); + Optional> getVanillaItem(Key key); default Optional> getBuildableItem(Key key) { diff --git a/core/src/main/java/net/momirealms/craftengine/core/item/behavior/ItemBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/item/behavior/ItemBehavior.java index 85c5c0a09..3c73c14e7 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/item/behavior/ItemBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/item/behavior/ItemBehavior.java @@ -4,7 +4,7 @@ import net.momirealms.craftengine.core.entity.player.InteractionHand; import net.momirealms.craftengine.core.entity.player.InteractionResult; import net.momirealms.craftengine.core.entity.player.Player; import net.momirealms.craftengine.core.item.context.UseOnContext; -import net.momirealms.craftengine.core.world.CEWorld; +import net.momirealms.craftengine.core.world.World; public abstract class ItemBehavior { @@ -12,7 +12,7 @@ public abstract class ItemBehavior { return InteractionResult.PASS; } - public InteractionResult use(CEWorld context, Player player, InteractionHand hand) { + public InteractionResult use(World world, Player player, InteractionHand hand) { return InteractionResult.PASS; } }