mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-30 04:19:27 +00:00
Add support for Happy Ghast and harness interactions
Introduces logic for handling Happy Ghast entity interactions and harness item tags, gated by Minecraft version 1.21.6. Refactors entity and block interaction checks to use new utility methods and dynamic entity sets, improving maintainability and future compatibility.
This commit is contained in:
@@ -34,6 +34,8 @@ import org.bukkit.GameMode;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockState;
|
||||
import org.bukkit.block.ChiseledBookshelf;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Openable;
|
||||
import org.bukkit.entity.Entity;
|
||||
@@ -53,10 +55,7 @@ import org.bukkit.inventory.EnchantingInventory;
|
||||
import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
public class ItemEventListener implements Listener {
|
||||
private final BukkitCraftEngine plugin;
|
||||
@@ -280,12 +279,12 @@ public class ItemEventListener implements Listener {
|
||||
.withParameter(DirectContextParameters.EVENT, dummy)
|
||||
);
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
if (!InteractUtils.isInteractable(player, blockData, hitResult, null)) {
|
||||
if (!InteractUtils.isInteractable(player, blockData, hitResult, itemInHand) && !player.isSneaking()) {
|
||||
customItem.execute(context, EventTrigger.RIGHT_CLICK);
|
||||
if (dummy.isCancelled()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (dummy.isCancelled()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,14 +2,17 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
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.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;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -34,4 +37,24 @@ public class EntityUtils {
|
||||
return LegacyEntityUtils.spawnEntity(world, loc, type, function);
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isPiglinWithGoldIngot(Entity entity, Item<ItemStack> item) {
|
||||
return entity.getType() == EntityType.PIGLIN &&
|
||||
item != null &&
|
||||
item.vanillaId().equals(Key.of("minecraft:gold_ingot"));
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
public static boolean hasHarness(EntityEquipment equipment) {
|
||||
ItemStack bodyItem = equipment.getItem(EquipmentSlot.BODY);
|
||||
return ItemTags.ITEMS_HARNESSES != null &&
|
||||
ItemTags.ITEMS_HARNESSES.isTagged(bodyItem.getType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,23 +12,25 @@ import net.momirealms.craftengine.core.plugin.config.Config;
|
||||
import net.momirealms.craftengine.core.util.Direction;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.QuadFunction;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
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.block.data.type.ChiseledBookshelf;
|
||||
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;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
public class InteractUtils {
|
||||
private static final Map<Key, QuadFunction<Player, Item<ItemStack>, BlockData, BlockHitResult, Boolean>> INTERACTIONS = new HashMap<>();
|
||||
private static final Map<Key, QuadFunction<Player, Item<ItemStack>, 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<EntityType> INTERACTABLE_ENTITIES = createInteractableEntities();
|
||||
|
||||
private InteractUtils() {}
|
||||
|
||||
@@ -90,7 +92,15 @@ public class InteractUtils {
|
||||
item.recipeIngredientId(), item
|
||||
))) != null;
|
||||
});
|
||||
registerInteraction(BlockKeys.CHISELED_BOOKSHELF, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.CHISELED_BOOKSHELF, (player, item, blockState, result) -> {
|
||||
Direction direction = result.getDirection();
|
||||
if (player.isSneaking()) return false;
|
||||
if (blockState instanceof ChiseledBookshelf chiseledBookshelf) {
|
||||
Direction facing = DirectionUtils.toDirection(chiseledBookshelf.getFacing());
|
||||
return facing == direction;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
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);
|
||||
@@ -279,7 +289,9 @@ public class InteractUtils {
|
||||
result.getDirection() == Direction.UP && item.id().equals(ItemKeys.CACTUS));
|
||||
}
|
||||
|
||||
private static final Set<EntityType> INTERACTABLE_ENTITIES = Set.of(
|
||||
private static Set<EntityType> createInteractableEntities() {
|
||||
Set<EntityType> set = EnumSet.noneOf(EntityType.class);
|
||||
set.addAll(Set.of(
|
||||
EntityType.ALLAY,
|
||||
EntityType.HORSE,
|
||||
EntityType.ZOMBIE_HORSE,
|
||||
@@ -296,9 +308,17 @@ public class InteractUtils {
|
||||
EntityType.HOPPER_MINECART,
|
||||
EntityType.COMMAND_BLOCK_MINECART,
|
||||
EntityType.ITEM_FRAME,
|
||||
EntityType.GLOW_ITEM_FRAME,
|
||||
EntityType.HAPPY_GHAST
|
||||
);
|
||||
EntityType.GLOW_ITEM_FRAME
|
||||
));
|
||||
if (VersionHelper.isOrAbove1_21_6()) {
|
||||
try {
|
||||
Field happyGhastField = EntityType.class.getField("HAPPY_GHAST");
|
||||
EntityType happyGhast = (EntityType) happyGhastField.get(null);
|
||||
set.add(happyGhast);
|
||||
} catch (NoSuchFieldException | IllegalAccessException ignored) {}
|
||||
}
|
||||
return Collections.unmodifiableSet(set);
|
||||
}
|
||||
|
||||
private static void registerInteraction(Key key, QuadFunction<org.bukkit.entity.Player, Item<ItemStack>, BlockData, BlockHitResult, Boolean> function) {
|
||||
var previous = INTERACTIONS.put(key, function);
|
||||
@@ -325,9 +345,10 @@ 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"))) {
|
||||
if (EntityUtils.isPiglinWithGoldIngot(entity, item)) {
|
||||
return true;
|
||||
}
|
||||
if (EntityUtils.isHappyGhastRideable(entity) && !isSneaking) {
|
||||
return true;
|
||||
}
|
||||
return switch (entity) {
|
||||
|
||||
@@ -3,6 +3,11 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MRegistries;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.NamespacedKey;
|
||||
import org.bukkit.Tag;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -12,6 +17,7 @@ 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<Material> ITEMS_HARNESSES = getHarnessTag();
|
||||
|
||||
private ItemTags() {}
|
||||
|
||||
@@ -23,4 +29,13 @@ public class ItemTags {
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Tag<Material> getHarnessTag() {
|
||||
if (!VersionHelper.isOrAbove1_21_6()) return null;
|
||||
try {
|
||||
return Bukkit.getTag("items", NamespacedKey.minecraft("harnesses"), Material.class);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user