diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityUtils.java index 070dd8ebe..2772f445e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/EntityUtils.java @@ -1,5 +1,6 @@ package net.momirealms.craftengine.bukkit.util; +import net.momirealms.craftengine.bukkit.item.BukkitItemManager; import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.core.item.Item; @@ -8,12 +9,8 @@ import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.BlockPos; import org.bukkit.Location; import org.bukkit.World; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.LivingEntity; -import org.bukkit.entity.Player; +import org.bukkit.entity.*; import org.bukkit.event.entity.CreatureSpawnEvent; -import org.bukkit.inventory.EntityEquipment; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; @@ -21,7 +18,8 @@ import java.util.function.Consumer; public class EntityUtils { - private EntityUtils() {} + private EntityUtils() { + } public static BlockPos getOnPos(Player player) { try { @@ -41,6 +39,13 @@ public class EntityUtils { } } + public static boolean isPetOwner(Player player, Entity entity) { + if (!(entity instanceof Sittable sittable)) return false; + return sittable instanceof Tameable tameable + && tameable.isTamed() + && tameable.getOwnerUniqueId() == player.getUniqueId(); + } + public static boolean isPiglinWithGoldIngot(Entity entity, Item item) { return entity.getType() == EntityType.PIGLIN && item != null && @@ -48,16 +53,12 @@ public class EntityUtils { } public static boolean isHappyGhastRideable(Entity entity) { - if (!VersionHelper.isOrAbove1_21_6() && - !entity.getType().name().equals("HAPPY_GHAST")) return false; - return entity instanceof LivingEntity livingEntity - && livingEntity.getEquipment() != null - && hasHarness(livingEntity.getEquipment()); + if (!VersionHelper.isOrAbove1_21_6()) return false; + if (entity instanceof LivingEntity living && entity.getType() == EntityType.HAPPY_GHAST) { + ItemStack bodyItem = living.getEquipment().getItem(EquipmentSlot.BODY); + Item wrapped = BukkitItemManager.instance().wrap(bodyItem); + return wrapped.is(Key.of("harnesses")); + } + return false; } - - public static boolean hasHarness(EntityEquipment equipment) { - ItemStack bodyItem = equipment.getItem(EquipmentSlot.BODY); - return ItemTags.ITEMS_HARNESSES != null && - ItemTags.ITEMS_HARNESSES.isTagged(bodyItem.getType()); - } -} +} \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java index 99b3398a2..9ff03e35c 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/util/InteractUtils.java @@ -1,7 +1,9 @@ package net.momirealms.craftengine.bukkit.util; import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager; +import net.momirealms.craftengine.bukkit.nms.FastNMS; import net.momirealms.craftengine.core.block.BlockKeys; +import net.momirealms.craftengine.core.entity.EntityKeys; import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.item.ItemKeys; import net.momirealms.craftengine.core.item.recipe.RecipeTypes; @@ -29,7 +31,7 @@ public class InteractUtils { private static final Map, BlockData, BlockHitResult, Boolean>> INTERACTIONS = new HashMap<>(); private static final Map, BlockData, BlockHitResult, Boolean>> WILL_CONSUME = new HashMap<>(); private static final Key NOTE_BLOCK_TOP_INSTRUMENTS = Key.of("minecraft:noteblock_top_instruments"); - private static final Set INTERACTABLE_ENTITIES = createInteractableEntities(); + private static final Set INTERACTABLE_ENTITIES = new HashSet<>(); private InteractUtils() {} @@ -92,12 +94,8 @@ public class InteractUtils { ))) != null; }); registerInteraction(BlockKeys.CHISELED_BOOKSHELF, (player, item, blockState, result) -> { - Direction direction = result.getDirection(); - if (blockState instanceof ChiseledBookshelf chiseledBookshelf) { - Direction facing = DirectionUtils.toDirection(chiseledBookshelf.getFacing()); - return facing == direction; - } - return false; + if (!(blockState instanceof ChiseledBookshelf chiseledBookshelf)) return false; + return DirectionUtils.toDirection(chiseledBookshelf.getFacing()) == result.getDirection(); }); registerInteraction(BlockKeys.DECORATED_POT, (player, item, blockState, result) -> true); registerInteraction(BlockKeys.HOPPER, (player, item, blockState, result) -> true); @@ -287,31 +285,35 @@ public class InteractUtils { result.getDirection() == Direction.UP && item.id().equals(ItemKeys.CACTUS)); } - private static Set createInteractableEntities() { - Set set = EnumSet.noneOf(EntityType.class); - set.addAll(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 - )); - if (VersionHelper.isOrAbove1_21_6()) { - set.add(EntityType.valueOf("HAPPY_GHAST")); + static { + registerInteractableEntity(EntityKeys.ALLAY); + registerInteractableEntity(EntityKeys.HORSE); + registerInteractableEntity(EntityKeys.ZOMBIE_HORSE); + registerInteractableEntity(EntityKeys.SKELETON_HORSE); + registerInteractableEntity(EntityKeys.DONKEY); + registerInteractableEntity(EntityKeys.MULE); + registerInteractableEntity(EntityKeys.VILLAGER); + registerInteractableEntity(EntityKeys.WANDERING_TRADER); + registerInteractableEntity(EntityKeys.LLAMA); + registerInteractableEntity(EntityKeys.TRADER_LLAMA); + registerInteractableEntity(EntityKeys.CAMEL); + registerInteractableEntity(EntityKeys.ITEM_FRAME); + registerInteractableEntity(EntityKeys.GLOW_ITEM_FRAME); + registerInteractableEntity(EntityKeys.INTERACTION); + if (VersionHelper.isOrAbove1_20_5()) { + registerInteractableEntity(EntityKeys.CHEST_MINECART); + registerInteractableEntity(EntityKeys.FURNACE_MINECART); + registerInteractableEntity(EntityKeys.HOPPER_MINECART); + registerInteractableEntity(EntityKeys.COMMAND_BLOCK_MINECART); + } else { + registerInteractableEntity(EntityKeys.MINECART_CHEST); + registerInteractableEntity(EntityKeys.MINECART_FURNACE); + registerInteractableEntity(EntityKeys.MINECART_HOPPER); + registerInteractableEntity(EntityKeys.MINECART_COMMAND); + } + if (VersionHelper.isOrAbove1_21_6()) { + registerInteractableEntity(EntityKeys.HAPPY_GHAST); } - return Collections.unmodifiableSet(set); } private static void registerInteraction(Key key, QuadFunction, BlockData, BlockHitResult, Boolean> function) { @@ -328,6 +330,13 @@ public class InteractUtils { } } + private static void registerInteractableEntity(Key key) { + var previous = INTERACTABLE_ENTITIES.add(key); + if (!previous) { + CraftEngine.instance().logger().warn("Duplicated interaction check: " + key); + } + } + public static boolean isInteractable(Player player, BlockData state, BlockHitResult hit, @Nullable Item item) { Key blockType = BlockStateUtils.getBlockOwnerIdFromData(state); if (INTERACTIONS.containsKey(blockType)) { @@ -338,22 +347,17 @@ public class InteractUtils { } public static boolean isEntityInteractable(Player player, Entity entity, Item item) { - if (EntityUtils.isPiglinWithGoldIngot(entity, item)) { - return true; - } +// Object entityType = FastNMS.INSTANCE.method$CraftEntityType$toNMSEntityType(entity.getType()); + Key entityType = Key.of(String.valueOf(entity.getType())); + if (EntityUtils.isPetOwner(player, entity)) return true; + if (EntityUtils.isPiglinWithGoldIngot(entity, item)) return true; if (!player.isSneaking()) { - if (EntityUtils.isHappyGhastRideable(entity)) { - return true; - } - return switch (entity) { - case Boat ignored -> true; - case RideableMinecart ignored -> true; - case Steerable steerable -> steerable.hasSaddle(); - default -> INTERACTABLE_ENTITIES.contains(entity.getType()); - }; + if (EntityUtils.isHappyGhastRideable(entity)) return true; + if (entity instanceof Boat) return true; + if (entity instanceof RideableMinecart) return true; + if (entity instanceof Steerable steerable && steerable.hasSaddle()) return true; } - return entity instanceof ChestBoat - || INTERACTABLE_ENTITIES.contains(entity.getType()); + return entity instanceof ChestBoat || INTERACTABLE_ENTITIES.contains(entityType); } public static boolean willConsume(Player player, BlockData state, BlockHitResult hit, @Nullable Item item) { @@ -365,7 +369,7 @@ public class InteractUtils { return false; } } - + private static boolean canEat(Player player, boolean ignoreHunger) { return ignoreHunger || player.isInvulnerable() || player.getFoodLevel() < 20; } 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 62ab60190..6028485a4 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 @@ -17,7 +17,6 @@ public class ItemTags { public static final Key AXES = Key.of("minecraft:axes"); public static final Key SWORDS = Key.of("minecraft:swords"); - public static final Tag ITEMS_HARNESSES = getHarnessTag(); private ItemTags() {} @@ -29,13 +28,4 @@ public class ItemTags { } return value; } - - public static Tag getHarnessTag() { - if (!VersionHelper.isOrAbove1_21_6()) return null; - try { - return Bukkit.getTag("items", NamespacedKey.minecraft("harnesses"), Material.class); - } catch (Exception e) { - return null; - } - } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/entity/EntityKeys.java b/core/src/main/java/net/momirealms/craftengine/core/entity/EntityKeys.java new file mode 100644 index 000000000..4b34d4c20 --- /dev/null +++ b/core/src/main/java/net/momirealms/craftengine/core/entity/EntityKeys.java @@ -0,0 +1,34 @@ +package net.momirealms.craftengine.core.entity; + +import net.momirealms.craftengine.core.util.Key; + +public class EntityKeys { + private EntityKeys() {} + + public static final Key ALLAY = Key.of("minecraft:ALLAY"); + public static final Key HORSE = Key.of("minecraft:HORSE"); + public static final Key ZOMBIE_HORSE = Key.of("minecraft:ZOMBIE_HORSE"); + public static final Key SKELETON_HORSE = Key.of("minecraft:SKELETON_HORSE"); + public static final Key DONKEY = Key.of("minecraft:DONKEY"); + public static final Key MULE = Key.of("minecraft:MULE"); + public static final Key VILLAGER = Key.of("minecraft:VILLAGER"); + public static final Key WANDERING_TRADER = Key.of("minecraft:WANDERING_TRADER"); + public static final Key LLAMA = Key.of("minecraft:LLAMA"); + public static final Key TRADER_LLAMA = Key.of("minecraft:TRADER_LLAMA"); + public static final Key CAMEL = Key.of("minecraft:CAMEL"); + public static final Key ITEM_FRAME = Key.of("minecraft:ITEM_FRAME"); + public static final Key GLOW_ITEM_FRAME = Key.of("minecraft:GLOW_ITEM_FRAME"); + public static final Key INTERACTION = Key.of("minecraft:INTERACTION"); + // ≥1.20.5 + public static final Key CHEST_MINECART = Key.of("minecraft:CHEST_MINECART"); + public static final Key FURNACE_MINECART = Key.of("minecraft:FURNACE_MINECART"); + public static final Key HOPPER_MINECART = Key.of("minecraft:HOPPER_MINECART"); + public static final Key COMMAND_BLOCK_MINECART = Key.of("minecraft:COMMAND_BLOCK_MINECART"); + // <1.20.5 + public static final Key MINECART_CHEST = Key.of("minecraft:MINECART_CHEST"); + public static final Key MINECART_FURNACE = Key.of("minecraft:MINECART_FURNACE"); + public static final Key MINECART_HOPPER = Key.of("minecraft:MINECART_HOPPER"); + public static final Key MINECART_COMMAND = Key.of("minecraft:MINECART_COMMAND"); + // ≥1.21.6 + public static final Key HAPPY_GHAST = Key.of("minecraft:HAPPY_GHAST"); +}