mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2026-01-04 15:41:38 +00:00
解决吃食物等行为与原版方块放置行为的冲突
This commit is contained in:
@@ -21,6 +21,7 @@ import net.momirealms.craftengine.core.item.CustomItem;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemBuildContext;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.item.setting.FoodData;
|
||||
import net.momirealms.craftengine.core.item.updater.ItemUpdateResult;
|
||||
@@ -141,7 +142,7 @@ public class ItemEventListener implements Listener {
|
||||
Direction direction = DirectionUtils.toDirection(event.getBlockFace());
|
||||
BlockPos pos = LocationUtils.toBlockPos(block.getLocation());
|
||||
Vec3d vec3d = new Vec3d(interactionPoint.getX(), interactionPoint.getY(), interactionPoint.getZ());
|
||||
hitResult = new BlockHitResult(vec3d, direction, pos, false);
|
||||
hitResult = new BlockHitResult(vec3d, direction, pos, false); // todo 需要检测玩家是否在方块内
|
||||
}
|
||||
|
||||
// 处理自定义方块
|
||||
@@ -165,9 +166,8 @@ public class ItemEventListener implements Listener {
|
||||
|
||||
// fix client side issues
|
||||
if (action.isRightClick() && hitResult != null &&
|
||||
InteractUtils.canPlace(player, BlockStateUtils.fromBlockData(immutableBlockState.vanillaBlockState().literalObject()), hitResult, itemInHand)) {
|
||||
InteractUtils.canPlaceVisualBlock(player, BlockStateUtils.fromBlockData(immutableBlockState.vanillaBlockState().literalObject()), hitResult, itemInHand)) {
|
||||
player.updateInventory();
|
||||
//PlayerUtils.resendItemInHand(player);
|
||||
}
|
||||
|
||||
Cancellable dummy = Cancellable.dummy();
|
||||
@@ -288,8 +288,9 @@ public class ItemEventListener implements Listener {
|
||||
if (optionalCustomItem.get().settings().disableVanillaBehavior()) {
|
||||
// 允许尝试放置方块
|
||||
if (serverPlayer.isSecondaryUseActive() || !InteractUtils.isInteractable(player, blockData, hitResult, itemInHand)) {
|
||||
// todo 检测不可以放置方块
|
||||
event.setCancelled(true);
|
||||
if (InteractUtils.canPlaceBlock(new BlockPlaceContext(new UseOnContext(serverPlayer, hand, itemInHand, hitResult)))) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,14 @@ import java.util.Optional;
|
||||
public final class BlockStateUtils {
|
||||
private BlockStateUtils() {}
|
||||
|
||||
public static boolean isTag(BlockData blockData, Key tag) {
|
||||
return isTag(blockDataToBlockState(blockData), tag);
|
||||
}
|
||||
|
||||
public static boolean isTag(Object blockState, Key tag) {
|
||||
return FastNMS.INSTANCE.method$BlockStateBase$is(blockState, BlockTags.getOrCreate(tag));
|
||||
}
|
||||
|
||||
public static BlockStateWrapper toBlockStateWrapper(BlockData blockData) {
|
||||
Object state = blockDataToBlockState(blockData);
|
||||
return toBlockStateWrapper(state);
|
||||
|
||||
@@ -5,13 +5,17 @@ import net.momirealms.craftengine.bukkit.item.BukkitItemManager;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.BlockItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.FlintAndSteelItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitExistingBlock;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitWorld;
|
||||
import net.momirealms.craftengine.core.block.BlockKeys;
|
||||
import net.momirealms.craftengine.core.entity.EntityTypeKeys;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionHand;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.item.ItemKeys;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.context.BlockPlaceContext;
|
||||
import net.momirealms.craftengine.core.item.modifier.AttributeModifiersModifier;
|
||||
import net.momirealms.craftengine.core.item.recipe.RecipeType;
|
||||
import net.momirealms.craftengine.core.item.recipe.UniqueIdItem;
|
||||
@@ -712,7 +716,6 @@ public final class InteractUtils {
|
||||
registerInteraction(BlockKeys.WARPED_WALL_HANGING_SIGN, (player, item, blockState, result) -> true);
|
||||
}
|
||||
|
||||
// 消耗
|
||||
static {
|
||||
registerCanPlace(BlockKeys.CACTUS, (player, item, blockState, result) -> {
|
||||
Key id = item.vanillaId();
|
||||
@@ -936,7 +939,7 @@ public final class InteractUtils {
|
||||
private static void registerCanPlace(Key key, QuadFunction<org.bukkit.entity.Player, Item<ItemStack>, BlockData, BlockHitResult, Boolean> function) {
|
||||
var previous = CAN_PLACE.put(key, function);
|
||||
if (previous != null) {
|
||||
CraftEngine.instance().logger().warn("Duplicated interaction check: " + key);
|
||||
CraftEngine.instance().logger().warn("Duplicated can place check: " + key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -955,8 +958,9 @@ public final class InteractUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 这个方法用于解决玩家使用仙人掌放在基于仙人掌的方块上,物品暂时消失的类似问题
|
||||
public static boolean canPlace(Player player, BlockData state, BlockHitResult hit, @Nullable Item<ItemStack> item) {
|
||||
// 这个方法用于解决玩家使用仙人掌放在基于仙人掌的方块上,物品暂时消失的类似问题,但是无法彻底解决
|
||||
// todo 需要通过创建代理Level来实现getBlockState的方法拦截,从而实现模拟客户端测的方块状态更新,这个过程可能也需要创建代理Chunk和代理Section
|
||||
public static boolean canPlaceVisualBlock(Player player, BlockData state, BlockHitResult hit, @Nullable Item<ItemStack> item) {
|
||||
if (item == null) return false;
|
||||
Key blockType = BlockStateUtils.getBlockOwnerIdFromData(state);
|
||||
if (CAN_PLACE.containsKey(blockType)) {
|
||||
@@ -1046,4 +1050,30 @@ public final class InteractUtils {
|
||||
Key id = item.vanillaId();
|
||||
return entity instanceof Shearable shearable && shearable.readyToBeSheared() && ItemKeys.SHEARS.equals(id);
|
||||
}
|
||||
|
||||
public static boolean canPlaceBlock(BlockPlaceContext context) {
|
||||
Object item = FastNMS.INSTANCE.method$ItemStack$getItem(context.getItem().getLiteralObject());
|
||||
Object block = FastNMS.INSTANCE.method$BlockItem$getBlock(item);
|
||||
Object stateToPlace = FastNMS.INSTANCE.method$Block$getStateForPlacement(block, toNMSBlockPlaceContext(context));
|
||||
return FastNMS.INSTANCE.method$BlockStateBase$canSurvive(stateToPlace, context.getLevel().serverWorld(), LocationUtils.toBlockPos(context.getClickedPos()));
|
||||
}
|
||||
|
||||
private static Object toNMSHitResult(BlockHitResult result) {
|
||||
return FastNMS.INSTANCE.constructor$BlockHitResult(
|
||||
LocationUtils.toVec(result.getLocation()),
|
||||
DirectionUtils.toNMSDirection(result.getDirection()),
|
||||
LocationUtils.toBlockPos(result.getBlockPos()),
|
||||
result.isInside()
|
||||
);
|
||||
}
|
||||
|
||||
private static Object toNMSBlockPlaceContext(BlockPlaceContext context) {
|
||||
return FastNMS.INSTANCE.constructor$BlockPlaceContext(
|
||||
context.getLevel().serverWorld(),
|
||||
Optional.ofNullable(context.getPlayer()).map(net.momirealms.craftengine.core.entity.player.Player::serverPlayer).orElse(null),
|
||||
context.getHand() == InteractionHand.MAIN_HAND ? CoreReflections.instance$InteractionHand$MAIN_HAND : CoreReflections.instance$InteractionHand$OFF_HAND,
|
||||
context.getItem().getLiteralObject(),
|
||||
toNMSHitResult(context.getHitResult())
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,10 @@ public final class LocationUtils {
|
||||
return new WorldPosition(new BukkitWorld(location.getWorld()), location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
|
||||
}
|
||||
|
||||
public static Object toVec(Vec3d vec) {
|
||||
return FastNMS.INSTANCE.constructor$Vec3(vec.x, vec.y, vec.z);
|
||||
}
|
||||
|
||||
public static Vec3d toVec3d(Location loc) {
|
||||
return new Vec3d(loc.getX(), loc.getY(), loc.getZ());
|
||||
}
|
||||
|
||||
@@ -107,6 +107,12 @@ public class BukkitExistingBlock implements ExistingBlock {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean is(Key tag) {
|
||||
Object state = FastNMS.INSTANCE.method$BlockGetter$getBlockState(FastNMS.INSTANCE.field$CraftWorld$ServerLevel(block.getWorld()), LocationUtils.toBlockPos(block.getX(), block.getY(), block.getZ()));
|
||||
return BlockStateUtils.isTag(state, tag);
|
||||
}
|
||||
|
||||
public Block block() {
|
||||
return this.block;
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ public final class BlockKeys {
|
||||
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 LECTERN = Key.of("minecraft:lectern");
|
||||
public static final Key FARMLAND = Key.of("minecraft:farmland");
|
||||
|
||||
public static final Key CHEST = Key.of("minecraft:chest");
|
||||
public static final Key BARREL = Key.of("minecraft:barrel");
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
package net.momirealms.craftengine.core.block;
|
||||
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
|
||||
public final class BlockTagKeys {
|
||||
private BlockTagKeys() {}
|
||||
|
||||
public static final Key DIRT = Key.of("minecraft:dirt");
|
||||
}
|
||||
@@ -66,6 +66,13 @@ public final class ItemKeys {
|
||||
public static final Key MAGENTA_DYE = Key.of("minecraft:magenta_dye");
|
||||
public static final Key PINK_DYE = Key.of("minecraft:pink_dye");
|
||||
|
||||
public static final Key CARROT = Key.of("minecraft:carrot");
|
||||
public static final Key POTATO = Key.of("minecraft:potato");
|
||||
public static final Key BEETROOT_SEEDS = Key.of("minecraft:beetroot_seeds");
|
||||
public static final Key WHEAT_SEEDS = Key.of("minecraft:wheat_seeds");
|
||||
public static final Key SWEET_BERRIES = Key.of("minecraft:sweet_berries");
|
||||
public static final Key GLOW_BERRIES = Key.of("minecraft:glow_berries");
|
||||
|
||||
public static final Key[] AXES = new Key[] {WOODEN_AXE, STONE_AXE, IRON_AXE, GOLDEN_AXE, DIAMOND_AXE, NETHERITE_AXE};
|
||||
|
||||
public static final Key[] WATER_BUCKETS = new Key[] {WATER_BUCKET, COD_BUCKET, SALMON_BUCKET, TROPICAL_FISH_BUCKET, TADPOLE_BUCKET, PUFFERFISH_BUCKET, AXOLOTL_BUCKET};
|
||||
|
||||
@@ -40,6 +40,10 @@ public class BlockPos extends Vec3i {
|
||||
return new BlockPos(this.x(), this.y() + 1, this.z());
|
||||
}
|
||||
|
||||
public BlockPos below() {
|
||||
return new BlockPos(this.x(), this.y() - 1, this.z());
|
||||
}
|
||||
|
||||
public int toSectionBlockIndex() {
|
||||
return (y & 15) << 8 | (z & 15) << 4 | x & 15;
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ public interface ExistingBlock {
|
||||
return new WorldPosition(world(), x(), y(), z());
|
||||
}
|
||||
|
||||
boolean is(Key tag);
|
||||
|
||||
World world();
|
||||
|
||||
Key id();
|
||||
|
||||
@@ -50,7 +50,7 @@ byte_buddy_version=1.17.5
|
||||
ahocorasick_version=0.6.3
|
||||
snake_yaml_version=2.5
|
||||
anti_grief_version=1.0.2
|
||||
nms_helper_version=1.0.109
|
||||
nms_helper_version=1.0.112
|
||||
evalex_version=3.5.0
|
||||
reactive_streams_version=1.0.4
|
||||
amazon_awssdk_version=2.34.5
|
||||
|
||||
Reference in New Issue
Block a user