mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-25 09:59:20 +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);
|
||||
|
||||
@@ -42,6 +42,9 @@ public final class BlockKeys {
|
||||
public static final Key CHAIN_COMMAND_BLOCK = Key.of("minecraft:chain_command_block");
|
||||
public static final Key REPEATING_COMMAND_BLOCK = Key.of("minecraft:repeating_command_block");
|
||||
public static final Key DECORATED_POT = Key.of("minecraft:decorated_pot");
|
||||
public static final Key CHISELED_BOOKSHELF = Key.of("minecraft:chiseled_bookshelf");
|
||||
public static final Key REDSTONE_ORE = Key.of("minecraft:redstone_ore");
|
||||
public static final Key DEEPSLATE_REDSTONE_ORE = Key.of("minecraft:deepslate_redstone_ore");
|
||||
|
||||
public static final Key CAKE = Key.of("minecraft:cake");
|
||||
public static final Key CANDLE_CAKE = Key.of("minecraft:candle_cake");
|
||||
|
||||
Reference in New Issue
Block a user