From c285e6be78cb6ba0884578c40f7cce7cb5ecfa47 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 10:37:22 +0800 Subject: [PATCH 01/13] =?UTF-8?q?feat(block):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=8F=B0=E7=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../default/configuration/blocks.yml | 110 ++++++++++++++++++ .../default/configuration/categories.yml | 6 +- .../default/configuration/furniture.yml | 51 -------- 3 files changed, 113 insertions(+), 54 deletions(-) diff --git a/common-files/src/main/resources/resources/default/configuration/blocks.yml b/common-files/src/main/resources/resources/default/configuration/blocks.yml index 757d0d468..2384cba31 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks.yml @@ -739,6 +739,116 @@ items#misc: facing=west,shape=straight: appearance: facing=west,shape=straight id: 11 + default:table_lamp: + material: nether_brick + custom-model-data: 3011 + data: + item-name: + model: + type: minecraft:model + path: minecraft:item/custom/table_lamp + behavior: + type: block_item + block: + loot: + template: default:loot_table/self + settings: + template: + - default:sound/metal + overrides: + hardness: 1 + resistance: 1 + replaceable: false + is-redstone-conductor: false + is-suffocating: false + behaviors: + - type: toggleable_lamp_block + can-open-with-hand: true + - type: sturdy_base_block + direction: down + support-types: + - full + - center + states: + properties: + lit: + type: boolean + default: false + facing: + type: 4-direction + default: north + appearances: + east_off: + state: barrier + entity-renderer: + item: default:table_lamp + north_off: + state: barrier + entity-renderer: + item: default:table_lamp + yaw: -90 + south_off: + state: barrier + entity-renderer: + item: default:table_lamp + yaw: 90 + west_off: + state: barrier + entity-renderer: + item: default:table_lamp + yaw: 180 + east_on: + state: barrier + entity-renderer: + item: default:table_lamp + north_on: + state: barrier + entity-renderer: + item: default:table_lamp + yaw: -90 + south_on: + state: barrier + entity-renderer: + item: default:table_lamp + yaw: 90 + west_on: + state: barrier + entity-renderer: + item: default:table_lamp + yaw: 180 + variants: + facing=east,lit=false: + appearance: east_off + id: 12 + facing=north,lit=false: + appearance: north_off + id: 13 + facing=south,lit=false: + appearance: south_off + id: 14 + facing=west,lit=false: + appearance: west_off + id: 15 + facing=east,lit=true: + appearance: east_on + id: 16 + settings: + luminance: 15 + facing=north,lit=true: + appearance: north_on + id: 17 + settings: + luminance: 15 + facing=south,lit=true: + appearance: south_on + id: 18 + settings: + luminance: 15 + facing=west,lit=true: + appearance: west_on + id: 19 + settings: + luminance: 15 recipes#misc: default:chinese_lantern: type: shaped diff --git a/common-files/src/main/resources/resources/default/configuration/categories.yml b/common-files/src/main/resources/resources/default/configuration/categories.yml index 989c66a4b..8dc018294 100644 --- a/common-files/src/main/resources/resources/default/configuration/categories.yml +++ b/common-files/src/main/resources/resources/default/configuration/categories.yml @@ -52,10 +52,9 @@ categories: default:furniture: name: <#FFD700> hidden: true - icon: default:table_lamp + icon: default:flower_basket list: - default:bench - - default:table_lamp - default:wooden_chair - default:flower_basket default:misc: @@ -83,4 +82,5 @@ categories: - default:sleeper_sofa - minecraft:air - minecraft:air - - default:sofa \ No newline at end of file + - default:sofa + - default:table_lamp \ No newline at end of file diff --git a/common-files/src/main/resources/resources/default/configuration/furniture.yml b/common-files/src/main/resources/resources/default/configuration/furniture.yml index 23212868d..e54a3ccb0 100644 --- a/common-files/src/main/resources/resources/default/configuration/furniture.yml +++ b/common-files/src/main/resources/resources/default/configuration/furniture.yml @@ -42,57 +42,6 @@ items: template: default:loot_table/furniture arguments: item: default:bench - default:table_lamp: - material: nether_brick - custom-model-data: 2001 - data: - item-name: - model: - type: minecraft:model - path: minecraft:item/custom/table_lamp - behavior: - type: furniture_item - furniture: - settings: - item: default:table_lamp - sounds: - break: minecraft:block.lantern.break - place: minecraft:block.lantern.place - placement: - ground: - loot-spawn-offset: 0,0.2,0 - rules: - rotation: ANY - alignment: QUARTER - elements: - - item: default:table_lamp - display-transform: NONE - billboard: FIXED - translation: 0,0.5,0 - rotation: 90 - hitboxes: - - position: 0,0,0 - type: interaction - blocks-building: true - width: 0.7 - height: 0.1 - interactive: true - - position: 0,0.1,-0.1 - type: interaction - blocks-building: true - width: 0.1 - height: 0.6 - interactive: true - - position: 0,0.6,0.15 - type: interaction - blocks-building: true - width: 0.4 - height: 0.4 - interactive: true - loot: - template: default:loot_table/furniture - arguments: - item: default:table_lamp default:wooden_chair: material: nether_brick custom-model-data: 2002 From f724faaf86be4fea2340e680299f14769eeb95a0 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 13:21:41 +0800 Subject: [PATCH 02/13] =?UTF-8?q?feat(block):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E5=BA=A7=E6=A4=85=E6=96=B9=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/behavior/BukkitBlockBehaviors.java | 2 + .../block/behavior/SeatBlockBehavior.java | 77 ++++++++ .../block/entity/BukkitBlockEntityTypes.java | 1 + .../bukkit/block/entity/SeatBlockEntity.java | 179 ++++++++++++++++++ .../furniture/BukkitFurnitureManager.java | 3 + .../default/configuration/blocks.yml | 13 +- .../block/behavior/EntityBlockBehavior.java | 5 + .../block/entity/BlockEntityTypeKeys.java | 1 + 8 files changed, 277 insertions(+), 4 deletions(-) create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java create mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java index 34435ad14..f13476d45 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java @@ -32,6 +32,7 @@ public class BukkitBlockBehaviors extends BlockBehaviors { public static final Key TOGGLEABLE_LAMP_BLOCK = Key.from("craftengine:toggleable_lamp_block"); public static final Key SOFA_BLOCK = Key.from("craftengine:sofa_block"); public static final Key BOUNCING_BLOCK = Key.from("craftengine:bouncing_block"); + public static final Key SEAT_BLOCK = Key.from("craftengine:seat_block"); public static void init() { register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE); @@ -62,5 +63,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors { register(TOGGLEABLE_LAMP_BLOCK, ToggleableLampBlockBehavior.FACTORY); register(SOFA_BLOCK, SofaBlockBehavior.FACTORY); register(BOUNCING_BLOCK, BouncingBlockBehavior.FACTORY); + register(SEAT_BLOCK, SeatBlockBehavior.FACTORY); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java new file mode 100644 index 000000000..252c8b11d --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java @@ -0,0 +1,77 @@ +package net.momirealms.craftengine.bukkit.block.behavior; + +import net.momirealms.craftengine.bukkit.block.entity.BukkitBlockEntityTypes; +import net.momirealms.craftengine.bukkit.block.entity.SeatBlockEntity; +import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; +import net.momirealms.craftengine.core.block.BlockBehavior; +import net.momirealms.craftengine.core.block.CustomBlock; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; +import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior; +import net.momirealms.craftengine.core.block.entity.BlockEntity; +import net.momirealms.craftengine.core.block.entity.BlockEntityType; +import net.momirealms.craftengine.core.block.entity.tick.BlockEntityTicker; +import net.momirealms.craftengine.core.entity.player.InteractionResult; +import net.momirealms.craftengine.core.item.context.UseOnContext; +import net.momirealms.craftengine.core.util.ResourceConfigUtils; +import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.craftengine.core.world.CEWorld; +import org.joml.Vector3f; + +import java.util.Map; + +public class SeatBlockBehavior extends BukkitBlockBehavior implements EntityBlockBehavior { + public static final Factory FACTORY = new Factory(); + private final Vector3f offset; + private final float yaw; + private final boolean limitPlayerRotation; + + public SeatBlockBehavior(CustomBlock customBlock, Vector3f offset, float yaw, boolean limitPlayerRotation) { + super(customBlock); + this.offset = offset; + this.yaw = yaw; + this.limitPlayerRotation = limitPlayerRotation; + } + + @Override + public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) { + BukkitServerPlayer player = (BukkitServerPlayer) context.getPlayer(); + if (player == null || player.isSecondaryUseActive() || player.platformPlayer() == null) { + return InteractionResult.PASS; + } + CEWorld world = context.getLevel().storageWorld(); + BlockEntity blockEntity = world.getBlockEntityAtIfLoaded(context.getClickedPos()); + if (!(blockEntity instanceof SeatBlockEntity seatBlockEntity) || !seatBlockEntity.seatEntities().isEmpty()) { + return InteractionResult.PASS; + } + seatBlockEntity.spawnSeatEntityForPlayer(player.platformPlayer(), this.offset, this.yaw, this.limitPlayerRotation); + return InteractionResult.SUCCESS_AND_CANCEL; + } + + @SuppressWarnings("unchecked") + @Override + public BlockEntityType blockEntityType() { + return (BlockEntityType) BukkitBlockEntityTypes.SEAT; + } + + @Override + public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) { + return new SeatBlockEntity(pos, state); + } + + @Override + public BlockEntityTicker createBlockEntityTicker(CEWorld level, ImmutableBlockState state, BlockEntityType blockEntityType) { + return EntityBlockBehavior.createTickerHelper(SeatBlockEntity::tick); + } + + public static class Factory implements BlockBehaviorFactory { + + @Override + public BlockBehavior create(CustomBlock block, Map arguments) { + Vector3f offset = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("offset", "0,0,0"), "offset"); + float yaw = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("yaw", 0f), "yaw"); + boolean limitPlayerRotation = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("limit-player-rotation", true), "limit-player-rotation"); + return new SeatBlockBehavior(block, offset, yaw, limitPlayerRotation); + } + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java index 3e778bd32..c739d0bc4 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java @@ -6,4 +6,5 @@ import net.momirealms.craftengine.core.block.entity.BlockEntityTypes; public class BukkitBlockEntityTypes extends BlockEntityTypes { public static final BlockEntityType SIMPLE_STORAGE = register(BlockEntityTypeKeys.SIMPLE_STORAGE, SimpleStorageBlockEntity::new); + public static final BlockEntityType SEAT = register(BlockEntityTypeKeys.SEAT, SeatBlockEntity::new); } \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java new file mode 100644 index 000000000..40f6473cf --- /dev/null +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java @@ -0,0 +1,179 @@ +package net.momirealms.craftengine.bukkit.block.entity; + +import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; +import net.momirealms.craftengine.bukkit.util.EntityUtils; +import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils; +import net.momirealms.craftengine.core.block.ImmutableBlockState; +import net.momirealms.craftengine.core.block.entity.BlockEntity; +import net.momirealms.craftengine.core.block.properties.Property; +import net.momirealms.craftengine.core.util.HorizontalDirection; +import net.momirealms.craftengine.core.util.QuaternionUtils; +import net.momirealms.craftengine.core.util.VersionHelper; +import net.momirealms.craftengine.core.world.BlockPos; +import net.momirealms.craftengine.core.world.CEWorld; +import org.bukkit.Location; +import org.bukkit.World; +import org.bukkit.attribute.Attribute; +import org.bukkit.entity.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.joml.Vector3f; + +import java.util.Map; +import java.util.Objects; + +@SuppressWarnings("DuplicatedCode") +public class SeatBlockEntity extends BlockEntity { + private final Map seatEntities = new Reference2ObjectArrayMap<>(1); + + public SeatBlockEntity(BlockPos pos, ImmutableBlockState blockState) { + super(BukkitBlockEntityTypes.SEAT, pos, blockState); + } + + public Map seatEntities() { + return this.seatEntities; + } + + public static void tick(CEWorld world, BlockPos pos, ImmutableBlockState state, SeatBlockEntity seat) { + if (seat.seatEntities.isEmpty()) return; + for (Map.Entry entry : seat.seatEntities.entrySet()) { + Entity entity = entry.getKey(); + if (!entity.getPassengers().isEmpty()) continue; + Player player = entry.getValue(); + seat.tryLeavingSeat(player, entity); + seat.seatEntities.remove(entity); + } + } + + @Override + public void preRemove() { + if (this.seatEntities.isEmpty()) return; + for (Map.Entry entry : this.seatEntities.entrySet()) { + Entity entity = entry.getKey(); + entity.remove(); + this.seatEntities.remove(entity); + } + this.seatEntities.clear(); + } + + public void spawnSeatEntityForPlayer(@NotNull Player player, @NotNull Vector3f offset, float yaw, boolean limitPlayerRotation) { + if (!this.seatEntities.isEmpty() || !this.isValid()) return; + Location location = calculateSeatLocation(player, this.pos, this.blockState, offset, yaw); + Entity seatEntity = limitPlayerRotation ? + EntityUtils.spawnEntity(player.getWorld(), + VersionHelper.isOrAbove1_20_2() ? location.subtract(0, 0.9875, 0) : location.subtract(0, 0.990625, 0), + EntityType.ARMOR_STAND, + entity -> { + ArmorStand armorStand = (ArmorStand) entity; + if (VersionHelper.isOrAbove1_21_3()) { + Objects.requireNonNull(armorStand.getAttribute(Attribute.MAX_HEALTH)).setBaseValue(0.01); + } else { + LegacyAttributeUtils.setMaxHealth(armorStand); + } + armorStand.setSmall(true); + armorStand.setInvisible(true); + armorStand.setSilent(true); + armorStand.setInvulnerable(true); + armorStand.setArms(false); + armorStand.setCanTick(false); + armorStand.setAI(false); + armorStand.setGravity(false); + armorStand.setPersistent(false); + }) : + EntityUtils.spawnEntity(player.getWorld(), + VersionHelper.isOrAbove1_20_2() ? location : location.subtract(0, 0.25, 0), + EntityType.ITEM_DISPLAY, + entity -> { + ItemDisplay itemDisplay = (ItemDisplay) entity; + itemDisplay.setPersistent(false); + }); + if (!seatEntity.addPassenger(player)) { + seatEntity.remove(); + return; + } + this.seatEntities.put(seatEntity, player); + } + + private Location calculateSeatLocation(Player player, BlockPos pos, ImmutableBlockState state, Vector3f offset, float yaw) { + Location location = new Location(player.getWorld(), pos.x() + 0.5, pos.y() + 0.5, pos.z() + 0.5); + for (Property property : state.getProperties()) { + if (property.name().equals("facing") && property.valueClass() == HorizontalDirection.class) { + switch ((HorizontalDirection) state.get(property)) { + case NORTH -> location.setYaw(0); + case SOUTH -> location.setYaw(180); + case WEST -> location.setYaw(270); + case EAST -> location.setYaw(90); + } + break; + } + if (property.name().equals("facing_clockwise") && property.valueClass() == HorizontalDirection.class) { + switch ((HorizontalDirection) state.get(property)) { + case NORTH -> location.setYaw(90); + case SOUTH -> location.setYaw(270); + case WEST -> location.setYaw(0); + case EAST -> location.setYaw(180); + } + break; + } + } + Vector3f newOffset = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - location.getYaw()), 0) + .conjugate() + .transform(new Vector3f(offset)); + double newYaw = yaw + location.getYaw(); + if (newYaw < -180) newYaw += 360; + Location newLocation = location.clone(); + newLocation.setYaw((float) newYaw); + newLocation.add(newOffset.x, newOffset.y + 0.6, -newOffset.z); + return newLocation; + } + + private void tryLeavingSeat(@NotNull Player player, @NotNull Entity vehicle) { + vehicle.remove(); + if (player.getVehicle() != null) return; + Location vehicleLocation = vehicle.getLocation(); + Location originalLocation = vehicleLocation.clone(); + originalLocation.setY(this.pos.y()); + Location targetLocation = originalLocation.clone().add(vehicleLocation.getDirection().multiply(1.1)); + if (!isSafeLocation(targetLocation)) { + targetLocation = findSafeLocationNearby(originalLocation); + if (targetLocation == null) return; + } + targetLocation.setYaw(player.getLocation().getYaw()); + targetLocation.setPitch(player.getLocation().getPitch()); + if (VersionHelper.isFolia()) { + player.teleportAsync(targetLocation); + } else { + player.teleport(targetLocation); + } + } + + private boolean isSafeLocation(Location location) { + World world = location.getWorld(); + if (world == null) return false; + int x = location.getBlockX(); + int y = location.getBlockY(); + int z = location.getBlockZ(); + if (!world.getBlockAt(x, y - 1, z).getType().isSolid()) return false; + if (!world.getBlockAt(x, y, z).isPassable()) return false; + return world.getBlockAt(x, y + 1, z).isPassable(); + } + + @Nullable + private Location findSafeLocationNearby(Location center) { + World world = center.getWorld(); + if (world == null) return null; + int centerX = center.getBlockX(); + int centerY = center.getBlockY(); + int centerZ = center.getBlockZ(); + for (int dx = -1; dx <= 1; dx++) { + for (int dz = -1; dz <= 1; dz++) { + if (dx == 0 && dz == 0) continue; + int x = centerX + dx; + int z = centerZ + dz; + Location nearbyLocation = new Location(world, x + 0.5, centerY, z + 0.5); + if (isSafeLocation(nearbyLocation)) return nearbyLocation; + } + } + return null; + } +} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java index 7cc579dce..b7e58f8be 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/entity/furniture/BukkitFurnitureManager.java @@ -337,6 +337,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { plugin.scheduler().sync().runDelayed(() -> tryLeavingSeat(player, entity), player.getWorld(), location.getBlockX() >> 4, location.getBlockZ() >> 4); } + @SuppressWarnings("DuplicatedCode") protected void tryLeavingSeat(@NotNull Player player, @NotNull Entity vehicle) { Integer baseFurniture = vehicle.getPersistentDataContainer().get(FURNITURE_SEAT_BASE_ENTITY_KEY, PersistentDataType.INTEGER); if (baseFurniture == null) return; @@ -375,6 +376,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { return (entity instanceof ArmorStand || entity instanceof ItemDisplay); } + @SuppressWarnings("DuplicatedCode") private boolean isSafeLocation(Location location) { World world = location.getWorld(); if (world == null) return false; @@ -386,6 +388,7 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { return world.getBlockAt(x, y + 1, z).isPassable(); } + @SuppressWarnings("DuplicatedCode") @Nullable private Location findSafeLocationNearby(Location center) { World world = center.getWorld(); diff --git a/common-files/src/main/resources/resources/default/configuration/blocks.yml b/common-files/src/main/resources/resources/default/configuration/blocks.yml index 2384cba31..f3b182d5b 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks.yml @@ -587,10 +587,13 @@ items#misc: step: minecraft:block.wood.step tags: - minecraft:mineable/axe - behavior: - type: bouncing_block - bounce-height: 0.66 - sync-player-position: false + behaviors: + - type: bouncing_block + bounce-height: 0.66 + sync-player-position: false + - type: seat_block + offset: 0,-0.5,0 + limit-player-rotation: false state: id: 0 state: white_bed[facing=west,occupied=false,part=foot] @@ -638,6 +641,8 @@ items#misc: - type: sofa_block - type: bouncing_block bounce-height: 0.66 + - type: seat_block + offset: 0,-0.45,0 states: properties: facing: diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/EntityBlockBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/EntityBlockBehavior.java index e994ca03e..5df15876e 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/EntityBlockBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/EntityBlockBehavior.java @@ -18,4 +18,9 @@ public interface EntityBlockBehavior { default BlockEntityTicker createBlockEntityTicker(CEWorld level, ImmutableBlockState state, BlockEntityType blockEntityType) { return null; } + + @SuppressWarnings("unchecked") + static BlockEntityTicker createTickerHelper(BlockEntityTicker ticker) { + return (BlockEntityTicker) ticker; + } } diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java index cb452fd4d..b801d9156 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/entity/BlockEntityTypeKeys.java @@ -7,4 +7,5 @@ public final class BlockEntityTypeKeys { public static final Key UNSAFE_COMPOSITE = Key.of("craftengine:unsafe_composite"); public static final Key SIMPLE_STORAGE = Key.of("craftengine:simple_storage"); + public static final Key SEAT = Key.of("craftengine:seat"); } From c70b765a32417ba5291cb8b438e917446aa48798 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 13:41:00 +0800 Subject: [PATCH 03/13] =?UTF-8?q?fix(block):=20=E8=A1=A5=E4=B8=80=E4=B8=8B?= =?UTF-8?q?=E6=8C=A5=E6=89=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../craftengine/bukkit/block/behavior/SeatBlockBehavior.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java index 252c8b11d..bc8995e80 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java @@ -36,12 +36,13 @@ public class SeatBlockBehavior extends BukkitBlockBehavior implements EntityBloc @Override public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) { BukkitServerPlayer player = (BukkitServerPlayer) context.getPlayer(); - if (player == null || player.isSecondaryUseActive() || player.platformPlayer() == null) { + if (player == null || player.isSecondaryUseActive()) { return InteractionResult.PASS; } CEWorld world = context.getLevel().storageWorld(); BlockEntity blockEntity = world.getBlockEntityAtIfLoaded(context.getClickedPos()); if (!(blockEntity instanceof SeatBlockEntity seatBlockEntity) || !seatBlockEntity.seatEntities().isEmpty()) { + player.swingHand(context.getHand()); return InteractionResult.PASS; } seatBlockEntity.spawnSeatEntityForPlayer(player.platformPlayer(), this.offset, this.yaw, this.limitPlayerRotation); From 071b6872e4caf55f0e6dce1bee9041f10594b386 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 14:44:22 +0800 Subject: [PATCH 04/13] =?UTF-8?q?fix(block):=20=E4=BF=AE=E5=A4=8D=E5=BC=82?= =?UTF-8?q?=E5=B8=B8=E8=B9=A6=E8=B5=B7=E6=9D=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/behavior/BouncingBlockBehavior.java | 21 ++++++++++++++++--- .../block/behavior/SeatBlockBehavior.java | 2 +- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java index 2d40df2d3..01d3539db 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java @@ -1,15 +1,18 @@ package net.momirealms.craftengine.bukkit.block.behavior; import net.momirealms.craftengine.bukkit.nms.FastNMS; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.plugin.reflection.minecraft.CoreReflections; import net.momirealms.craftengine.bukkit.util.LocationUtils; import net.momirealms.craftengine.core.block.BlockBehavior; import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; import net.momirealms.craftengine.core.block.behavior.special.TriggerOnceBlockBehavior; +import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.Vec3d; +import org.bukkit.entity.Entity; import java.util.Map; import java.util.concurrent.Callable; @@ -31,7 +34,7 @@ public class BouncingBlockBehavior extends BukkitBlockBehavior implements Trigge public void fallOn(Object thisBlock, Object[] args, Callable superMethod) { if (this.fallDamageMultiplier <= 0.0) return; Object entity = args[3]; - Object finalFallDistance = VersionHelper.isOrAbove1_21_5() ? (double) args[4] * this.fallDamageMultiplier : (float) args[4] * this.fallDamageMultiplier; + Object finalFallDistance = VersionHelper.isOrAbove1_21_5() ? (double) args[4] * this.fallDamageMultiplier : (float) args[4] * (float) this.fallDamageMultiplier; FastNMS.INSTANCE.method$Entity$causeFallDamage( entity, finalFallDistance, 1.0F, FastNMS.INSTANCE.method$DamageSources$fall(FastNMS.INSTANCE.method$Entity$damageSources(entity)) @@ -55,9 +58,21 @@ public class BouncingBlockBehavior extends BukkitBlockBehavior implements Trigge double y = -deltaMovement.y * this.bounceHeight * d; FastNMS.INSTANCE.method$Entity$setDeltaMovement(entity, deltaMovement.x, y, deltaMovement.z); if (CoreReflections.clazz$Player.isInstance(entity) && this.syncPlayerPosition - && /* 防抖 -> */ y > 0.032 /* <- 防抖 */ + && /* 防抖 -> */ y > 0.035 /* <- 防抖 */ ) { - FastNMS.INSTANCE.field$Entity$hurtMarked(entity, true); + // 这里一定要延迟 1t 不然就会出问题 + if (VersionHelper.isFolia()) { + Entity bukkitEntity = FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity); + bukkitEntity.getScheduler().runDelayed(BukkitCraftEngine.instance().javaPlugin(), + r -> FastNMS.INSTANCE.field$Entity$hurtMarked(entity, true), + () -> {}, 1L + ); + } else { + CraftEngine.instance().scheduler().sync().runLater( + () -> FastNMS.INSTANCE.field$Entity$hurtMarked(entity, true), + 1L + ); + } } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java index bc8995e80..7cd3d28a2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java @@ -39,10 +39,10 @@ public class SeatBlockBehavior extends BukkitBlockBehavior implements EntityBloc if (player == null || player.isSecondaryUseActive()) { return InteractionResult.PASS; } + player.swingHand(context.getHand()); CEWorld world = context.getLevel().storageWorld(); BlockEntity blockEntity = world.getBlockEntityAtIfLoaded(context.getClickedPos()); if (!(blockEntity instanceof SeatBlockEntity seatBlockEntity) || !seatBlockEntity.seatEntities().isEmpty()) { - player.swingHand(context.getHand()); return InteractionResult.PASS; } seatBlockEntity.spawnSeatEntityForPlayer(player.platformPlayer(), this.offset, this.yaw, this.limitPlayerRotation); From 0ae97b8d48e66e86b0f40732dcacdcf363717f72 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 15:16:02 +0800 Subject: [PATCH 05/13] =?UTF-8?q?fix(block):=20=E4=BF=AE=E5=A4=8D=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E5=AE=89=E5=85=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/behavior/BouncingBlockBehavior.java | 2 +- .../bukkit/block/entity/SeatBlockEntity.java | 44 ++++++++++++++++--- 2 files changed, 40 insertions(+), 6 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java index 01d3539db..f72f41ed8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java @@ -65,7 +65,7 @@ public class BouncingBlockBehavior extends BukkitBlockBehavior implements Trigge Entity bukkitEntity = FastNMS.INSTANCE.method$Entity$getBukkitEntity(entity); bukkitEntity.getScheduler().runDelayed(BukkitCraftEngine.instance().javaPlugin(), r -> FastNMS.INSTANCE.field$Entity$hurtMarked(entity, true), - () -> {}, 1L + null, 1L ); } else { CraftEngine.instance().scheduler().sync().runLater( diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java index 40f6473cf..63320eb1b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java @@ -1,6 +1,8 @@ package net.momirealms.craftengine.bukkit.block.entity; +import com.google.common.collect.ImmutableList; import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; +import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; import net.momirealms.craftengine.bukkit.util.EntityUtils; import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils; import net.momirealms.craftengine.core.block.ImmutableBlockState; @@ -35,13 +37,45 @@ public class SeatBlockEntity extends BlockEntity { } public static void tick(CEWorld world, BlockPos pos, ImmutableBlockState state, SeatBlockEntity seat) { - if (seat.seatEntities.isEmpty()) return; - for (Map.Entry entry : seat.seatEntities.entrySet()) { + int size = seat.seatEntities.size(); + if (size == 0) return; + if (size == 1) { + // 99.9999%的情况下会命中这里 + Map.Entry entry = seat.seatEntities.entrySet().iterator().next(); Entity entity = entry.getKey(); - if (!entity.getPassengers().isEmpty()) continue; Player player = entry.getValue(); - seat.tryLeavingSeat(player, entity); - seat.seatEntities.remove(entity); + if (VersionHelper.isFolia()) { + entity.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), t -> { + if (entity.getPassengers().isEmpty()) { + seat.tryLeavingSeat(player, entity); + seat.seatEntities.remove(entity); + } + }, null); + } else { + if (entity.getPassengers().isEmpty()) { + seat.tryLeavingSeat(player, entity); + seat.seatEntities.remove(entity); + } + } + return; + } + for (Map.Entry entry : ImmutableList.copyOf(seat.seatEntities.entrySet())) { + // 几乎不可能命中这里,除非写出bug了 + Entity entity = entry.getKey(); + Player player = entry.getValue(); + if (VersionHelper.isFolia()) { + entity.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), t -> { + if (entity.getPassengers().isEmpty()) { + seat.tryLeavingSeat(player, entity); + seat.seatEntities.remove(entity); + } + }, null); + } else { + if (entity.getPassengers().isEmpty()) { + seat.tryLeavingSeat(player, entity); + seat.seatEntities.remove(entity); + } + } } } From 760a98319438bb5dcccf1f5ac5a63721a6820830 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 15:24:39 +0800 Subject: [PATCH 06/13] =?UTF-8?q?fix(block):=20=E4=BF=AE=E5=A4=8D=E7=BA=BF?= =?UTF-8?q?=E7=A8=8B=E5=AE=89=E5=85=A8=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../craftengine/bukkit/block/entity/SeatBlockEntity.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java index 63320eb1b..e39b6c2ae 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java @@ -82,12 +82,11 @@ public class SeatBlockEntity extends BlockEntity { @Override public void preRemove() { if (this.seatEntities.isEmpty()) return; - for (Map.Entry entry : this.seatEntities.entrySet()) { - Entity entity = entry.getKey(); - entity.remove(); - this.seatEntities.remove(entity); + try { + this.seatEntities.keySet().forEach(Entity::remove); + } finally { + this.seatEntities.clear(); } - this.seatEntities.clear(); } public void spawnSeatEntityForPlayer(@NotNull Player player, @NotNull Vector3f offset, float yaw, boolean limitPlayerRotation) { From ee37c8cd6820b70bddeb994e40726cd49f58ccd3 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 17:16:07 +0800 Subject: [PATCH 07/13] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resources/default/configuration/block_name.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common-files/src/main/resources/resources/default/configuration/block_name.yml b/common-files/src/main/resources/resources/default/configuration/block_name.yml index 4c750da5a..97e421dac 100644 --- a/common-files/src/main/resources/resources/default/configuration/block_name.yml +++ b/common-files/src/main/resources/resources/default/configuration/block_name.yml @@ -28,8 +28,8 @@ lang: block_name:default:copper_coil: Copper Coil block_name:default:chessboard_block: Chessboard Block block_name:default:safe_block: Safe Block + block_name:default:sleeper_sofa: Sofa block_name:default:sofa: Sofa - block_name:default:connectable_sofa: Sofa zh_cn: block_name:default:chinese_lantern: 灯笼 block_name:default:netherite_anvil: 下界合金砧 @@ -56,5 +56,5 @@ lang: block_name:default:copper_coil: 铜线圈 block_name:default:chessboard_block: 棋盘方块 block_name:default:safe_block: 保险柜 - block_name:default:sofa: 沙发 - block_name:default:connectable_sofa: 沙发 \ No newline at end of file + block_name:default:sleeper_sofa: 沙发 + block_name:default:sofa: 沙发 \ No newline at end of file From 1cb63e21950a9db7fdfa85b176840787606b43cc Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 17:40:35 +0800 Subject: [PATCH 08/13] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=BD=AC?= =?UTF-8?q?=E6=8D=A2=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bukkit/block/behavior/BouncingBlockBehavior.java | 4 ++-- gradle.properties | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java index f72f41ed8..f7895e804 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BouncingBlockBehavior.java @@ -34,9 +34,9 @@ public class BouncingBlockBehavior extends BukkitBlockBehavior implements Trigge public void fallOn(Object thisBlock, Object[] args, Callable superMethod) { if (this.fallDamageMultiplier <= 0.0) return; Object entity = args[3]; - Object finalFallDistance = VersionHelper.isOrAbove1_21_5() ? (double) args[4] * this.fallDamageMultiplier : (float) args[4] * (float) this.fallDamageMultiplier; + Number fallDistance = (Number) args[4]; FastNMS.INSTANCE.method$Entity$causeFallDamage( - entity, finalFallDistance, 1.0F, + entity, fallDistance.doubleValue() * this.fallDamageMultiplier, 1.0F, FastNMS.INSTANCE.method$DamageSources$fall(FastNMS.INSTANCE.method$Entity$damageSources(entity)) ); } diff --git a/gradle.properties b/gradle.properties index b366a9595..7f85f1eb8 100644 --- a/gradle.properties +++ b/gradle.properties @@ -50,7 +50,7 @@ byte_buddy_version=1.17.5 ahocorasick_version=0.6.3 snake_yaml_version=2.5 anti_grief_version=0.20 -nms_helper_version=1.0.82 +nms_helper_version=1.0.83 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.33.1 From 2c1251ce247142e4709d269fa1410a220b45871c Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 19:44:02 +0800 Subject: [PATCH 09/13] =?UTF-8?q?=E8=AE=A9=E6=88=91=E4=BB=AC=E7=9A=84?= =?UTF-8?q?=E4=B8=8B=E7=95=8C=E5=90=88=E9=87=91=E7=A0=A7=E6=91=94=E4=B8=8D?= =?UTF-8?q?=E6=AD=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/resources/resources/default/configuration/blocks.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/common-files/src/main/resources/resources/default/configuration/blocks.yml b/common-files/src/main/resources/resources/default/configuration/blocks.yml index f3b182d5b..23fbb2cf8 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks.yml @@ -69,7 +69,6 @@ items#misc: overrides: tags: - minecraft:mineable/pickaxe - - minecraft:anvil sounds: break: minecraft:block.anvil.break step: minecraft:block.anvil.step From ce55b9c2f69e3292950850d3b4653410bdba7dda Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 20:04:01 +0800 Subject: [PATCH 10/13] =?UTF-8?q?=E5=A6=82=E6=9E=9C=E4=B8=8B=E7=95=8C?= =?UTF-8?q?=E5=90=88=E9=87=91=E7=A0=A7=E6=91=94=E6=AD=BB=E8=A6=81=E6=9C=89?= =?UTF-8?q?=E5=A3=B0=E9=9F=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/FallingBlockRemoveListener.java | 43 +++++++++++++------ .../block/behavior/FallingBlockBehavior.java | 18 ++++---- 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/FallingBlockRemoveListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/FallingBlockRemoveListener.java index 5be81793d..d97dd842b 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/FallingBlockRemoveListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/FallingBlockRemoveListener.java @@ -9,10 +9,12 @@ import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldPosition; import org.bukkit.entity.FallingBlock; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityRemoveEvent; import java.util.Optional; @@ -20,32 +22,47 @@ import java.util.Optional; public final class FallingBlockRemoveListener implements Listener { @EventHandler - public void onFallingBlockBreak(org.bukkit.event.entity.EntityRemoveEvent event) { - if (event.getCause() == org.bukkit.event.entity.EntityRemoveEvent.Cause.DROP && event.getEntity() instanceof FallingBlock fallingBlock) { - try { + public void onFallingBlockBreak(EntityRemoveEvent event) { + if (!(event.getEntity() instanceof FallingBlock fallingBlock)) return; + try { + if (event.getCause() == EntityRemoveEvent.Cause.DROP) { Object fallingBlockEntity = CraftBukkitReflections.field$CraftEntity$entity.get(fallingBlock); - boolean cancelDrop = (boolean) CoreReflections.field$FallingBlockEntity$cancelDrop.get(fallingBlockEntity); - if (cancelDrop) return; Object blockState = CoreReflections.field$FallingBlockEntity$blockState.get(fallingBlockEntity); Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); if (optionalCustomState.isEmpty()) return; ImmutableBlockState customState = optionalCustomState.get(); - net.momirealms.craftengine.core.world.World world = new BukkitWorld(fallingBlock.getWorld()); + World world = new BukkitWorld(fallingBlock.getWorld()); WorldPosition position = new WorldPosition(world, CoreReflections.field$Entity$xo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$yo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$zo.getDouble(fallingBlockEntity)); - ContextHolder.Builder builder = ContextHolder.builder() - .withParameter(DirectContextParameters.FALLING_BLOCK, true) - .withParameter(DirectContextParameters.POSITION, position); - for (Item item : customState.getDrops(builder, world, null)) { - world.dropItemNaturally(position, item); + boolean cancelDrop = (boolean) CoreReflections.field$FallingBlockEntity$cancelDrop.get(fallingBlockEntity); + if (!cancelDrop) { + ContextHolder.Builder builder = ContextHolder.builder() + .withParameter(DirectContextParameters.FALLING_BLOCK, true) + .withParameter(DirectContextParameters.POSITION, position); + for (Item item : customState.getDrops(builder, world, null)) { + world.dropItemNaturally(position, item); + } } Object entityData = CoreReflections.field$Entity$entityData.get(fallingBlockEntity); boolean isSilent = (boolean) CoreReflections.method$SynchedEntityData$get.invoke(entityData, CoreReflections.instance$Entity$DATA_SILENT); if (!isSilent) { world.playBlockSound(position, customState.settings().sounds().destroySound()); } - } catch (ReflectiveOperationException e) { - CraftEngine.instance().logger().warn("Failed to handle EntityRemoveEvent", e); + } else if (event.getCause() == EntityRemoveEvent.Cause.DESPAWN) { + Object fallingBlockEntity = CraftBukkitReflections.field$CraftEntity$entity.get(fallingBlock); + Object blockState = CoreReflections.field$FallingBlockEntity$blockState.get(fallingBlockEntity); + Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); + if (optionalCustomState.isEmpty()) return; + ImmutableBlockState customState = optionalCustomState.get(); + World world = new BukkitWorld(fallingBlock.getWorld()); + WorldPosition position = new WorldPosition(world, CoreReflections.field$Entity$xo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$yo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$zo.getDouble(fallingBlockEntity)); + Object entityData = CoreReflections.field$Entity$entityData.get(fallingBlockEntity); + boolean isSilent = (boolean) CoreReflections.method$SynchedEntityData$get.invoke(entityData, CoreReflections.instance$Entity$DATA_SILENT); + if (!isSilent) { + world.playBlockSound(position, customState.settings().sounds().destroySound()); + } } + } catch (ReflectiveOperationException e) { + CraftEngine.instance().logger().warn("Failed to handle EntityRemoveEvent", e); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java index 308e0168e..52173b8e8 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java @@ -16,6 +16,7 @@ import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextPar import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.Vec3d; +import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldPosition; import java.util.Map; @@ -80,19 +81,20 @@ public class FallingBlockBehavior extends BukkitBlockBehavior { if (VersionHelper.isOrAbove1_20_3()) return; Object level = args[0]; Object fallingBlockEntity = args[2]; - boolean cancelDrop = (boolean) CoreReflections.field$FallingBlockEntity$cancelDrop.get(fallingBlockEntity); - if (cancelDrop) return; Object blockState = CoreReflections.field$FallingBlockEntity$blockState.get(fallingBlockEntity); Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); if (optionalCustomState.isEmpty()) return; ImmutableBlockState customState = optionalCustomState.get(); - net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); + World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); WorldPosition position = new WorldPosition(world, CoreReflections.field$Entity$xo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$yo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$zo.getDouble(fallingBlockEntity)); - ContextHolder.Builder builder = ContextHolder.builder() - .withParameter(DirectContextParameters.FALLING_BLOCK, true) - .withParameter(DirectContextParameters.POSITION, position); - for (Item item : customState.getDrops(builder, world, null)) { - world.dropItemNaturally(position, item); + boolean cancelDrop = (boolean) CoreReflections.field$FallingBlockEntity$cancelDrop.get(fallingBlockEntity); + if (!cancelDrop) { + ContextHolder.Builder builder = ContextHolder.builder() + .withParameter(DirectContextParameters.FALLING_BLOCK, true) + .withParameter(DirectContextParameters.POSITION, position); + for (Item item : customState.getDrops(builder, world, null)) { + world.dropItemNaturally(position, item); + } } Object entityData = CoreReflections.field$Entity$entityData.get(fallingBlockEntity); boolean isSilent = (boolean) CoreReflections.method$SynchedEntityData$get.invoke(entityData, CoreReflections.instance$Entity$DATA_SILENT); From 4d9dcd431a5713b441e0ebb9c28caad2f363ebd3 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 20:25:04 +0800 Subject: [PATCH 11/13] =?UTF-8?q?Revert=20"=E5=A6=82=E6=9E=9C=E4=B8=8B?= =?UTF-8?q?=E7=95=8C=E5=90=88=E9=87=91=E7=A0=A7=E6=91=94=E6=AD=BB=E8=A6=81?= =?UTF-8?q?=E6=9C=89=E5=A3=B0=E9=9F=B3"?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit ce55b9c2f69e3292950850d3b4653410bdba7dda. --- .../block/FallingBlockRemoveListener.java | 43 ++++++------------- .../block/behavior/FallingBlockBehavior.java | 18 ++++---- 2 files changed, 21 insertions(+), 40 deletions(-) diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/FallingBlockRemoveListener.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/FallingBlockRemoveListener.java index d97dd842b..5be81793d 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/FallingBlockRemoveListener.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/FallingBlockRemoveListener.java @@ -9,12 +9,10 @@ import net.momirealms.craftengine.core.item.Item; import net.momirealms.craftengine.core.plugin.CraftEngine; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; -import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldPosition; import org.bukkit.entity.FallingBlock; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityRemoveEvent; import java.util.Optional; @@ -22,47 +20,32 @@ import java.util.Optional; public final class FallingBlockRemoveListener implements Listener { @EventHandler - public void onFallingBlockBreak(EntityRemoveEvent event) { - if (!(event.getEntity() instanceof FallingBlock fallingBlock)) return; - try { - if (event.getCause() == EntityRemoveEvent.Cause.DROP) { + public void onFallingBlockBreak(org.bukkit.event.entity.EntityRemoveEvent event) { + if (event.getCause() == org.bukkit.event.entity.EntityRemoveEvent.Cause.DROP && event.getEntity() instanceof FallingBlock fallingBlock) { + try { Object fallingBlockEntity = CraftBukkitReflections.field$CraftEntity$entity.get(fallingBlock); - Object blockState = CoreReflections.field$FallingBlockEntity$blockState.get(fallingBlockEntity); - Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); - if (optionalCustomState.isEmpty()) return; - ImmutableBlockState customState = optionalCustomState.get(); - World world = new BukkitWorld(fallingBlock.getWorld()); - WorldPosition position = new WorldPosition(world, CoreReflections.field$Entity$xo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$yo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$zo.getDouble(fallingBlockEntity)); boolean cancelDrop = (boolean) CoreReflections.field$FallingBlockEntity$cancelDrop.get(fallingBlockEntity); - if (!cancelDrop) { - ContextHolder.Builder builder = ContextHolder.builder() - .withParameter(DirectContextParameters.FALLING_BLOCK, true) - .withParameter(DirectContextParameters.POSITION, position); - for (Item item : customState.getDrops(builder, world, null)) { - world.dropItemNaturally(position, item); - } - } - Object entityData = CoreReflections.field$Entity$entityData.get(fallingBlockEntity); - boolean isSilent = (boolean) CoreReflections.method$SynchedEntityData$get.invoke(entityData, CoreReflections.instance$Entity$DATA_SILENT); - if (!isSilent) { - world.playBlockSound(position, customState.settings().sounds().destroySound()); - } - } else if (event.getCause() == EntityRemoveEvent.Cause.DESPAWN) { - Object fallingBlockEntity = CraftBukkitReflections.field$CraftEntity$entity.get(fallingBlock); + if (cancelDrop) return; Object blockState = CoreReflections.field$FallingBlockEntity$blockState.get(fallingBlockEntity); Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); if (optionalCustomState.isEmpty()) return; ImmutableBlockState customState = optionalCustomState.get(); - World world = new BukkitWorld(fallingBlock.getWorld()); + net.momirealms.craftengine.core.world.World world = new BukkitWorld(fallingBlock.getWorld()); WorldPosition position = new WorldPosition(world, CoreReflections.field$Entity$xo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$yo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$zo.getDouble(fallingBlockEntity)); + ContextHolder.Builder builder = ContextHolder.builder() + .withParameter(DirectContextParameters.FALLING_BLOCK, true) + .withParameter(DirectContextParameters.POSITION, position); + for (Item item : customState.getDrops(builder, world, null)) { + world.dropItemNaturally(position, item); + } Object entityData = CoreReflections.field$Entity$entityData.get(fallingBlockEntity); boolean isSilent = (boolean) CoreReflections.method$SynchedEntityData$get.invoke(entityData, CoreReflections.instance$Entity$DATA_SILENT); if (!isSilent) { world.playBlockSound(position, customState.settings().sounds().destroySound()); } + } catch (ReflectiveOperationException e) { + CraftEngine.instance().logger().warn("Failed to handle EntityRemoveEvent", e); } - } catch (ReflectiveOperationException e) { - CraftEngine.instance().logger().warn("Failed to handle EntityRemoveEvent", e); } } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java index 52173b8e8..308e0168e 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/FallingBlockBehavior.java @@ -16,7 +16,6 @@ import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextPar import net.momirealms.craftengine.core.util.ResourceConfigUtils; import net.momirealms.craftengine.core.util.VersionHelper; import net.momirealms.craftengine.core.world.Vec3d; -import net.momirealms.craftengine.core.world.World; import net.momirealms.craftengine.core.world.WorldPosition; import java.util.Map; @@ -81,20 +80,19 @@ public class FallingBlockBehavior extends BukkitBlockBehavior { if (VersionHelper.isOrAbove1_20_3()) return; Object level = args[0]; Object fallingBlockEntity = args[2]; + boolean cancelDrop = (boolean) CoreReflections.field$FallingBlockEntity$cancelDrop.get(fallingBlockEntity); + if (cancelDrop) return; Object blockState = CoreReflections.field$FallingBlockEntity$blockState.get(fallingBlockEntity); Optional optionalCustomState = BlockStateUtils.getOptionalCustomBlockState(blockState); if (optionalCustomState.isEmpty()) return; ImmutableBlockState customState = optionalCustomState.get(); - World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); + net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); WorldPosition position = new WorldPosition(world, CoreReflections.field$Entity$xo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$yo.getDouble(fallingBlockEntity), CoreReflections.field$Entity$zo.getDouble(fallingBlockEntity)); - boolean cancelDrop = (boolean) CoreReflections.field$FallingBlockEntity$cancelDrop.get(fallingBlockEntity); - if (!cancelDrop) { - ContextHolder.Builder builder = ContextHolder.builder() - .withParameter(DirectContextParameters.FALLING_BLOCK, true) - .withParameter(DirectContextParameters.POSITION, position); - for (Item item : customState.getDrops(builder, world, null)) { - world.dropItemNaturally(position, item); - } + ContextHolder.Builder builder = ContextHolder.builder() + .withParameter(DirectContextParameters.FALLING_BLOCK, true) + .withParameter(DirectContextParameters.POSITION, position); + for (Item item : customState.getDrops(builder, world, null)) { + world.dropItemNaturally(position, item); } Object entityData = CoreReflections.field$Entity$entityData.get(fallingBlockEntity); boolean isSilent = (boolean) CoreReflections.method$SynchedEntityData$get.invoke(entityData, CoreReflections.instance$Entity$DATA_SILENT); From d6b2241325a509344576e4695c96126f2e5acc25 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 20:26:55 +0800 Subject: [PATCH 12/13] =?UTF-8?q?=E6=92=A4=E9=94=80=E5=BA=A7=E4=BD=8D?= =?UTF-8?q?=E6=96=B9=E5=9D=97=E8=A1=8C=E4=B8=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../block/behavior/BukkitBlockBehaviors.java | 2 - .../block/behavior/SeatBlockBehavior.java | 78 ------- .../block/entity/BukkitBlockEntityTypes.java | 1 - .../bukkit/block/entity/SeatBlockEntity.java | 212 ------------------ .../default/configuration/blocks.yml | 5 - 5 files changed, 298 deletions(-) delete mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java delete mode 100644 bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java index f13476d45..34435ad14 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/BukkitBlockBehaviors.java @@ -32,7 +32,6 @@ public class BukkitBlockBehaviors extends BlockBehaviors { public static final Key TOGGLEABLE_LAMP_BLOCK = Key.from("craftengine:toggleable_lamp_block"); public static final Key SOFA_BLOCK = Key.from("craftengine:sofa_block"); public static final Key BOUNCING_BLOCK = Key.from("craftengine:bouncing_block"); - public static final Key SEAT_BLOCK = Key.from("craftengine:seat_block"); public static void init() { register(EMPTY, (block, args) -> EmptyBlockBehavior.INSTANCE); @@ -63,6 +62,5 @@ public class BukkitBlockBehaviors extends BlockBehaviors { register(TOGGLEABLE_LAMP_BLOCK, ToggleableLampBlockBehavior.FACTORY); register(SOFA_BLOCK, SofaBlockBehavior.FACTORY); register(BOUNCING_BLOCK, BouncingBlockBehavior.FACTORY); - register(SEAT_BLOCK, SeatBlockBehavior.FACTORY); } } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java deleted file mode 100644 index 7cd3d28a2..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/SeatBlockBehavior.java +++ /dev/null @@ -1,78 +0,0 @@ -package net.momirealms.craftengine.bukkit.block.behavior; - -import net.momirealms.craftengine.bukkit.block.entity.BukkitBlockEntityTypes; -import net.momirealms.craftengine.bukkit.block.entity.SeatBlockEntity; -import net.momirealms.craftengine.bukkit.plugin.user.BukkitServerPlayer; -import net.momirealms.craftengine.core.block.BlockBehavior; -import net.momirealms.craftengine.core.block.CustomBlock; -import net.momirealms.craftengine.core.block.ImmutableBlockState; -import net.momirealms.craftengine.core.block.behavior.BlockBehaviorFactory; -import net.momirealms.craftengine.core.block.behavior.EntityBlockBehavior; -import net.momirealms.craftengine.core.block.entity.BlockEntity; -import net.momirealms.craftengine.core.block.entity.BlockEntityType; -import net.momirealms.craftengine.core.block.entity.tick.BlockEntityTicker; -import net.momirealms.craftengine.core.entity.player.InteractionResult; -import net.momirealms.craftengine.core.item.context.UseOnContext; -import net.momirealms.craftengine.core.util.ResourceConfigUtils; -import net.momirealms.craftengine.core.world.BlockPos; -import net.momirealms.craftengine.core.world.CEWorld; -import org.joml.Vector3f; - -import java.util.Map; - -public class SeatBlockBehavior extends BukkitBlockBehavior implements EntityBlockBehavior { - public static final Factory FACTORY = new Factory(); - private final Vector3f offset; - private final float yaw; - private final boolean limitPlayerRotation; - - public SeatBlockBehavior(CustomBlock customBlock, Vector3f offset, float yaw, boolean limitPlayerRotation) { - super(customBlock); - this.offset = offset; - this.yaw = yaw; - this.limitPlayerRotation = limitPlayerRotation; - } - - @Override - public InteractionResult useWithoutItem(UseOnContext context, ImmutableBlockState state) { - BukkitServerPlayer player = (BukkitServerPlayer) context.getPlayer(); - if (player == null || player.isSecondaryUseActive()) { - return InteractionResult.PASS; - } - player.swingHand(context.getHand()); - CEWorld world = context.getLevel().storageWorld(); - BlockEntity blockEntity = world.getBlockEntityAtIfLoaded(context.getClickedPos()); - if (!(blockEntity instanceof SeatBlockEntity seatBlockEntity) || !seatBlockEntity.seatEntities().isEmpty()) { - return InteractionResult.PASS; - } - seatBlockEntity.spawnSeatEntityForPlayer(player.platformPlayer(), this.offset, this.yaw, this.limitPlayerRotation); - return InteractionResult.SUCCESS_AND_CANCEL; - } - - @SuppressWarnings("unchecked") - @Override - public BlockEntityType blockEntityType() { - return (BlockEntityType) BukkitBlockEntityTypes.SEAT; - } - - @Override - public BlockEntity createBlockEntity(BlockPos pos, ImmutableBlockState state) { - return new SeatBlockEntity(pos, state); - } - - @Override - public BlockEntityTicker createBlockEntityTicker(CEWorld level, ImmutableBlockState state, BlockEntityType blockEntityType) { - return EntityBlockBehavior.createTickerHelper(SeatBlockEntity::tick); - } - - public static class Factory implements BlockBehaviorFactory { - - @Override - public BlockBehavior create(CustomBlock block, Map arguments) { - Vector3f offset = ResourceConfigUtils.getAsVector3f(arguments.getOrDefault("offset", "0,0,0"), "offset"); - float yaw = ResourceConfigUtils.getAsFloat(arguments.getOrDefault("yaw", 0f), "yaw"); - boolean limitPlayerRotation = ResourceConfigUtils.getAsBoolean(arguments.getOrDefault("limit-player-rotation", true), "limit-player-rotation"); - return new SeatBlockBehavior(block, offset, yaw, limitPlayerRotation); - } - } -} diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java index c739d0bc4..3e778bd32 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/BukkitBlockEntityTypes.java @@ -6,5 +6,4 @@ import net.momirealms.craftengine.core.block.entity.BlockEntityTypes; public class BukkitBlockEntityTypes extends BlockEntityTypes { public static final BlockEntityType SIMPLE_STORAGE = register(BlockEntityTypeKeys.SIMPLE_STORAGE, SimpleStorageBlockEntity::new); - public static final BlockEntityType SEAT = register(BlockEntityTypeKeys.SEAT, SeatBlockEntity::new); } \ No newline at end of file diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java deleted file mode 100644 index e39b6c2ae..000000000 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/entity/SeatBlockEntity.java +++ /dev/null @@ -1,212 +0,0 @@ -package net.momirealms.craftengine.bukkit.block.entity; - -import com.google.common.collect.ImmutableList; -import it.unimi.dsi.fastutil.objects.Reference2ObjectArrayMap; -import net.momirealms.craftengine.bukkit.plugin.BukkitCraftEngine; -import net.momirealms.craftengine.bukkit.util.EntityUtils; -import net.momirealms.craftengine.bukkit.util.LegacyAttributeUtils; -import net.momirealms.craftengine.core.block.ImmutableBlockState; -import net.momirealms.craftengine.core.block.entity.BlockEntity; -import net.momirealms.craftengine.core.block.properties.Property; -import net.momirealms.craftengine.core.util.HorizontalDirection; -import net.momirealms.craftengine.core.util.QuaternionUtils; -import net.momirealms.craftengine.core.util.VersionHelper; -import net.momirealms.craftengine.core.world.BlockPos; -import net.momirealms.craftengine.core.world.CEWorld; -import org.bukkit.Location; -import org.bukkit.World; -import org.bukkit.attribute.Attribute; -import org.bukkit.entity.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.joml.Vector3f; - -import java.util.Map; -import java.util.Objects; - -@SuppressWarnings("DuplicatedCode") -public class SeatBlockEntity extends BlockEntity { - private final Map seatEntities = new Reference2ObjectArrayMap<>(1); - - public SeatBlockEntity(BlockPos pos, ImmutableBlockState blockState) { - super(BukkitBlockEntityTypes.SEAT, pos, blockState); - } - - public Map seatEntities() { - return this.seatEntities; - } - - public static void tick(CEWorld world, BlockPos pos, ImmutableBlockState state, SeatBlockEntity seat) { - int size = seat.seatEntities.size(); - if (size == 0) return; - if (size == 1) { - // 99.9999%的情况下会命中这里 - Map.Entry entry = seat.seatEntities.entrySet().iterator().next(); - Entity entity = entry.getKey(); - Player player = entry.getValue(); - if (VersionHelper.isFolia()) { - entity.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), t -> { - if (entity.getPassengers().isEmpty()) { - seat.tryLeavingSeat(player, entity); - seat.seatEntities.remove(entity); - } - }, null); - } else { - if (entity.getPassengers().isEmpty()) { - seat.tryLeavingSeat(player, entity); - seat.seatEntities.remove(entity); - } - } - return; - } - for (Map.Entry entry : ImmutableList.copyOf(seat.seatEntities.entrySet())) { - // 几乎不可能命中这里,除非写出bug了 - Entity entity = entry.getKey(); - Player player = entry.getValue(); - if (VersionHelper.isFolia()) { - entity.getScheduler().run(BukkitCraftEngine.instance().javaPlugin(), t -> { - if (entity.getPassengers().isEmpty()) { - seat.tryLeavingSeat(player, entity); - seat.seatEntities.remove(entity); - } - }, null); - } else { - if (entity.getPassengers().isEmpty()) { - seat.tryLeavingSeat(player, entity); - seat.seatEntities.remove(entity); - } - } - } - } - - @Override - public void preRemove() { - if (this.seatEntities.isEmpty()) return; - try { - this.seatEntities.keySet().forEach(Entity::remove); - } finally { - this.seatEntities.clear(); - } - } - - public void spawnSeatEntityForPlayer(@NotNull Player player, @NotNull Vector3f offset, float yaw, boolean limitPlayerRotation) { - if (!this.seatEntities.isEmpty() || !this.isValid()) return; - Location location = calculateSeatLocation(player, this.pos, this.blockState, offset, yaw); - Entity seatEntity = limitPlayerRotation ? - EntityUtils.spawnEntity(player.getWorld(), - VersionHelper.isOrAbove1_20_2() ? location.subtract(0, 0.9875, 0) : location.subtract(0, 0.990625, 0), - EntityType.ARMOR_STAND, - entity -> { - ArmorStand armorStand = (ArmorStand) entity; - if (VersionHelper.isOrAbove1_21_3()) { - Objects.requireNonNull(armorStand.getAttribute(Attribute.MAX_HEALTH)).setBaseValue(0.01); - } else { - LegacyAttributeUtils.setMaxHealth(armorStand); - } - armorStand.setSmall(true); - armorStand.setInvisible(true); - armorStand.setSilent(true); - armorStand.setInvulnerable(true); - armorStand.setArms(false); - armorStand.setCanTick(false); - armorStand.setAI(false); - armorStand.setGravity(false); - armorStand.setPersistent(false); - }) : - EntityUtils.spawnEntity(player.getWorld(), - VersionHelper.isOrAbove1_20_2() ? location : location.subtract(0, 0.25, 0), - EntityType.ITEM_DISPLAY, - entity -> { - ItemDisplay itemDisplay = (ItemDisplay) entity; - itemDisplay.setPersistent(false); - }); - if (!seatEntity.addPassenger(player)) { - seatEntity.remove(); - return; - } - this.seatEntities.put(seatEntity, player); - } - - private Location calculateSeatLocation(Player player, BlockPos pos, ImmutableBlockState state, Vector3f offset, float yaw) { - Location location = new Location(player.getWorld(), pos.x() + 0.5, pos.y() + 0.5, pos.z() + 0.5); - for (Property property : state.getProperties()) { - if (property.name().equals("facing") && property.valueClass() == HorizontalDirection.class) { - switch ((HorizontalDirection) state.get(property)) { - case NORTH -> location.setYaw(0); - case SOUTH -> location.setYaw(180); - case WEST -> location.setYaw(270); - case EAST -> location.setYaw(90); - } - break; - } - if (property.name().equals("facing_clockwise") && property.valueClass() == HorizontalDirection.class) { - switch ((HorizontalDirection) state.get(property)) { - case NORTH -> location.setYaw(90); - case SOUTH -> location.setYaw(270); - case WEST -> location.setYaw(0); - case EAST -> location.setYaw(180); - } - break; - } - } - Vector3f newOffset = QuaternionUtils.toQuaternionf(0, Math.toRadians(180 - location.getYaw()), 0) - .conjugate() - .transform(new Vector3f(offset)); - double newYaw = yaw + location.getYaw(); - if (newYaw < -180) newYaw += 360; - Location newLocation = location.clone(); - newLocation.setYaw((float) newYaw); - newLocation.add(newOffset.x, newOffset.y + 0.6, -newOffset.z); - return newLocation; - } - - private void tryLeavingSeat(@NotNull Player player, @NotNull Entity vehicle) { - vehicle.remove(); - if (player.getVehicle() != null) return; - Location vehicleLocation = vehicle.getLocation(); - Location originalLocation = vehicleLocation.clone(); - originalLocation.setY(this.pos.y()); - Location targetLocation = originalLocation.clone().add(vehicleLocation.getDirection().multiply(1.1)); - if (!isSafeLocation(targetLocation)) { - targetLocation = findSafeLocationNearby(originalLocation); - if (targetLocation == null) return; - } - targetLocation.setYaw(player.getLocation().getYaw()); - targetLocation.setPitch(player.getLocation().getPitch()); - if (VersionHelper.isFolia()) { - player.teleportAsync(targetLocation); - } else { - player.teleport(targetLocation); - } - } - - private boolean isSafeLocation(Location location) { - World world = location.getWorld(); - if (world == null) return false; - int x = location.getBlockX(); - int y = location.getBlockY(); - int z = location.getBlockZ(); - if (!world.getBlockAt(x, y - 1, z).getType().isSolid()) return false; - if (!world.getBlockAt(x, y, z).isPassable()) return false; - return world.getBlockAt(x, y + 1, z).isPassable(); - } - - @Nullable - private Location findSafeLocationNearby(Location center) { - World world = center.getWorld(); - if (world == null) return null; - int centerX = center.getBlockX(); - int centerY = center.getBlockY(); - int centerZ = center.getBlockZ(); - for (int dx = -1; dx <= 1; dx++) { - for (int dz = -1; dz <= 1; dz++) { - if (dx == 0 && dz == 0) continue; - int x = centerX + dx; - int z = centerZ + dz; - Location nearbyLocation = new Location(world, x + 0.5, centerY, z + 0.5); - if (isSafeLocation(nearbyLocation)) return nearbyLocation; - } - } - return null; - } -} diff --git a/common-files/src/main/resources/resources/default/configuration/blocks.yml b/common-files/src/main/resources/resources/default/configuration/blocks.yml index 23fbb2cf8..8de04abc3 100644 --- a/common-files/src/main/resources/resources/default/configuration/blocks.yml +++ b/common-files/src/main/resources/resources/default/configuration/blocks.yml @@ -590,9 +590,6 @@ items#misc: - type: bouncing_block bounce-height: 0.66 sync-player-position: false - - type: seat_block - offset: 0,-0.5,0 - limit-player-rotation: false state: id: 0 state: white_bed[facing=west,occupied=false,part=foot] @@ -640,8 +637,6 @@ items#misc: - type: sofa_block - type: bouncing_block bounce-height: 0.66 - - type: seat_block - offset: 0,-0.45,0 states: properties: facing: From df91e5ee8ef295f2cbdd5cf4160cfbe6dcc5f1d6 Mon Sep 17 00:00:00 2001 From: jhqwqmc <2110242767@qq.com> Date: Fri, 12 Sep 2025 20:36:30 +0800 Subject: [PATCH 13/13] =?UTF-8?q?=E7=AE=80=E5=8C=96=E6=97=A0=E6=84=8F?= =?UTF-8?q?=E4=B9=89=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../craftengine/core/block/behavior/EntityBlockBehavior.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/EntityBlockBehavior.java b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/EntityBlockBehavior.java index 5df15876e..b5df01017 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/block/behavior/EntityBlockBehavior.java +++ b/core/src/main/java/net/momirealms/craftengine/core/block/behavior/EntityBlockBehavior.java @@ -20,7 +20,7 @@ public interface EntityBlockBehavior { } @SuppressWarnings("unchecked") - static BlockEntityTicker createTickerHelper(BlockEntityTicker ticker) { - return (BlockEntityTicker) ticker; + static BlockEntityTicker createTickerHelper(BlockEntityTicker ticker) { + return (BlockEntityTicker) ticker; } }