mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-30 04:19:27 +00:00
稍微改进一下
This commit is contained in:
@@ -77,6 +77,7 @@ public class ItemEventListener implements Listener {
|
||||
if (ItemUtils.isEmpty(itemInHand)) return;
|
||||
Optional<CustomItem<ItemStack>> optionalCustomItem = itemInHand.getCustomItem();
|
||||
if (optionalCustomItem.isEmpty()) return;
|
||||
// 如果目标实体与手中物品可以产生交互,那么忽略
|
||||
if (InteractUtils.isEntityInteractable(player, entity, itemInHand)) return;
|
||||
|
||||
Cancellable cancellable = Cancellable.of(event::isCancelled, event::setCancelled);
|
||||
@@ -267,27 +268,7 @@ public class ItemEventListener implements Listener {
|
||||
}
|
||||
}
|
||||
|
||||
// execute item right click functions
|
||||
if (hasCustomItem) {
|
||||
Cancellable dummy = Cancellable.dummy();
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block))
|
||||
.withOptionalParameter(DirectContextParameters.CUSTOM_BLOCK_STATE, immutableBlockState)
|
||||
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
|
||||
.withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(block.getLocation()))
|
||||
.withParameter(DirectContextParameters.HAND, hand)
|
||||
.withParameter(DirectContextParameters.EVENT, dummy)
|
||||
);
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
if (!(InteractUtils.isInteractable(player, blockData, hitResult, itemInHand) && !player.isSneaking())) {
|
||||
customItem.execute(context, EventTrigger.RIGHT_CLICK);
|
||||
}
|
||||
if (dummy.isCancelled()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 优先检查物品行为,再执行自定义事件
|
||||
// 检查其他的物品行为,物品行为理论只在交互时处理
|
||||
Optional<List<ItemBehavior>> optionalItemBehaviors = itemInHand.getItemBehavior();
|
||||
// 物品类型是否包含自定义物品行为,行为不一定来自于自定义物品,部分原版物品也包含了新的行为
|
||||
@@ -315,8 +296,31 @@ public class ItemEventListener implements Listener {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 执行物品右键事件
|
||||
if (hasCustomItem) {
|
||||
// 要求服务端侧这个方块不可交互,或玩家处于潜行状态
|
||||
if (serverPlayer.isSecondaryUseActive() || !InteractUtils.isInteractable(player, blockData, hitResult, itemInHand)) {
|
||||
Cancellable dummy = Cancellable.dummy();
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.BLOCK, new BukkitBlockInWorld(block))
|
||||
.withOptionalParameter(DirectContextParameters.CUSTOM_BLOCK_STATE, immutableBlockState)
|
||||
.withOptionalParameter(DirectContextParameters.ITEM_IN_HAND, itemInHand)
|
||||
.withParameter(DirectContextParameters.POSITION, LocationUtils.toWorldPosition(block.getLocation()))
|
||||
.withParameter(DirectContextParameters.HAND, hand)
|
||||
.withParameter(DirectContextParameters.EVENT, dummy)
|
||||
);
|
||||
CustomItem<ItemStack> customItem = optionalCustomItem.get();
|
||||
customItem.execute(context, EventTrigger.RIGHT_CLICK);
|
||||
if (dummy.isCancelled()) {
|
||||
event.setCancelled(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 执行物品左键事件
|
||||
if (hasCustomItem && action == Action.LEFT_CLICK_BLOCK) {
|
||||
Cancellable dummy = Cancellable.dummy();
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||
|
||||
@@ -3,6 +3,7 @@ package net.momirealms.craftengine.bukkit.plugin.classpath;
|
||||
import net.momirealms.craftengine.core.plugin.classpath.ClassPathAppender;
|
||||
import net.momirealms.craftengine.core.plugin.classpath.URLClassLoaderAccess;
|
||||
import net.momirealms.craftengine.core.util.ReflectionUtils;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.MalformedURLException;
|
||||
@@ -20,18 +21,20 @@ public class PaperClassPathAppender implements ClassPathAppender {
|
||||
private final URLClassLoaderAccess classLoaderAccess;
|
||||
|
||||
public PaperClassPathAppender(ClassLoader classLoader) {
|
||||
try {
|
||||
if (clazz$PaperPluginClassLoader != null && clazz$PaperPluginClassLoader.isInstance(classLoader)) {
|
||||
URLClassLoader libraryClassLoader = (URLClassLoader) field$PaperPluginClassLoader$libraryLoader.get(classLoader);
|
||||
this.classLoaderAccess = URLClassLoaderAccess.create(libraryClassLoader);
|
||||
} else if (classLoader instanceof URLClassLoader) {
|
||||
this.classLoaderAccess = URLClassLoaderAccess.create((URLClassLoader) classLoader);
|
||||
} else {
|
||||
throw new IllegalStateException("ClassLoader is not instance of URLClassLoader");
|
||||
}
|
||||
} catch (ReflectiveOperationException e) {
|
||||
throw new RuntimeException("Failed to instantiate PaperPluginClassLoader", e);
|
||||
}
|
||||
// 25/7/26 往Bukkit类加载器里硬灌,就能保证库也被其他插件使用了
|
||||
this.classLoaderAccess = URLClassLoaderAccess.create((URLClassLoader) Bukkit.class.getClassLoader());
|
||||
// try {
|
||||
// if (clazz$PaperPluginClassLoader != null && clazz$PaperPluginClassLoader.isInstance(classLoader)) {
|
||||
// URLClassLoader libraryClassLoader = (URLClassLoader) field$PaperPluginClassLoader$libraryLoader.get(classLoader);
|
||||
// this.classLoaderAccess = URLClassLoaderAccess.create(libraryClassLoader);
|
||||
// } else if (classLoader instanceof URLClassLoader) {
|
||||
// this.classLoaderAccess = URLClassLoaderAccess.create((URLClassLoader) classLoader);
|
||||
// } else {
|
||||
// throw new IllegalStateException("ClassLoader is not instance of URLClassLoader");
|
||||
// }
|
||||
// } catch (ReflectiveOperationException e) {
|
||||
// throw new RuntimeException("Failed to instantiate PaperPluginClassLoader", e);
|
||||
// }
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -6,7 +6,9 @@ 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.*;
|
||||
import org.bukkit.entity.Entity;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.event.entity.CreatureSpawnEvent;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
@@ -4,6 +4,8 @@ import io.papermc.paper.entity.Shearable;
|
||||
import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BlockItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBuiltInRegistries;
|
||||
import net.momirealms.craftengine.core.block.BlockKeys;
|
||||
import net.momirealms.craftengine.core.entity.EntityTypeKeys;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
@@ -28,7 +30,10 @@ import org.bukkit.inventory.EquipmentSlot;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
public class InteractUtils {
|
||||
private static final Map<Key, QuadFunction<Player, Item<ItemStack>, BlockData, BlockHitResult, Boolean>> INTERACTIONS = new HashMap<>();
|
||||
@@ -67,11 +72,15 @@ public class InteractUtils {
|
||||
registerInteraction(BlockKeys.TEST_BLOCK, (player, item, blockState, result) -> player.isOp() && player.getGameMode() == GameMode.CREATIVE);
|
||||
registerInteraction(BlockKeys.LIGHT, (player, item, blockState, result) -> item.vanillaId().equals(ItemKeys.LIGHT));
|
||||
registerInteraction(BlockKeys.LODESTONE, (player, item, blockState, result) -> item.vanillaId().equals(ItemKeys.COMPASS));
|
||||
registerInteraction(BlockKeys.BEE_NEST, (player, item, blockState, result) -> Set.of(ItemKeys.SHEARS, ItemKeys.GLASS_BOTTLE).contains(item.vanillaId()));
|
||||
registerInteraction(BlockKeys.BEEHIVE, (player, item, blockState, result) -> Set.of(ItemKeys.SHEARS, ItemKeys.GLASS_BOTTLE).contains(item.vanillaId()));
|
||||
registerInteraction(BlockKeys.BEE_NEST, (player, item, blockState, result) -> {
|
||||
Key id = item.vanillaId();
|
||||
return ItemKeys.SHEARS.equals(id) || ItemKeys.GLASS_BOTTLE.equals(id);
|
||||
});
|
||||
registerInteraction(BlockKeys.BEEHIVE, (player, item, blockState, result) -> {
|
||||
Key id = item.vanillaId();
|
||||
return ItemKeys.SHEARS.equals(id) || ItemKeys.GLASS_BOTTLE.equals(id);
|
||||
});
|
||||
registerInteraction(BlockKeys.POWDER_SNOW, (player, item, blockState, result) -> item.vanillaId().equals(ItemKeys.BUCKET));
|
||||
registerWillConsume(BlockKeys.CAULDRON, (player, item, blockState, result) -> Set.of(ItemKeys.WATER_BUCKET, ItemKeys.LAVA_BUCKET).contains(item.vanillaId()));
|
||||
registerWillConsume(BlockKeys.LAVA_CAULDRON, (player, item, blockState, result) -> Set.of(ItemKeys.BUCKET, ItemKeys.WATER_BUCKET, ItemKeys.LAVA_BUCKET).contains(item.vanillaId()));
|
||||
registerInteraction(BlockKeys.REDSTONE_ORE, (player, item, blockState, result) -> {
|
||||
Optional<List<ItemBehavior>> behaviors = item.getItemBehavior();
|
||||
if (behaviors.isPresent()) {
|
||||
@@ -90,11 +99,7 @@ public class InteractUtils {
|
||||
}
|
||||
return true;
|
||||
});
|
||||
registerWillConsume(BlockKeys.WATER_CAULDRON, (player, item, blockState, result) -> {
|
||||
if (blockState instanceof Levelled levelled && levelled.getLevel() == levelled.getMaximumLevel())
|
||||
return item.vanillaId().equals(ItemKeys.BUCKET);
|
||||
return Set.of(ItemKeys.GLASS_BOTTLE, ItemKeys.WATER_BUCKET, ItemKeys.LAVA_BUCKET).contains(item.vanillaId());
|
||||
});
|
||||
|
||||
registerInteraction(BlockKeys.BELL, (player, item, blockState, result) -> {
|
||||
Direction direction = result.getDirection();
|
||||
BlockPos pos = result.getBlockPos();
|
||||
@@ -327,6 +332,20 @@ public class InteractUtils {
|
||||
static {
|
||||
registerWillConsume(BlockKeys.CACTUS, (player, item, blockState, result) ->
|
||||
result.getDirection() == Direction.UP && item.id().equals(ItemKeys.CACTUS));
|
||||
registerWillConsume(BlockKeys.CAULDRON, (player, item, blockState, result) -> {
|
||||
Key id = item.vanillaId();
|
||||
return ItemKeys.WATER_BUCKET.equals(id) || ItemKeys.LAVA_BUCKET.equals(id);
|
||||
});
|
||||
registerWillConsume(BlockKeys.LAVA_CAULDRON, (player, item, blockState, result) -> {
|
||||
Key id = item.vanillaId();
|
||||
return ItemKeys.BUCKET.equals(id) || ItemKeys.LAVA_BUCKET.equals(id) || ItemKeys.WATER_BUCKET.equals(id);
|
||||
});
|
||||
registerWillConsume(BlockKeys.WATER_CAULDRON, (player, item, blockState, result) -> {
|
||||
if (blockState instanceof Levelled levelled && levelled.getLevel() == levelled.getMaximumLevel())
|
||||
return item.vanillaId().equals(ItemKeys.BUCKET);
|
||||
Key id = item.vanillaId();
|
||||
return ItemKeys.GLASS_BOTTLE.equals(id) || ItemKeys.WATER_BUCKET.equals(id) || ItemKeys.LAVA_BUCKET.equals(id);
|
||||
});
|
||||
}
|
||||
|
||||
static {
|
||||
@@ -466,8 +485,10 @@ public class InteractUtils {
|
||||
}
|
||||
|
||||
public static boolean isEntityInteractable(Player player, Entity entity, @Nullable Item<ItemStack> item) {
|
||||
Key key = Key.of(String.valueOf(entity.getType()));
|
||||
TriFunction<Player, Entity, Item<ItemStack>, Boolean> func = ENTITY_INTERACTIONS.get(key);
|
||||
Object nmsEntity = FastNMS.INSTANCE.method$CraftEntity$getHandle(entity);
|
||||
Object entityType = FastNMS.INSTANCE.method$Entity$getType(nmsEntity);
|
||||
Object id = FastNMS.INSTANCE.method$Registry$getKey(MBuiltInRegistries.ENTITY_TYPE, entityType);
|
||||
TriFunction<Player, Entity, Item<ItemStack>, Boolean> func = ENTITY_INTERACTIONS.get(KeyUtils.resourceLocationToKey(id));
|
||||
return func != null && func.apply(player, entity, item);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,11 +3,6 @@ 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;
|
||||
|
||||
Reference in New Issue
Block a user