diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoorBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoorBlockBehavior.java index c49967a9e..ab5571ac0 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoorBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoorBlockBehavior.java @@ -23,6 +23,7 @@ import net.momirealms.craftengine.core.item.context.BlockPlaceContext; import net.momirealms.craftengine.core.item.context.UseOnContext; import net.momirealms.craftengine.core.plugin.context.ContextHolder; import net.momirealms.craftengine.core.plugin.context.parameter.DirectContextParameters; +import net.momirealms.craftengine.core.sound.SoundData; import net.momirealms.craftengine.core.util.Direction; import net.momirealms.craftengine.core.util.HorizontalDirection; import net.momirealms.craftengine.core.util.ResourceConfigUtils; @@ -51,6 +52,8 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { private final Property openProperty; private final boolean canOpenWithHand; private final boolean canOpenByWindCharge; + private final SoundData openSound; + private final SoundData closeSound; public DoorBlockBehavior(CustomBlock block, Property halfProperty, @@ -59,7 +62,9 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { Property poweredProperty, Property openProperty, boolean canOpenWithHand, - boolean canOpenByWindCharge) { + boolean canOpenByWindCharge, + SoundData openSound, + SoundData closeSound) { super(block, 0); this.halfProperty = halfProperty; this.facingProperty = facingProperty; @@ -68,6 +73,8 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { this.openProperty = openProperty; this.canOpenWithHand = canOpenWithHand; this.canOpenByWindCharge = canOpenByWindCharge; + this.openSound = openSound; + this.closeSound = closeSound; } public boolean isOpen(ImmutableBlockState state) { @@ -138,7 +145,7 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { @Override public void setPlacedBy(BlockPlaceContext context, ImmutableBlockState state) { BlockPos pos = context.getClickedPos(); - context.getLevel().setBlockAt(pos.x(), pos.y() + 1, pos.z(), state.with(this.halfProperty, DoubleBlockHalf.UPPER).customBlockState(), 3); + context.getLevel().setBlockAt(pos.x(), pos.y() + 1, pos.z(), state.with(this.halfProperty, DoubleBlockHalf.UPPER).customBlockState(), UpdateOption.UPDATE_ALL.flags()); } @Override @@ -213,19 +220,33 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { public void setOpen(@Nullable Player player, Object serverLevel, ImmutableBlockState state, BlockPos pos, boolean isOpen) { if (isOpen(state) != isOpen) { + org.bukkit.World world = FastNMS.INSTANCE.method$Level$getCraftWorld(serverLevel); FastNMS.INSTANCE.method$LevelWriter$setBlock(serverLevel, LocationUtils.toBlockPos(pos), state.with(this.openProperty, isOpen).customBlockState().handle(), UpdateOption.builder().updateImmediate().updateClients().build().flags()); - FastNMS.INSTANCE.method$Level$getCraftWorld(serverLevel).sendGameEvent(player == null ? null : (org.bukkit.entity.Player) player.platformPlayer(), isOpen ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, new Vector(pos.x(), pos.y(), pos.z())); - // todo 播放声音 + world.sendGameEvent(player == null ? null : (org.bukkit.entity.Player) player.platformPlayer(), isOpen ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, new Vector(pos.x(), pos.y(), pos.z())); + SoundData soundData = isOpen ? this.openSound : this.closeSound; + if (soundData != null) { + new BukkitWorld(world).playBlockSound( + new Vec3d(pos.x() + 0.5, pos.y() + 0.5, pos.z() + 0.5), + soundData + ); + } } } @Override public InteractionResult useOnBlock(UseOnContext context, ImmutableBlockState state) { - if (!this.canOpenWithHand || context.getPlayer().isSecondaryUseActive()) { + if (!this.canOpenWithHand) { + return InteractionResult.PASS; + } + if (context.getItem() == null) { + setOpen(context.getPlayer(), context.getLevel().serverWorld(), state, context.getClickedPos(), !state.get(this.openProperty)); + return InteractionResult.SUCCESS; + } else if (!context.getPlayer().isSecondaryUseActive()) { + setOpen(context.getPlayer(), context.getLevel().serverWorld(), state, context.getClickedPos(), !state.get(this.openProperty)); + return InteractionResult.SUCCESS_AND_CANCEL; + } else { return InteractionResult.PASS; } - setOpen(context.getPlayer(), context.getLevel().serverWorld(), state, context.getClickedPos(), !state.get(this.openProperty)); - return InteractionResult.SUCCESS_AND_CANCEL; } @Override @@ -258,8 +279,15 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { Bukkit.getPluginManager().callEvent(event); boolean flag = event.getNewCurrent() > 0; if (flag != immutableBlockState.get(this.openProperty)) { - FastNMS.INSTANCE.method$Level$getCraftWorld(level).sendGameEvent(null, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, new Vector(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ())); - // todo 播放声音 + org.bukkit.World world = FastNMS.INSTANCE.method$Level$getCraftWorld(level); + world.sendGameEvent(null, flag ? GameEvent.BLOCK_OPEN : GameEvent.BLOCK_CLOSE, new Vector(bukkitBlock.getX(), bukkitBlock.getY(), bukkitBlock.getZ())); + SoundData soundData = flag ? this.openSound : this.closeSound; + if (soundData != null) { + new BukkitWorld(world).playBlockSound( + new Vec3d(FastNMS.INSTANCE.field$Vec3i$x(blockPos) + 0.5, FastNMS.INSTANCE.field$Vec3i$y(blockPos) + 0.5, FastNMS.INSTANCE.field$Vec3i$z(blockPos) + 0.5), + soundData + ); + } } FastNMS.INSTANCE.method$LevelWriter$setBlock(level, blockPos, immutableBlockState.with(this.poweredProperty, flag).with(this.openProperty, flag).customBlockState().handle(), UpdateOption.Flags.UPDATE_CLIENTS); } @@ -297,7 +325,14 @@ public class DoorBlockBehavior extends AbstractCanSurviveBlockBehavior { Property powered = (Property) ResourceConfigUtils.requireNonNullOrThrow(block.getProperty("powered"), "warning.config.block.behavior.door.missing_powered"); boolean canOpenWithHand = (boolean) arguments.getOrDefault("can-open-with-hand", true); boolean canOpenByWindCharge = (boolean) arguments.getOrDefault("can-open-by-wind-charge", true); - return new DoorBlockBehavior(block, half, facing, hinge, powered, open, canOpenWithHand, canOpenByWindCharge); + Map sounds = (Map) arguments.get("sounds"); + SoundData openSound = null; + SoundData closeSound = null; + if (sounds != null) { + openSound = Optional.ofNullable(sounds.get("open")).map(obj -> SoundData.create(obj, 1, 1)).orElse(null); + closeSound = Optional.ofNullable(sounds.get("close")).map(obj -> SoundData.create(obj, 1, 1)).orElse(null); + } + return new DoorBlockBehavior(block, half, facing, hinge, powered, open, canOpenWithHand, canOpenByWindCharge, openSound, closeSound); } } } 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 8042863ac..8b55f60df 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 @@ -31,6 +31,7 @@ import java.util.List; import java.util.Map; import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiConsumer; public class BukkitFurnitureManager extends AbstractFurnitureManager { public static final NamespacedKey FURNITURE_KEY = KeyUtils.toNamespacedKey(FurnitureManager.FURNITURE_KEY); @@ -95,15 +96,31 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { COLLISION_ENTITY_TYPE = Config.colliderType(); Bukkit.getPluginManager().registerEvents(this.dismountListener, this.plugin.javaPlugin()); Bukkit.getPluginManager().registerEvents(this.furnitureEventListener, this.plugin.javaPlugin()); - for (World world : Bukkit.getWorlds()) { - List entities = world.getEntities(); - for (Entity entity : entities) { - if (entity instanceof ItemDisplay display) { - handleBaseEntityLoadEarly(display); - } else if (entity instanceof Interaction interaction) { - handleCollisionEntityLoadOnEntitiesLoad(interaction); - } else if (entity instanceof Boat boat) { - handleCollisionEntityLoadOnEntitiesLoad(boat); + if (VersionHelper.isFolia()) { + BiConsumer taskExecutor = (entity, runnable) -> entity.getScheduler().run(this.plugin.javaPlugin(), (t) -> runnable.run(), () -> {}); + for (World world : Bukkit.getWorlds()) { + List entities = world.getEntities(); + for (Entity entity : entities) { + if (entity instanceof ItemDisplay display) { + taskExecutor.accept(entity, () -> handleBaseEntityLoadEarly(display)); + } else if (entity instanceof Interaction interaction) { + taskExecutor.accept(entity, () -> handleCollisionEntityLoadOnEntitiesLoad(interaction)); + } else if (entity instanceof Boat boat) { + taskExecutor.accept(entity, () -> handleCollisionEntityLoadOnEntitiesLoad(boat)); + } + } + } + } else { + for (World world : Bukkit.getWorlds()) { + List entities = world.getEntities(); + for (Entity entity : entities) { + if (entity instanceof ItemDisplay display) { + handleBaseEntityLoadEarly(display); + } else if (entity instanceof Interaction interaction) { + handleCollisionEntityLoadOnEntitiesLoad(interaction); + } else if (entity instanceof Boat boat) { + handleCollisionEntityLoadOnEntitiesLoad(boat); + } } } } @@ -266,6 +283,12 @@ public class BukkitFurnitureManager extends AbstractFurnitureManager { } public void handleCollisionEntityLoadOnEntitiesLoad(Entity collisionEntity) { + // faster + if (FastNMS.INSTANCE.method$CraftEntity$getHandle(collisionEntity) instanceof CollisionEntity) { + collisionEntity.remove(); + return; + } + // not a collision entity Byte flag = collisionEntity.getPersistentDataContainer().get(FURNITURE_COLLISION, PersistentDataType.BYTE); if (flag == null || flag != 1) { diff --git a/common-files/src/main/resources/resources/default/configuration/palm_tree.yml b/common-files/src/main/resources/resources/default/configuration/palm_tree.yml index ee0da60be..07fbe2ea8 100644 --- a/common-files/src/main/resources/resources/default/configuration/palm_tree.yml +++ b/common-files/src/main/resources/resources/default/configuration/palm_tree.yml @@ -350,6 +350,9 @@ items: type: door_block can-open-with-hand: true can-open-by-wind-charge: true + sounds: + open: block.wooden_door.open + close: block.wooden_door.close loot: template: default:loot_table/self settings: