mirror of
https://github.com/Xiao-MoMi/craft-engine.git
synced 2025-12-27 10:59:07 +00:00
添加物品行为,修正方块交互
This commit is contained in:
@@ -4,8 +4,7 @@ import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.AxeItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.FlintAndSteelItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.*;
|
||||
import net.momirealms.craftengine.bukkit.item.factory.BukkitItemFactory;
|
||||
import net.momirealms.craftengine.bukkit.item.listener.ArmorEventListener;
|
||||
import net.momirealms.craftengine.bukkit.item.listener.DebugStickListener;
|
||||
@@ -41,6 +40,9 @@ public class BukkitItemManager extends AbstractItemManager<ItemStack> {
|
||||
static {
|
||||
registerVanillaItemExtraBehavior(FlintAndSteelItemBehavior.INSTANCE, ItemKeys.FLINT_AND_STEEL);
|
||||
registerVanillaItemExtraBehavior(AxeItemBehavior.INSTANCE, ItemKeys.AXES);
|
||||
registerVanillaItemExtraBehavior(CompassItemBehavior.INSTANCE, ItemKeys.COMPASS);
|
||||
registerVanillaItemExtraBehavior(EnderEyeItemBehavior.INSTANCE, ItemKeys.ENDER_EYE);
|
||||
registerVanillaItemExtraBehavior(EndCrystalItemBehavior.INSTANCE, ItemKeys.END_CRYSTAL);
|
||||
}
|
||||
|
||||
private static BukkitItemManager instance;
|
||||
|
||||
@@ -108,10 +108,7 @@ public class AxeItemBehavior extends ItemBehavior {
|
||||
if (!InteractUtils.isInteractable(
|
||||
bukkitPlayer, BlockStateUtils.fromBlockData(customState.vanillaBlockState().literalObject()),
|
||||
context.getHitResult(), item
|
||||
) || (player.isSecondaryUseActive() && !InteractUtils.isIgnoreSneaking(
|
||||
bukkitPlayer, BlockStateUtils.fromBlockData(customState.vanillaBlockState().literalObject()),
|
||||
context.getHitResult(), item
|
||||
))) {
|
||||
) || player.isSecondaryUseActive()) {
|
||||
player.swingHand(context.getHand());
|
||||
}
|
||||
// shrink item amount
|
||||
|
||||
@@ -12,6 +12,9 @@ public class BukkitItemBehaviors extends ItemBehaviors {
|
||||
public static final Key COMPOSTABLE_ITEM = Key.from("craftengine:compostable_item");
|
||||
public static final Key AXE_ITEM = Key.from("craftengine:axe_item");
|
||||
public static final Key DOUBLE_HIGH_BLOCK_ITEM = Key.from("craftengine:double_high_block_item");
|
||||
public static final Key COMPASS_ITEM = Key.from("craftengine:compass_item");
|
||||
public static final Key ENDER_EYE_ITEM = Key.from("craftengine:ender_eye_item");
|
||||
public static final Key END_CRYSTAL_ITEM = Key.from("craftengine:end_crystal_item");
|
||||
|
||||
public static void init() {
|
||||
register(EMPTY, EmptyItemBehavior.FACTORY);
|
||||
@@ -22,5 +25,8 @@ public class BukkitItemBehaviors extends ItemBehaviors {
|
||||
register(COMPOSTABLE_ITEM, CompostableItemBehavior.FACTORY);
|
||||
register(AXE_ITEM, AxeItemBehavior.FACTORY);
|
||||
register(DOUBLE_HIGH_BLOCK_ITEM, DoubleHighBlockItemBehavior.FACTORY);
|
||||
register(COMPASS_ITEM, CompassItemBehavior.FACTORY);
|
||||
register(ENDER_EYE_ITEM, EnderEyeItemBehavior.FACTORY);
|
||||
register(END_CRYSTAL_ITEM, EndCrystalItemBehavior.FACTORY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package net.momirealms.craftengine.bukkit.item.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitExistingBlock;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
public class CompassItemBehavior extends ItemBehavior {
|
||||
public static final CompassItemBehavior INSTANCE = new CompassItemBehavior();
|
||||
public static final CompassItemBehavior.Factory FACTORY = new CompassItemBehavior.Factory();
|
||||
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context) {
|
||||
BukkitExistingBlock block = (BukkitExistingBlock) context.getLevel().getBlockAt(context.getClickedPos());
|
||||
BlockData blockData = block.block().getBlockData();
|
||||
Object blockOwner = BlockStateUtils.getBlockOwner(BlockStateUtils.blockDataToBlockState(blockData));
|
||||
|
||||
if (blockOwner != MBlocks.LODESTONE) {
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements ItemBehaviorFactory {
|
||||
@Override
|
||||
public ItemBehavior create(Pack pack, Path path, Key id, Map<String, Object> arguments) {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package net.momirealms.craftengine.bukkit.item.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitExistingBlock;
|
||||
import net.momirealms.craftengine.core.entity.Entity;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.World;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class EndCrystalItemBehavior extends ItemBehavior {
|
||||
public static final EndCrystalItemBehavior INSTANCE = new EndCrystalItemBehavior();
|
||||
public static final EndCrystalItemBehavior.Factory FACTORY = new EndCrystalItemBehavior.Factory();
|
||||
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context) {
|
||||
World world = context.getLevel();
|
||||
BlockPos blockPos = context.getClickedPos();
|
||||
BukkitExistingBlock block = (BukkitExistingBlock) world.getBlockAt(blockPos);
|
||||
BlockData blockData = block.block().getBlockData();
|
||||
Object blockOwner = BlockStateUtils.getBlockOwner(BlockStateUtils.blockDataToBlockState(blockData));
|
||||
|
||||
if (blockOwner != MBlocks.OBSIDIAN && blockOwner != MBlocks.BEDROCK) {
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
BlockPos abovePos = blockPos.above();
|
||||
BukkitExistingBlock aboveBlock = (BukkitExistingBlock) world.getBlockAt(abovePos);
|
||||
BlockData aboveBlockData = aboveBlock.block().getBlockData();
|
||||
Object aboveBlockOwner = BlockStateUtils.getBlockOwner(BlockStateUtils.blockDataToBlockState(aboveBlockData));
|
||||
|
||||
if (aboveBlockOwner != MBlocks.AIR) {
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
|
||||
double x = abovePos.x();
|
||||
double y = abovePos.y();
|
||||
double z = abovePos.z();
|
||||
AABB aabb = new AABB(x, y, z, x + 1.0, y + 2.0, z + 1.0);
|
||||
List<Entity> entities = world.getEntities(null, aabb);
|
||||
if (!entities.isEmpty()) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
|
||||
List<AABB> aabbs = List.of(aabb);
|
||||
List<Object> nmsAABB = aabbs.stream()
|
||||
.map(AABB -> FastNMS.INSTANCE.constructor$AABB(
|
||||
AABB.minX, AABB.minY, AABB.minZ,
|
||||
AABB.maxX, AABB.maxY, AABB.maxZ
|
||||
)).toList();
|
||||
if (!FastNMS.INSTANCE.checkEntityCollision(context.getLevel().serverWorld(), nmsAABB, x, y, z)) {
|
||||
return InteractionResult.PASS;
|
||||
}
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements ItemBehaviorFactory {
|
||||
@Override
|
||||
public ItemBehavior create(Pack pack, Path path, Key id, Map<String, Object> arguments) {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package net.momirealms.craftengine.bukkit.item.behavior;
|
||||
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.MBlocks;
|
||||
import net.momirealms.craftengine.bukkit.util.BlockStateUtils;
|
||||
import net.momirealms.craftengine.bukkit.world.BukkitExistingBlock;
|
||||
import net.momirealms.craftengine.core.entity.player.InteractionResult;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehavior;
|
||||
import net.momirealms.craftengine.core.item.behavior.ItemBehaviorFactory;
|
||||
import net.momirealms.craftengine.core.item.context.UseOnContext;
|
||||
import net.momirealms.craftengine.core.pack.Pack;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.type.EndPortalFrame;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.Map;
|
||||
|
||||
public class EnderEyeItemBehavior extends ItemBehavior {
|
||||
public static final EnderEyeItemBehavior INSTANCE = new EnderEyeItemBehavior();
|
||||
public static final EnderEyeItemBehavior.Factory FACTORY = new EnderEyeItemBehavior.Factory();
|
||||
|
||||
@Override
|
||||
public InteractionResult useOnBlock(UseOnContext context) {
|
||||
BukkitExistingBlock block = (BukkitExistingBlock) context.getLevel().getBlockAt(context.getClickedPos());
|
||||
BlockData blockData = block.block().getBlockData();
|
||||
Object blockOwner = BlockStateUtils.getBlockOwner(BlockStateUtils.blockDataToBlockState(blockData));
|
||||
|
||||
if (blockOwner != MBlocks.END_PORTAL_FRAME || (blockData instanceof EndPortalFrame endPortalFrame && endPortalFrame.hasEye())) {
|
||||
return InteractionResult.PASS;
|
||||
} else {
|
||||
return InteractionResult.SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
public static class Factory implements ItemBehaviorFactory {
|
||||
@Override
|
||||
public ItemBehavior create(Pack pack, Path path, Key id, Map<String, Object> arguments) {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -257,7 +257,7 @@ public class ItemEventListener implements Listener {
|
||||
// so we should check and resend sounds on BlockPlaceEvent
|
||||
BlockData craftBlockData = BlockStateUtils.fromBlockData(immutableBlockState.vanillaBlockState().literalObject());
|
||||
if (InteractUtils.isInteractable(player, craftBlockData, hitResult, itemInHand)) {
|
||||
if (!serverPlayer.isSecondaryUseActive() || InteractUtils.isIgnoreSneaking(player, craftBlockData, hitResult, itemInHand)) {
|
||||
if (!serverPlayer.isSecondaryUseActive()) {
|
||||
serverPlayer.setResendSound();
|
||||
}
|
||||
} else {
|
||||
@@ -276,7 +276,7 @@ public class ItemEventListener implements Listener {
|
||||
return;
|
||||
} else {
|
||||
// todo 实际上这里的处理并不正确,因为判断玩家是否能够放置那个方块需要更加细节的判断。比如玩家无法对着树叶放置火把,但是交互事件依然触发,此情况下不可丢弃自定义行为。
|
||||
if ((serverPlayer.isSecondaryUseActive() && InteractUtils.isIgnoreSneaking(player, blockData, hitResult, itemInHand)) || !InteractUtils.isInteractable(player, blockData, hitResult, itemInHand)) {
|
||||
if (serverPlayer.isSecondaryUseActive() || !InteractUtils.isInteractable(player, blockData, hitResult, itemInHand)) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
}
|
||||
@@ -290,10 +290,9 @@ public class ItemEventListener implements Listener {
|
||||
if (optionalItemBehaviors.isPresent()) {
|
||||
// 检测是否可交互应当只判断原版方块,因为自定义方块早就判断过了,如果可交互不可能到这一步
|
||||
boolean interactable = immutableBlockState == null && InteractUtils.isInteractable(player, blockData, hitResult, itemInHand);
|
||||
boolean isIgnoreSneaking = InteractUtils.isIgnoreSneaking(player, blockData, hitResult, itemInHand);
|
||||
// 如果方块可交互但是玩家没shift,那么原版的方块交互优先,取消自定义物品的behavior
|
||||
// todo 如果我的物品行为允许某些交互呢?是否值得进一步处理?
|
||||
if ((!serverPlayer.isSecondaryUseActive() || isIgnoreSneaking) && interactable) {
|
||||
if (!serverPlayer.isSecondaryUseActive() && interactable) {
|
||||
return;
|
||||
}
|
||||
UseOnContext useOnContext = new UseOnContext(serverPlayer, hand, itemInHand, hitResult);
|
||||
@@ -316,7 +315,7 @@ public class ItemEventListener implements Listener {
|
||||
// 执行物品右键事件
|
||||
if (hasCustomItem) {
|
||||
// 要求服务端侧这个方块不可交互,或玩家处于潜行状态
|
||||
if ((serverPlayer.isSecondaryUseActive() && !InteractUtils.isIgnoreSneaking(player, blockData, hitResult, itemInHand)) || !InteractUtils.isInteractable(player, blockData, hitResult, itemInHand)) {
|
||||
if (serverPlayer.isSecondaryUseActive() || !InteractUtils.isInteractable(player, blockData, hitResult, itemInHand)) {
|
||||
Cancellable dummy = Cancellable.dummy();
|
||||
PlayerOptionalContext context = PlayerOptionalContext.of(serverPlayer, ContextHolder.builder()
|
||||
.withParameter(DirectContextParameters.BLOCK, new BukkitExistingBlock(block))
|
||||
|
||||
@@ -10,6 +10,8 @@ public final class MBlocks {
|
||||
public static final Object AIR$defaultState;
|
||||
public static final Object STONE;
|
||||
public static final Object STONE$defaultState;
|
||||
public static final Object BEDROCK;
|
||||
public static final Object OBSIDIAN;
|
||||
public static final Object FIRE;
|
||||
public static final Object SOUL_FIRE;
|
||||
public static final Object ICE;
|
||||
@@ -22,6 +24,8 @@ public final class MBlocks {
|
||||
public static final Object WATER$defaultState;
|
||||
public static final Object TNT;
|
||||
public static final Object TNT$defaultState;
|
||||
public static final Object LODESTONE;
|
||||
public static final Object END_PORTAL_FRAME;
|
||||
|
||||
private static Object getById(String id) {
|
||||
Object rl = FastNMS.INSTANCE.method$ResourceLocation$fromNamespaceAndPath("minecraft", id);
|
||||
@@ -35,6 +39,8 @@ public final class MBlocks {
|
||||
SOUL_FIRE = getById("soul_fire");
|
||||
STONE = getById("stone");
|
||||
STONE$defaultState = FastNMS.INSTANCE.method$Block$defaultState(STONE);
|
||||
BEDROCK = getById("bedrock");
|
||||
OBSIDIAN = getById("obsidian");
|
||||
ICE = getById("ice");
|
||||
SHORT_GRASS = getById(VersionHelper.isOrAbove1_20_3() ? "short_grass" : "grass");
|
||||
SHORT_GRASS$defaultState = FastNMS.INSTANCE.method$Block$defaultState(SHORT_GRASS);
|
||||
@@ -45,5 +51,7 @@ public final class MBlocks {
|
||||
WATER$defaultState = FastNMS.INSTANCE.method$Block$defaultState(WATER);
|
||||
TNT = getById("tnt");
|
||||
TNT$defaultState = FastNMS.INSTANCE.method$Block$defaultState(TNT);
|
||||
LODESTONE = getById("lodestone");
|
||||
END_PORTAL_FRAME = getById("end_portal_frame");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@ package net.momirealms.craftengine.bukkit.util;
|
||||
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.behavior.EnderEyeItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.behavior.FlintAndSteelItemBehavior;
|
||||
import net.momirealms.craftengine.bukkit.item.recipe.BukkitRecipeManager;
|
||||
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;
|
||||
@@ -16,16 +19,17 @@ import net.momirealms.craftengine.core.item.recipe.UniqueIdItem;
|
||||
import net.momirealms.craftengine.core.item.recipe.input.SingleItemInput;
|
||||
import net.momirealms.craftengine.core.plugin.CraftEngine;
|
||||
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.TriFunction;
|
||||
import net.momirealms.craftengine.core.util.*;
|
||||
import net.momirealms.craftengine.core.world.BlockHitResult;
|
||||
import net.momirealms.craftengine.core.world.BlockPos;
|
||||
import net.momirealms.craftengine.core.world.ExistingBlock;
|
||||
import org.bukkit.*;
|
||||
import org.bukkit.DyeColor;
|
||||
import org.bukkit.GameMode;
|
||||
import org.bukkit.Registry;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.attribute.Attribute;
|
||||
import org.bukkit.attribute.AttributeInstance;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.block.BlockFace;
|
||||
import org.bukkit.block.data.BlockData;
|
||||
import org.bukkit.block.data.Levelled;
|
||||
import org.bukkit.block.data.Lightable;
|
||||
@@ -42,7 +46,6 @@ import java.util.Optional;
|
||||
|
||||
public final 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>> SNEAK_BYPASS = new HashMap<>();
|
||||
private static final Map<Key, QuadFunction<Player, Item<ItemStack>, BlockData, BlockHitResult, Boolean>> WILL_CONSUME = new HashMap<>();
|
||||
private static final Map<Key, TriFunction<Player, Entity, @Nullable Item<ItemStack>, Boolean>> ENTITY_INTERACTIONS = new HashMap<>();
|
||||
|
||||
@@ -61,63 +64,6 @@ public final class InteractUtils {
|
||||
Key id = item.vanillaId();
|
||||
return ItemKeys.BUCKET.equals(id);
|
||||
});
|
||||
// 自然方块
|
||||
registerInteraction(BlockKeys.OBSIDIAN, (player, item, blockState, result) -> {
|
||||
Key id = item.vanillaId();
|
||||
if (ItemKeys.END_CRYSTAL.equals(id)) {
|
||||
World world = player.getWorld();
|
||||
BukkitWorld bukkitWorld = new BukkitWorld(world);
|
||||
BlockPos blockPos = result.getBlockPos();
|
||||
BlockPos abovePos = blockPos.relative(Direction.UP);
|
||||
ExistingBlock aboveBlock = bukkitWorld.getBlockAt(abovePos);
|
||||
if (!aboveBlock.id().equals(BlockKeys.AIR)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
// TODO 需要判定区域内无任何实体
|
||||
// double x = aboveBlock.x();
|
||||
// double y = aboveBlock.y();
|
||||
// double z = aboveBlock.z();
|
||||
// Object serverWorld = bukkitWorld.serverWorld();
|
||||
// AABB aabb = new AABB(x, y, z, x + 1.0, y + 2.0, z + 1.0);
|
||||
// Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(
|
||||
// aabb.minX, aabb.minY, aabb.minZ,
|
||||
// aabb.maxX, aabb.maxY, aabb.maxZ
|
||||
// );
|
||||
// boolean hasCollision = FastNMS.INSTANCE.checkEntityCollision(serverWorld, List.of(nmsAABB), x + 0.5, y + 1.0, z + 0.5);
|
||||
// return !hasCollision;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
registerInteraction(BlockKeys.BEDROCK, (player, item, blockState, result) -> {
|
||||
Key id = item.vanillaId();
|
||||
if (ItemKeys.END_CRYSTAL.equals(id)) {
|
||||
World world = player.getWorld();
|
||||
BukkitWorld bukkitWorld = new BukkitWorld(world);
|
||||
BlockPos blockPos = result.getBlockPos();
|
||||
BlockPos abovePos = blockPos.relative(Direction.UP);
|
||||
ExistingBlock aboveBlock = bukkitWorld.getBlockAt(abovePos);
|
||||
if (!aboveBlock.id().equals(BlockKeys.AIR)) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
// TODO 需要判定区域内无任何实体
|
||||
// double x = aboveBlock.x();
|
||||
// double y = aboveBlock.y();
|
||||
// double z = aboveBlock.z();
|
||||
// Object serverWorld = bukkitWorld.serverWorld();
|
||||
// AABB aabb = new AABB(x, y, z, x + 1.0, y + 2.0, z + 1.0);
|
||||
// Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(
|
||||
// aabb.minX, aabb.minY, aabb.minZ,
|
||||
// aabb.maxX, aabb.maxY, aabb.maxZ
|
||||
// );
|
||||
// boolean hasCollision = FastNMS.INSTANCE.checkEntityCollision(serverWorld, List.of(nmsAABB), x + 0.5, y + 1.0, z + 0.5);
|
||||
// return !hasCollision;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
// 功能方块
|
||||
registerInteraction(BlockKeys.CRAFTING_TABLE, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.STONECUTTER, (player, item, blockState, result) -> true);
|
||||
@@ -190,10 +136,6 @@ public final class InteractUtils {
|
||||
return false;
|
||||
});
|
||||
registerInteraction(BlockKeys.BEACON, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.LODESTONE, (player, item, blockState, result) -> {
|
||||
Key id = item.vanillaId();
|
||||
return ItemKeys.COMPASS.equals(id);
|
||||
});
|
||||
registerInteraction(BlockKeys.BEE_NEST, (player, item, blockState, result) -> {
|
||||
if (blockState instanceof Beehive beehive && beehive.getHoneyLevel() == beehive.getMaximumHoneyLevel()) {
|
||||
Key id = item.vanillaId();
|
||||
@@ -226,9 +168,11 @@ public final class InteractUtils {
|
||||
});
|
||||
registerInteraction(BlockKeys.DRAGON_EGG, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.END_PORTAL_FRAME, (player, item, blockState, result) -> {
|
||||
if (blockState instanceof EndPortalFrame endPortalFrame && !endPortalFrame.hasEye()) {
|
||||
Key id = item.vanillaId();
|
||||
return ItemKeys.ENDER_EYE.equals(id);
|
||||
Optional<List<ItemBehavior>> behaviors = item.getItemBehavior();
|
||||
if (behaviors.isPresent()) {
|
||||
for (ItemBehavior behavior : behaviors.get()) {
|
||||
if (behavior instanceof EnderEyeItemBehavior) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
@@ -242,7 +186,49 @@ public final class InteractUtils {
|
||||
return id.asString().endsWith("_spawn_egg");
|
||||
});
|
||||
// 红石方块
|
||||
registerInteraction(BlockKeys.REDSTONE_WIRE, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.REDSTONE_WIRE, (player, item, blockState, result) -> {
|
||||
if (blockState instanceof RedstoneWire redstoneWire) {
|
||||
boolean isCross = redstoneWire.getFace(BlockFace.EAST).equals(RedstoneWire.Connection.SIDE)
|
||||
&& redstoneWire.getFace(BlockFace.NORTH).equals(RedstoneWire.Connection.SIDE)
|
||||
&& redstoneWire.getFace(BlockFace.SOUTH).equals(RedstoneWire.Connection.SIDE)
|
||||
&& redstoneWire.getFace(BlockFace.WEST).equals(RedstoneWire.Connection.SIDE);
|
||||
boolean isDot = redstoneWire.getFace(BlockFace.EAST).equals(RedstoneWire.Connection.NONE)
|
||||
&& redstoneWire.getFace(BlockFace.NORTH).equals(RedstoneWire.Connection.NONE)
|
||||
&& redstoneWire.getFace(BlockFace.SOUTH).equals(RedstoneWire.Connection.NONE)
|
||||
&& redstoneWire.getFace(BlockFace.WEST).equals(RedstoneWire.Connection.NONE);
|
||||
if (isCross || isDot) {
|
||||
BlockPos blockPos = result.getBlockPos();
|
||||
BukkitWorld bukkitWorld = new BukkitWorld(player.getWorld());
|
||||
World world = bukkitWorld.platformWorld();
|
||||
|
||||
Direction[] directions = {Direction.EAST, Direction.WEST, Direction.SOUTH, Direction.NORTH};
|
||||
for (Direction direction : directions) {
|
||||
BlockPos neighborPos = blockPos.relative(direction);
|
||||
Block neighborBlock = world.getBlockAt(neighborPos.x(), neighborPos.y(), neighborPos.z());
|
||||
Key neighborBlockKey = new BukkitExistingBlock(neighborBlock).id();
|
||||
BlockData neighborBlockData = neighborBlock.getBlockData();
|
||||
boolean canConnection = ArrayUtils.contains(BlockKeys.REDSTONE_CONNECTION, neighborBlockKey)
|
||||
|| ArrayUtils.contains(BlockKeys.PRESSURE_PLATES, neighborBlockKey)
|
||||
|| ArrayUtils.contains(BlockKeys.BUTTONS, neighborBlockKey);
|
||||
if (canConnection) {
|
||||
return switch (neighborBlockData) {
|
||||
case Repeater repeater -> {
|
||||
Direction neighborDirection = DirectionUtils.toDirection(repeater.getFacing());
|
||||
yield !(neighborDirection == direction || neighborDirection == direction.opposite());
|
||||
}
|
||||
case Observer observer -> {
|
||||
Direction neighborDirection = DirectionUtils.toDirection(observer.getFacing());
|
||||
yield !(neighborDirection == direction);
|
||||
}
|
||||
default -> false;
|
||||
};
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
registerInteraction(BlockKeys.REPEATER, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.COMPARATOR, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.LEVER, (player, item, blockState, result) -> true);
|
||||
@@ -252,8 +238,13 @@ public final class InteractUtils {
|
||||
registerInteraction(BlockKeys.CRAFTER, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.HOPPER, (player, item, blockState, result) -> true);
|
||||
registerInteraction(BlockKeys.TNT, (player, item, blockState, result) -> {
|
||||
Key id = item.vanillaId();
|
||||
return ItemKeys.FLINT_AND_STEEL.equals(id);
|
||||
Optional<List<ItemBehavior>> behaviors = item.getItemBehavior();
|
||||
if (behaviors.isPresent()) {
|
||||
for (ItemBehavior behavior : behaviors.get()) {
|
||||
if (behavior instanceof FlintAndSteelItemBehavior) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
registerInteraction(BlockKeys.REDSTONE_ORE, (player, item, blockState, result) -> {
|
||||
Optional<List<ItemBehavior>> behaviors = item.getItemBehavior();
|
||||
@@ -727,21 +718,6 @@ public final class InteractUtils {
|
||||
registerInteraction(BlockKeys.WARPED_WALL_HANGING_SIGN, (player, item, blockState, result) -> true);
|
||||
}
|
||||
|
||||
// 忽略潜行
|
||||
static {
|
||||
registerSneakBypass(BlockKeys.LODESTONE, (player, item, blockState, result) -> {
|
||||
Key id = item.vanillaId();
|
||||
return ItemKeys.COMPASS.equals(id);
|
||||
});
|
||||
registerSneakBypass(BlockKeys.END_PORTAL_FRAME, (player, item, blockState, result) -> {
|
||||
if (blockState instanceof EndPortalFrame endPortalFrame && !endPortalFrame.hasEye()) {
|
||||
Key id = item.vanillaId();
|
||||
return ItemKeys.ENDER_EYE.equals(id);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
// 消耗
|
||||
static {
|
||||
registerWillConsume(BlockKeys.CACTUS, (player, item, blockState, result) -> {
|
||||
@@ -794,7 +770,7 @@ public final class InteractUtils {
|
||||
|
||||
registerEntityInteraction(EntityTypeKeys.SHEEP, (player, entity, item) -> {
|
||||
Key id = item.vanillaId();
|
||||
if (entity instanceof Sheep sheep && sheep.readyToBeSheared() && id.in(ItemKeys.DYES)) {
|
||||
if (entity instanceof Sheep sheep && sheep.readyToBeSheared() && ArrayUtils.contains(ItemKeys.DYES, item)) {
|
||||
DyeColor sheepColor = sheep.getColor();
|
||||
if (sheepColor != null) {
|
||||
String color = sheepColor.name().toLowerCase();
|
||||
@@ -820,12 +796,17 @@ public final class InteractUtils {
|
||||
});
|
||||
|
||||
registerEntityInteraction(EntityTypeKeys.CREEPER, (player, entity, item) -> {
|
||||
Key id = item.vanillaId();
|
||||
return canBeFeed(entity, item) || ItemKeys.FLINT_AND_STEEL.equals(id);
|
||||
Optional<List<ItemBehavior>> behaviors = item.getItemBehavior();
|
||||
if (behaviors.isPresent()) {
|
||||
for (ItemBehavior behavior : behaviors.get()) {
|
||||
if (behavior instanceof FlintAndSteelItemBehavior) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
registerEntityInteraction(EntityTypeKeys.PIGLIN, (player, entity, item) -> {
|
||||
Key id = item.vanillaId();
|
||||
return canBeFeed(entity, item) || ItemKeys.GOLD_INGOT.equals(id);
|
||||
return ItemKeys.GOLD_INGOT.equals(id);
|
||||
});
|
||||
registerEntityInteraction(EntityTypeKeys.ARMADILLO, (player, entity, item) -> {
|
||||
Key id = item.vanillaId();
|
||||
@@ -954,13 +935,6 @@ public final class InteractUtils {
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerSneakBypass(Key key, QuadFunction<org.bukkit.entity.Player, Item<ItemStack>, BlockData, BlockHitResult, Boolean> function) {
|
||||
var previous = SNEAK_BYPASS.put(key, function);
|
||||
if (previous != null) {
|
||||
CraftEngine.instance().logger().warn("Duplicated interaction check: " + key);
|
||||
}
|
||||
}
|
||||
|
||||
private static void registerWillConsume(Key key, QuadFunction<org.bukkit.entity.Player, Item<ItemStack>, BlockData, BlockHitResult, Boolean> function) {
|
||||
var previous = WILL_CONSUME.put(key, function);
|
||||
if (previous != null) {
|
||||
@@ -983,14 +957,6 @@ public final class InteractUtils {
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isIgnoreSneaking(Player player, BlockData state, BlockHitResult hit, @Nullable Item<ItemStack> item) {
|
||||
Key blockType = BlockStateUtils.getBlockOwnerIdFromData(state);
|
||||
if (SNEAK_BYPASS.containsKey(blockType)) {
|
||||
return SNEAK_BYPASS.get(blockType).apply(player, item, state, hit);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean willConsume(Player player, BlockData state, BlockHitResult hit, @Nullable Item<ItemStack> item) {
|
||||
if (item == null) return false;
|
||||
Key blockType = BlockStateUtils.getBlockOwnerIdFromData(state);
|
||||
|
||||
@@ -1,27 +1,36 @@
|
||||
package net.momirealms.craftengine.bukkit.world;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import net.momirealms.craftengine.bukkit.entity.BukkitEntity;
|
||||
import net.momirealms.craftengine.bukkit.nms.FastNMS;
|
||||
import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections;
|
||||
import net.momirealms.craftengine.bukkit.util.*;
|
||||
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||
import net.momirealms.craftengine.core.entity.Entity;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.sound.SoundSource;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.util.VersionHelper;
|
||||
import net.momirealms.craftengine.core.world.*;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import net.momirealms.craftengine.core.world.particle.ParticleData;
|
||||
import org.bukkit.Location;
|
||||
import org.bukkit.Particle;
|
||||
import org.bukkit.SoundCategory;
|
||||
import org.bukkit.entity.EnderDragonPart;
|
||||
import org.bukkit.entity.EntityType;
|
||||
import org.bukkit.entity.ExperienceOrb;
|
||||
import org.bukkit.inventory.ItemStack;
|
||||
import org.bukkit.util.BoundingBox;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public class BukkitWorld implements World {
|
||||
private final WeakReference<org.bukkit.World> world;
|
||||
@@ -54,6 +63,49 @@ public class BukkitWorld implements World {
|
||||
return new BukkitExistingBlock(platformWorld().getBlockAt(x, y, z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Entity> getEntities(@Nullable Entity entity, AABB aabb, Predicate<? super Entity> predicate) {
|
||||
List<Entity> entities = Lists.newArrayList();
|
||||
Object nmsAABB = FastNMS.INSTANCE.constructor$AABB(
|
||||
aabb.minX, aabb.minY, aabb.minZ,
|
||||
aabb.maxX, aabb.maxY, aabb.maxZ
|
||||
);
|
||||
BoundingBox bukkitAABB = new BoundingBox(
|
||||
aabb.minX, aabb.minY, aabb.minZ,
|
||||
aabb.maxX, aabb.maxY, aabb.maxZ
|
||||
);
|
||||
Object level = serverWorld();
|
||||
int entityCount = FastNMS.INSTANCE.method$EntityGetter$getEntitiesOfClass(level, nmsAABB, CoreReflections.clazz$Entity);
|
||||
if (entityCount == 0) {
|
||||
return entities;
|
||||
}
|
||||
for (org.bukkit.entity.Entity bukkitEntity : platformWorld().getNearbyEntities(bukkitAABB)) {
|
||||
if (bukkitEntity instanceof org.bukkit.entity.EnderDragonPart) {
|
||||
continue;
|
||||
}
|
||||
Entity craftEngineEntity = new BukkitEntity(bukkitEntity);
|
||||
if (!craftEngineEntity.equals(entity) && predicate.test(craftEngineEntity)) {
|
||||
entities.add(craftEngineEntity);
|
||||
}
|
||||
}
|
||||
for (EnderDragonPart dragonPart : platformWorld().getEntitiesByClass(EnderDragonPart.class)) {
|
||||
org.bukkit.util.BoundingBox partBoundingBox = dragonPart.getBoundingBox();
|
||||
boolean intersects = aabb.maxX >= partBoundingBox.getMinX() &&
|
||||
aabb.minX <= partBoundingBox.getMaxX() &&
|
||||
aabb.maxY >= partBoundingBox.getMinY() &&
|
||||
aabb.minY <= partBoundingBox.getMaxY() &&
|
||||
aabb.maxZ >= partBoundingBox.getMinZ() &&
|
||||
aabb.minZ <= partBoundingBox.getMaxZ();
|
||||
if (!intersects) continue;
|
||||
Entity craftEnginePart = new BukkitEntity(dragonPart);
|
||||
Entity craftEngineParent = new BukkitEntity(dragonPart.getParent());
|
||||
if (!craftEnginePart.equals(entity) && !craftEngineParent.equals(entity) && predicate.test(craftEnginePart)) {
|
||||
entities.add(craftEnginePart);
|
||||
}
|
||||
}
|
||||
return entities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String name() {
|
||||
return platformWorld().getName();
|
||||
|
||||
@@ -6,13 +6,9 @@ public final class BlockKeys {
|
||||
private BlockKeys() {}
|
||||
// 特殊
|
||||
public static final Key AIR = Key.of("minecraft:air");
|
||||
public static final Key NOTE_BLOCK = Key.of("minecraft:note_block");
|
||||
public static final Key TRIPWIRE = Key.of("minecraft:tripwire");
|
||||
public static final Key CACTUS = Key.of("minecraft:cactus");
|
||||
public static final Key POWDER_SNOW = Key.of("minecraft:powder_snow");
|
||||
// 自然方块
|
||||
public static final Key OBSIDIAN = Key.of("minecraft:obsidian");
|
||||
public static final Key BEDROCK = Key.of("minecraft:bedrock");
|
||||
// 功能方块
|
||||
public static final Key CRAFTING_TABLE = Key.of("minecraft:crafting_table");
|
||||
public static final Key STONECUTTER = Key.of("minecraft:stonecutter");
|
||||
@@ -37,7 +33,6 @@ public final class BlockKeys {
|
||||
public static final Key WATER_CAULDRON = Key.of("minecraft:water_cauldron");
|
||||
public static final Key BELL = Key.of("minecraft:bell");
|
||||
public static final Key BEACON = Key.of("minecraft:beacon");
|
||||
public static final Key LODESTONE = Key.of("minecraft:lodestone");
|
||||
public static final Key BEE_NEST = Key.of("minecraft:bee_nest");
|
||||
public static final Key BEEHIVE = Key.of("minecraft:beehive");
|
||||
public static final Key FLOWER_POT = Key.of("minecraft:flower_pot");
|
||||
@@ -59,17 +54,59 @@ public final class BlockKeys {
|
||||
public static final Key TRIAL_SPAWNER = Key.of("minecraft:trial_spawner");
|
||||
// 红石方块
|
||||
public static final Key REDSTONE_WIRE = Key.of("minecraft:redstone_wire");
|
||||
public static final Key REDSTONE_TORCH = Key.of("minecraft:redstone_torch");
|
||||
public static final Key REDSTONE_BLOCK = Key.of("minecraft:redstone_block");
|
||||
public static final Key REPEATER = Key.of("minecraft:repeater");
|
||||
public static final Key COMPARATOR = Key.of("minecraft:comparator");
|
||||
public static final Key TARGET = Key.of("minecraft:target");
|
||||
public static final Key LEVER = Key.of("minecraft:lever");
|
||||
public static final Key SCULK_SENSOR = Key.of("minecraft:sculk_sensor");
|
||||
public static final Key CALIBRATED_SCULK_SENSOR = Key.of("minecraft:calibrated_sculk_sensor");
|
||||
public static final Key TRIPWIRE_HOOK = Key.of("minecraft:tripwire_hook");
|
||||
public static final Key DAYLIGHT_DETECTOR = Key.of("minecraft:daylight_detector");
|
||||
public static final Key LIGHTNING_ROD = Key.of("minecraft:lightning_rod");
|
||||
public static final Key DISPENSER = Key.of("minecraft:dispenser");
|
||||
public static final Key DROPPER = Key.of("minecraft:dropper");
|
||||
public static final Key CRAFTER = Key.of("minecraft:crafter");
|
||||
public static final Key HOPPER = Key.of("minecraft:hopper");
|
||||
public static final Key OBSERVER = Key.of("minecraft:observer");
|
||||
public static final Key NOTE_BLOCK = Key.of("minecraft:note_block");
|
||||
public static final Key DETECTOR_RAIL = Key.of("minecraft:detector_rail");
|
||||
public static final Key TNT = Key.of("minecraft:tnt");
|
||||
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 OAK_BUTTON = Key.of("minecraft:oak_button");
|
||||
public static final Key SPRUCE_BUTTON = Key.of("minecraft:spruce_button");
|
||||
public static final Key BIRCH_BUTTON = Key.of("minecraft:birch_button");
|
||||
public static final Key JUNGLE_BUTTON = Key.of("minecraft:jungle_button");
|
||||
public static final Key ACACIA_BUTTON = Key.of("minecraft:acacia_button");
|
||||
public static final Key DARK_OAK_BUTTON = Key.of("minecraft:dark_oak_button");
|
||||
public static final Key MANGROVE_BUTTON = Key.of("minecraft:mangrove_button");
|
||||
public static final Key CHERRY_BUTTON = Key.of("minecraft:cherry_button");
|
||||
public static final Key PALE_OAK_BUTTON = Key.of("minecraft:pale_oak_button");
|
||||
public static final Key BAMBOO_BUTTON = Key.of("minecraft:bamboo_button");
|
||||
public static final Key CRIMSON_BUTTON = Key.of("minecraft:crimson_button");
|
||||
public static final Key WARPED_BUTTON = Key.of("minecraft:warped_button");
|
||||
public static final Key STONE_BUTTON = Key.of("minecraft:stone_button");
|
||||
public static final Key POLISHED_BLACKSTONE_BUTTON = Key.of("minecraft:polished_blackstone_button");
|
||||
// 压力板
|
||||
public static final Key OAK_PRESSURE_PLATE = Key.of("minecraft:oak_pressure_plate");
|
||||
public static final Key SPRUCE_PRESSURE_PLATE = Key.of("minecraft:spruce_pressure_plate");
|
||||
public static final Key BIRCH_PRESSURE_PLATE = Key.of("minecraft:birch_pressure_plate");
|
||||
public static final Key JUNGLE_PRESSURE_PLATE = Key.of("minecraft:jungle_pressure_plate");
|
||||
public static final Key ACACIA_PRESSURE_PLATE = Key.of("minecraft:acacia_pressure_plate");
|
||||
public static final Key DARK_OAK_PRESSURE_PLATE = Key.of("minecraft:dark_oak_pressure_plate");
|
||||
public static final Key MANGROVE_PRESSURE_PLATE = Key.of("minecraft:mangrove_pressure_plate");
|
||||
public static final Key CHERRY_PRESSURE_PLATE = Key.of("minecraft:cherry_pressure_plate");
|
||||
public static final Key PALE_OAK_PRESSURE_PLATE = Key.of("minecraft:pale_oak_pressure_plate");
|
||||
public static final Key BAMBOO_PRESSURE_PLATE = Key.of("minecraft:bamboo_pressure_plate");
|
||||
public static final Key CRIMSON_PRESSURE_PLATE = Key.of("minecraft:crimson_pressure_plate");
|
||||
public static final Key WARPED_PRESSURE_PLATE = Key.of("minecraft:warped_pressure_plate");
|
||||
public static final Key STONE_PRESSURE_PLATE = Key.of("minecraft:stone_pressure_plate");
|
||||
public static final Key POLISHED_BLACKSTONE_PRESSURE_PLATE = Key.of("minecraft:polished_blackstone_pressure_plate");
|
||||
public static final Key LIGHT_WEIGHTED_PRESSURE_PLATE = Key.of("minecraft:light_weighted_pressure_plate");
|
||||
public static final Key HEAVY_WEIGHTED_PRESSURE_PLATE = Key.of("minecraft:heavy_weighted_pressure_plate");
|
||||
// 管理员用品
|
||||
public static final Key COMMAND_BLOCK = Key.of("minecraft:command_block");
|
||||
public static final Key CHAIN_COMMAND_BLOCK = Key.of("minecraft:chain_command_block");
|
||||
@@ -79,6 +116,65 @@ public final class BlockKeys {
|
||||
public static final Key TEST_INSTANCE_BLOCK = Key.of("minecraft:test_instance_block");
|
||||
public static final Key TEST_BLOCK = Key.of("minecraft:test_block");
|
||||
public static final Key LIGHT = Key.of("minecraft:light");
|
||||
// 门
|
||||
public static final Key OAK_DOOR = Key.of("minecraft:oak_door");
|
||||
public static final Key SPRUCE_DOOR = Key.of("minecraft:spruce_door");
|
||||
public static final Key BIRCH_DOOR = Key.of("minecraft:birch_door");
|
||||
public static final Key JUNGLE_DOOR = Key.of("minecraft:jungle_door");
|
||||
public static final Key ACACIA_DOOR = Key.of("minecraft:acacia_door");
|
||||
public static final Key DARK_OAK_DOOR = Key.of("minecraft:dark_oak_door");
|
||||
public static final Key MANGROVE_DOOR = Key.of("minecraft:mangrove_door");
|
||||
public static final Key CHERRY_DOOR = Key.of("minecraft:cherry_door");
|
||||
public static final Key PALE_OAK_DOOR = Key.of("minecraft:pale_oak_door");
|
||||
public static final Key BAMBOO_DOOR = Key.of("minecraft:bamboo_door");
|
||||
public static final Key CRIMSON_DOOR = Key.of("minecraft:crimson_door");
|
||||
public static final Key WARPED_DOOR = Key.of("minecraft:warped_door");
|
||||
public static final Key IRON_DOOR = Key.of("minecraft:iron_door");
|
||||
|
||||
public static final Key COPPER_DOOR = Key.of("minecraft:copper_door");
|
||||
public static final Key EXPOSED_COPPER_DOOR = Key.of("minecraft:exposed_copper_door");
|
||||
public static final Key WEATHERED_COPPER_DOOR = Key.of("minecraft:weathered_copper_door");
|
||||
public static final Key OXIDIZED_COPPER_DOOR = Key.of("minecraft:oxidized_copper_door");
|
||||
public static final Key WAXED_COPPER_DOOR = Key.of("minecraft:waxed_copper_door");
|
||||
public static final Key WAXED_EXPOSED_COPPER_DOOR = Key.of("minecraft:waxed_exposed_copper_door");
|
||||
public static final Key WAXED_WEATHERED_COPPER_DOOR = Key.of("minecraft:waxed_weathered_copper_door");
|
||||
public static final Key WAXED_OXIDIZED_COPPER_DOOR = Key.of("minecraft:waxed_oxidized_copper_door");
|
||||
// 活板门
|
||||
public static final Key OAK_TRAPDOOR = Key.of("minecraft:oak_trapdoor");
|
||||
public static final Key SPRUCE_TRAPDOOR = Key.of("minecraft:spruce_trapdoor");
|
||||
public static final Key BIRCH_TRAPDOOR = Key.of("minecraft:birch_trapdoor");
|
||||
public static final Key JUNGLE_TRAPDOOR = Key.of("minecraft:jungle_trapdoor");
|
||||
public static final Key ACACIA_TRAPDOOR = Key.of("minecraft:acacia_trapdoor");
|
||||
public static final Key DARK_OAK_TRAPDOOR = Key.of("minecraft:dark_oak_trapdoor");
|
||||
public static final Key MANGROVE_TRAPDOOR = Key.of("minecraft:mangrove_trapdoor");
|
||||
public static final Key CHERRY_TRAPDOOR = Key.of("minecraft:cherry_trapdoor");
|
||||
public static final Key PALE_OAK_TRAPDOOR = Key.of("minecraft:pale_oak_trapdoor");
|
||||
public static final Key BAMBOO_TRAPDOOR = Key.of("minecraft:bamboo_trapdoor");
|
||||
public static final Key CRIMSON_TRAPDOOR = Key.of("minecraft:crimson_trapdoor");
|
||||
public static final Key WARPED_TRAPDOOR = Key.of("minecraft:warped_trapdoor");
|
||||
public static final Key IRON_TRAPDOOR = Key.of("minecraft:iron_trapdoor");
|
||||
|
||||
public static final Key COPPER_TRAPDOOR = Key.of("minecraft:copper_trapdoor");
|
||||
public static final Key EXPOSED_COPPER_TRAPDOOR = Key.of("minecraft:exposed_copper_trapdoor");
|
||||
public static final Key WEATHERED_COPPER_TRAPDOOR = Key.of("minecraft:weathered_copper_trapdoor");
|
||||
public static final Key OXIDIZED_COPPER_TRAPDOOR = Key.of("minecraft:oxidized_copper_trapdoor");
|
||||
public static final Key WAXED_COPPER_TRAPDOOR = Key.of("minecraft:waxed_copper_trapdoor");
|
||||
public static final Key WAXED_EXPOSED_COPPER_TRAPDOOR = Key.of("minecraft:waxed_exposed_copper_trapdoor");
|
||||
public static final Key WAXED_WEATHERED_COPPER_TRAPDOOR = Key.of("minecraft:waxed_weathered_copper_trapdoor");
|
||||
public static final Key WAXED_OXIDIZED_COPPER_TRAPDOOR = Key.of("minecraft:waxed_oxidized_copper_trapdoor");
|
||||
// 栅栏门
|
||||
public static final Key OAK_FENCE_GATE = Key.of("minecraft:oak_fence_gate");
|
||||
public static final Key SPRUCE_FENCE_GATE = Key.of("minecraft:spruce_fence_gate");
|
||||
public static final Key BIRCH_FENCE_GATE = Key.of("minecraft:birch_fence_gate");
|
||||
public static final Key JUNGLE_FENCE_GATE = Key.of("minecraft:jungle_fence_gate");
|
||||
public static final Key ACACIA_FENCE_GATE = Key.of("minecraft:acacia_fence_gate");
|
||||
public static final Key DARK_OAK_FENCE_GATE = Key.of("minecraft:dark_oak_fence_gate");
|
||||
public static final Key MANGROVE_FENCE_GATE = Key.of("minecraft:mangrove_fence_gate");
|
||||
public static final Key CHERRY_FENCE_GATE = Key.of("minecraft:cherry_fence_gate");
|
||||
public static final Key PALE_OAK_FENCE_GATE = Key.of("minecraft:pale_oak_fence_gate");
|
||||
public static final Key BAMBOO_FENCE_GATE = Key.of("minecraft:bamboo_fence_gate");
|
||||
public static final Key CRIMSON_FENCE_GATE = Key.of("minecraft:crimson_fence_gate");
|
||||
public static final Key WARPED_FENCE_GATE = Key.of("minecraft:warped_fence_gate");
|
||||
// 床
|
||||
public static final Key WHITE_BED = Key.of("minecraft:white_bed");
|
||||
public static final Key LIGHT_GRAY_BED = Key.of("minecraft:light_gray_bed");
|
||||
@@ -151,80 +247,6 @@ public final class BlockKeys {
|
||||
public static final Key PURPLE_SHULKER_BOX = Key.of("minecraft:purple_shulker_box");
|
||||
public static final Key MAGENTA_SHULKER_BOX = Key.of("minecraft:magenta_shulker_box");
|
||||
public static final Key PINK_SHULKER_BOX = Key.of("minecraft:pink_shulker_box");
|
||||
// 按钮
|
||||
public static final Key OAK_BUTTON = Key.of("minecraft:oak_button");
|
||||
public static final Key SPRUCE_BUTTON = Key.of("minecraft:spruce_button");
|
||||
public static final Key BIRCH_BUTTON = Key.of("minecraft:birch_button");
|
||||
public static final Key JUNGLE_BUTTON = Key.of("minecraft:jungle_button");
|
||||
public static final Key ACACIA_BUTTON = Key.of("minecraft:acacia_button");
|
||||
public static final Key DARK_OAK_BUTTON = Key.of("minecraft:dark_oak_button");
|
||||
public static final Key MANGROVE_BUTTON = Key.of("minecraft:mangrove_button");
|
||||
public static final Key CHERRY_BUTTON = Key.of("minecraft:cherry_button");
|
||||
public static final Key PALE_OAK_BUTTON = Key.of("minecraft:pale_oak_button");
|
||||
public static final Key BAMBOO_BUTTON = Key.of("minecraft:bamboo_button");
|
||||
public static final Key CRIMSON_BUTTON = Key.of("minecraft:crimson_button");
|
||||
public static final Key WARPED_BUTTON = Key.of("minecraft:warped_button");
|
||||
public static final Key STONE_BUTTON = Key.of("minecraft:stone_button");
|
||||
public static final Key POLISHED_BLACKSTONE_BUTTON = Key.of("minecraft:polished_blackstone_button");
|
||||
// 门
|
||||
public static final Key OAK_DOOR = Key.of("minecraft:oak_door");
|
||||
public static final Key SPRUCE_DOOR = Key.of("minecraft:spruce_door");
|
||||
public static final Key BIRCH_DOOR = Key.of("minecraft:birch_door");
|
||||
public static final Key JUNGLE_DOOR = Key.of("minecraft:jungle_door");
|
||||
public static final Key ACACIA_DOOR = Key.of("minecraft:acacia_door");
|
||||
public static final Key DARK_OAK_DOOR = Key.of("minecraft:dark_oak_door");
|
||||
public static final Key MANGROVE_DOOR = Key.of("minecraft:mangrove_door");
|
||||
public static final Key CHERRY_DOOR = Key.of("minecraft:cherry_door");
|
||||
public static final Key PALE_OAK_DOOR = Key.of("minecraft:pale_oak_door");
|
||||
public static final Key BAMBOO_DOOR = Key.of("minecraft:bamboo_door");
|
||||
public static final Key CRIMSON_DOOR = Key.of("minecraft:crimson_door");
|
||||
public static final Key WARPED_DOOR = Key.of("minecraft:warped_door");
|
||||
public static final Key IRON_DOOR = Key.of("minecraft:iron_door");
|
||||
|
||||
public static final Key COPPER_DOOR = Key.of("minecraft:copper_door");
|
||||
public static final Key EXPOSED_COPPER_DOOR = Key.of("minecraft:exposed_copper_door");
|
||||
public static final Key WEATHERED_COPPER_DOOR = Key.of("minecraft:weathered_copper_door");
|
||||
public static final Key OXIDIZED_COPPER_DOOR = Key.of("minecraft:oxidized_copper_door");
|
||||
public static final Key WAXED_COPPER_DOOR = Key.of("minecraft:waxed_copper_door");
|
||||
public static final Key WAXED_EXPOSED_COPPER_DOOR = Key.of("minecraft:waxed_exposed_copper_door");
|
||||
public static final Key WAXED_WEATHERED_COPPER_DOOR = Key.of("minecraft:waxed_weathered_copper_door");
|
||||
public static final Key WAXED_OXIDIZED_COPPER_DOOR = Key.of("minecraft:waxed_oxidized_copper_door");
|
||||
// 活板门
|
||||
public static final Key OAK_TRAPDOOR = Key.of("minecraft:oak_trapdoor");
|
||||
public static final Key SPRUCE_TRAPDOOR = Key.of("minecraft:spruce_trapdoor");
|
||||
public static final Key BIRCH_TRAPDOOR = Key.of("minecraft:birch_trapdoor");
|
||||
public static final Key JUNGLE_TRAPDOOR = Key.of("minecraft:jungle_trapdoor");
|
||||
public static final Key ACACIA_TRAPDOOR = Key.of("minecraft:acacia_trapdoor");
|
||||
public static final Key DARK_OAK_TRAPDOOR = Key.of("minecraft:dark_oak_trapdoor");
|
||||
public static final Key MANGROVE_TRAPDOOR = Key.of("minecraft:mangrove_trapdoor");
|
||||
public static final Key CHERRY_TRAPDOOR = Key.of("minecraft:cherry_trapdoor");
|
||||
public static final Key PALE_OAK_TRAPDOOR = Key.of("minecraft:pale_oak_trapdoor");
|
||||
public static final Key BAMBOO_TRAPDOOR = Key.of("minecraft:bamboo_trapdoor");
|
||||
public static final Key CRIMSON_TRAPDOOR = Key.of("minecraft:crimson_trapdoor");
|
||||
public static final Key WARPED_TRAPDOOR = Key.of("minecraft:warped_trapdoor");
|
||||
public static final Key IRON_TRAPDOOR = Key.of("minecraft:iron_trapdoor");
|
||||
|
||||
public static final Key COPPER_TRAPDOOR = Key.of("minecraft:copper_trapdoor");
|
||||
public static final Key EXPOSED_COPPER_TRAPDOOR = Key.of("minecraft:exposed_copper_trapdoor");
|
||||
public static final Key WEATHERED_COPPER_TRAPDOOR = Key.of("minecraft:weathered_copper_trapdoor");
|
||||
public static final Key OXIDIZED_COPPER_TRAPDOOR = Key.of("minecraft:oxidized_copper_trapdoor");
|
||||
public static final Key WAXED_COPPER_TRAPDOOR = Key.of("minecraft:waxed_copper_trapdoor");
|
||||
public static final Key WAXED_EXPOSED_COPPER_TRAPDOOR = Key.of("minecraft:waxed_exposed_copper_trapdoor");
|
||||
public static final Key WAXED_WEATHERED_COPPER_TRAPDOOR = Key.of("minecraft:waxed_weathered_copper_trapdoor");
|
||||
public static final Key WAXED_OXIDIZED_COPPER_TRAPDOOR = Key.of("minecraft:waxed_oxidized_copper_trapdoor");
|
||||
// 栅栏门
|
||||
public static final Key OAK_FENCE_GATE = Key.of("minecraft:oak_fence_gate");
|
||||
public static final Key SPRUCE_FENCE_GATE = Key.of("minecraft:spruce_fence_gate");
|
||||
public static final Key BIRCH_FENCE_GATE = Key.of("minecraft:birch_fence_gate");
|
||||
public static final Key JUNGLE_FENCE_GATE = Key.of("minecraft:jungle_fence_gate");
|
||||
public static final Key ACACIA_FENCE_GATE = Key.of("minecraft:acacia_fence_gate");
|
||||
public static final Key DARK_OAK_FENCE_GATE = Key.of("minecraft:dark_oak_fence_gate");
|
||||
public static final Key MANGROVE_FENCE_GATE = Key.of("minecraft:mangrove_fence_gate");
|
||||
public static final Key CHERRY_FENCE_GATE = Key.of("minecraft:cherry_fence_gate");
|
||||
public static final Key PALE_OAK_FENCE_GATE = Key.of("minecraft:pale_oak_fence_gate");
|
||||
public static final Key BAMBOO_FENCE_GATE = Key.of("minecraft:bamboo_fence_gate");
|
||||
public static final Key CRIMSON_FENCE_GATE = Key.of("minecraft:crimson_fence_gate");
|
||||
public static final Key WARPED_FENCE_GATE = Key.of("minecraft:warped_fence_gate");
|
||||
// 告示牌
|
||||
public static final Key OAK_SIGN = Key.of("minecraft:oak_sign");
|
||||
public static final Key SPRUCE_SIGN = Key.of("minecraft:spruce_sign");
|
||||
@@ -277,4 +299,21 @@ public final class BlockKeys {
|
||||
public static final Key BAMBOO_WALL_HANGING_SIGN = Key.of("minecraft:bamboo_wall_hanging_sign");
|
||||
public static final Key CRIMSON_WALL_HANGING_SIGN = Key.of("minecraft:crimson_wall_hanging_sign");
|
||||
public static final Key WARPED_WALL_HANGING_SIGN = Key.of("minecraft:warped_wall_hanging_sign");
|
||||
|
||||
public static final Key[] BUTTONS = new Key[]{
|
||||
OAK_BUTTON, SPRUCE_BUTTON, BIRCH_BUTTON, JUNGLE_BUTTON, ACACIA_BUTTON, DARK_OAK_BUTTON, MANGROVE_BUTTON, CHERRY_BUTTON,
|
||||
PALE_OAK_BUTTON, BAMBOO_BUTTON, CRIMSON_BUTTON, WARPED_BUTTON, STONE_BUTTON, POLISHED_BLACKSTONE_BUTTON
|
||||
};
|
||||
|
||||
public static final Key[] PRESSURE_PLATES = new Key[]{
|
||||
OAK_PRESSURE_PLATE, SPRUCE_PRESSURE_PLATE, BIRCH_PRESSURE_PLATE, JUNGLE_PRESSURE_PLATE, ACACIA_PRESSURE_PLATE,
|
||||
DARK_OAK_PRESSURE_PLATE, MANGROVE_PRESSURE_PLATE, CHERRY_PRESSURE_PLATE, PALE_OAK_PRESSURE_PLATE, BAMBOO_PRESSURE_PLATE,
|
||||
CRIMSON_PRESSURE_PLATE, WARPED_PRESSURE_PLATE, STONE_PRESSURE_PLATE, POLISHED_BLACKSTONE_PRESSURE_PLATE,
|
||||
LIGHT_WEIGHTED_PRESSURE_PLATE, HEAVY_WEIGHTED_PRESSURE_PLATE
|
||||
};
|
||||
|
||||
public static final Key[] REDSTONE_CONNECTION = new Key[] {
|
||||
REDSTONE_WIRE, REDSTONE_TORCH, REDSTONE_BLOCK, REPEATER, COMPARATOR, TARGET, LEVER, SCULK_SENSOR, CALIBRATED_SCULK_SENSOR,
|
||||
TRIPWIRE_HOOK, LECTERN, DAYLIGHT_DETECTOR, LIGHTNING_ROD, TRAPPED_CHEST, JUKEBOX, OBSERVER, DETECTOR_RAIL
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
package net.momirealms.craftengine.core.util;
|
||||
|
||||
import java.lang.reflect.Array;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
public class ArrayUtils {
|
||||
|
||||
@@ -77,6 +74,18 @@ public class ArrayUtils {
|
||||
.split(",");
|
||||
}
|
||||
|
||||
public static <T> boolean contains(T[] array, T element) {
|
||||
if (array == null || element == null) {
|
||||
return false;
|
||||
}
|
||||
for (T item : array) {
|
||||
if (Objects.equals(item, element)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static boolean isEmpty(Object[] array) {
|
||||
return array == null || array.length == 0;
|
||||
}
|
||||
|
||||
@@ -57,21 +57,6 @@ public record Key(String namespace, String value) {
|
||||
return this.value.equals(key.value()) && this.namespace.equals(key.namespace());
|
||||
}
|
||||
|
||||
public boolean in(Key... items) {
|
||||
if (items == null) {
|
||||
return false;
|
||||
}
|
||||
for (Key key : items) {
|
||||
if (key == this) {
|
||||
return true;
|
||||
}
|
||||
if (this.value.equals(key.value()) && this.namespace.equals(key.namespace())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull String toString() {
|
||||
return asString();
|
||||
|
||||
@@ -1,17 +1,22 @@
|
||||
package net.momirealms.craftengine.core.world;
|
||||
|
||||
import net.momirealms.craftengine.core.block.BlockStateWrapper;
|
||||
import net.momirealms.craftengine.core.entity.Entity;
|
||||
import net.momirealms.craftengine.core.entity.player.Player;
|
||||
import net.momirealms.craftengine.core.item.Item;
|
||||
import net.momirealms.craftengine.core.plugin.context.Context;
|
||||
import net.momirealms.craftengine.core.sound.SoundData;
|
||||
import net.momirealms.craftengine.core.sound.SoundSource;
|
||||
import net.momirealms.craftengine.core.util.Key;
|
||||
import net.momirealms.craftengine.core.world.collision.AABB;
|
||||
import net.momirealms.craftengine.core.world.particle.ParticleData;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public interface World {
|
||||
|
||||
@@ -29,6 +34,18 @@ public interface World {
|
||||
|
||||
void setBlockAt(int x, int y, int z, BlockStateWrapper blockState, int flags);
|
||||
|
||||
List<Entity> getEntities(@Nullable Entity entity, AABB aabb, Predicate<? super Entity> predicate);
|
||||
|
||||
default List<Entity> getEntities(@Nullable Entity entity, AABB aabb) {
|
||||
Predicate<Entity> noSpectator = player -> {
|
||||
if (player instanceof Player) {
|
||||
return !((Player) player).isSpectatorMode();
|
||||
}
|
||||
return true;
|
||||
};
|
||||
return this.getEntities(entity, aabb, noSpectator);
|
||||
}
|
||||
|
||||
String name();
|
||||
|
||||
Path directory();
|
||||
|
||||
Reference in New Issue
Block a user