mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-28 19:39:11 +00:00
Improve entity and block interaction handling
Added checks for interactable entities and blocks, including chiseled bookshelf, redstone ore, and deepslate redstone ore. Updated ItemEventListener to use new InteractUtils methods for entity and block interactions, preventing custom item execution on interactable entities and blocks.
This commit is contained in:
@@ -36,6 +36,7 @@ import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Openable;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
@@ -66,6 +67,8 @@ public class ItemEventListener implements Listener {
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
public void onInteractEntity(PlayerInteractEntityEvent event) {
|
||||
Player player = event.getPlayer();
|
||||
Entity entity = event.getRightClicked();
|
||||
BukkitServerPlayer serverPlayer = this.plugin.adapt(event.getPlayer());
|
||||
if (serverPlayer == null) return;
|
||||
InteractionHand hand = event.getHand() == EquipmentSlot.HAND ? InteractionHand.MAIN_HAND : InteractionHand.OFF_HAND;
|
||||
@@ -75,15 +78,17 @@ public class ItemEventListener implements Listener {
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
|
||||
if (optionalCustomItem.isEmpty()) return;
|
||||
|
||||
Cancellable cancellable = Cancellable.of(event::isCancelled, event::setCancelled);
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
|
||||
.withParameter(DirectContextParameters.EVENT, cancellable)
|
||||
.withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(event.getRightClicked().getLocation()))
|
||||
.withParameter(DirectContextParameters.HAND, hand)
|
||||
);
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
customItem.execute(context, EventTrigger.RIGHT_CLICK);
|
||||
if (!InteractUtils.isEntityInteractable(player, entity, itemInHand)) {
|
||||
Cancellable cancellable = Cancellable.of(event::isCancelled, event::setCancelled);
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
|
||||
.withParameter(DirectContextParameters.EVENT, cancellable)
|
||||
.withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(event.getRightClicked().getLocation()))
|
||||
.withParameter(DirectContextParameters.HAND, hand)
|
||||
);
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
customItem.execute(context, EventTrigger.RIGHT_CLICK);
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(ignoreCancelled = true, priority = EventPriority.HIGHEST)
|
||||
@@ -275,10 +280,12 @@ public class ItemEventListener implements Listener {
|
||||
.withParameter(DirectContextParameters.EVENT, dummy)
|
||||
);
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
customItem.execute(context, EventTrigger.RIGHT_CLICK);
|
||||
if (dummy.isCancelled()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
if (!InteractUtils.isInteractable(player, blockData, hitResult, null)) {
|
||||
customItem.execute(context, EventTrigger.RIGHT_CLICK);
|
||||
if (dummy.isCancelled()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,12 +16,14 @@ import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.Bell;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.entity.*;
|
||||
import org.bukkit.entity.minecart.RideableMinecart;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class InteractUtils {
|
||||
private static final Map<Key, QuadFunction<Player, Item<ItemStack>, BlockData, BlockHitResult, Boolean>> INTERACTIONS = new HashMap<>();
|
||||
@@ -88,6 +90,7 @@ public class InteractUtils {
|
||||
item.recipeIngredientId(), item
|
||||
))) != null;
|
||||
});
|
||||
registerInteraction(BlockKeys.CHISELED_BOOKSHELF, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.DECORATED_POT, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.HOPPER, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.DISPENSER, (player, item, blockState, result) -> true);
|
||||
@@ -267,6 +270,8 @@ public class InteractUtils {
|
||||
registerInteraction(BlockKeys.REPEATING_COMMAND_BLOCK, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.CHAIN_COMMAND_BLOCK, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.COMMAND_BLOCK, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.REDSTONE_ORE, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.DEEPSLATE_REDSTONE_ORE, (player, item, blockState, result) -> true);
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -274,6 +279,27 @@ public class InteractUtils {
|
||||
result.getDirection() == Direction.UP && item.id().equals(ItemKeys.CACTUS));
|
||||
}
|
||||
|
||||
private static final Set<EntityType> INTERACTABLE_ENTITIES = Set.of(
|
||||
EntityType.ALLAY,
|
||||
EntityType.HORSE,
|
||||
EntityType.ZOMBIE_HORSE,
|
||||
EntityType.SKELETON_HORSE,
|
||||
EntityType.DONKEY,
|
||||
EntityType.MULE,
|
||||
EntityType.VILLAGER,
|
||||
EntityType.WANDERING_TRADER,
|
||||
EntityType.LLAMA,
|
||||
EntityType.TRADER_LLAMA,
|
||||
EntityType.CAMEL,
|
||||
EntityType.CHEST_MINECART,
|
||||
EntityType.FURNACE_MINECART,
|
||||
EntityType.HOPPER_MINECART,
|
||||
EntityType.COMMAND_BLOCK_MINECART,
|
||||
EntityType.ITEM_FRAME,
|
||||
EntityType.GLOW_ITEM_FRAME,
|
||||
EntityType.HAPPY_GHAST
|
||||
);
|
||||
|
||||
private static void registerInteraction(Key key, QuadFunction<org.bukkit.entity.Player, Item<ItemStack>, BlockData, BlockHitResult, Boolean> function) {
|
||||
var previous = INTERACTIONS.put(key, function);
|
||||
if (previous != null) {
|
||||
@@ -297,6 +323,22 @@ public class InteractUtils {
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isEntityInteractable(Player player, Entity entity, Item<ItemStack> item) {
|
||||
boolean isSneaking = player.isSneaking();
|
||||
if (entity.getType() == EntityType.PIGLIN &&
|
||||
item != null &&
|
||||
item.vanillaId().equals(Key.of("minecraft:gold_ingot"))) {
|
||||
return true;
|
||||
}
|
||||
return switch (entity) {
|
||||
case ChestBoat ignored -> true;
|
||||
case Boat ignored -> !isSneaking;
|
||||
case RideableMinecart ignored -> !isSneaking;
|
||||
case Steerable steerable -> !isSneaking && steerable.hasSaddle();
|
||||
default -> INTERACTABLE_ENTITIES.contains(entity.getType());
|
||||
};
|
||||
}
|
||||
|
||||
public static boolean willConsume(Player player, BlockData state, BlockHitResult hit, @Nullable Item<ItemStack> item) {
|
||||
if (item == null) return false;
|
||||
Key blockType = BlockStateUtils.getBlockOwnerIdFromData(state);
|
||||
|
||||
Reference in New Issue
Block a user