diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java index 93ec4c025..3fb08edd3 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/api/CraftEngineBlocks.java @@ -188,16 +188,14 @@ public final class CraftEngineBlocks { * @param player player who breaks the block * @param dropLoot whether to drop block loots * @param isMoving is moving - * @param playSound whether to play break sounds - * @param sendParticles whether to send break particles + * @param sendLevelEvent whether to send break particles and sounds * @return success or not */ public static boolean remove(@NotNull Block block, @Nullable Player player, boolean isMoving, boolean dropLoot, - boolean playSound, - boolean sendParticles) { + boolean sendLevelEvent) { ImmutableBlockState state = getCustomBlockState(block); if (state == null || state.isEmpty()) return false; World world = new BukkitWorld(block.getWorld()); @@ -215,16 +213,34 @@ public final class CraftEngineBlocks { world.dropItemNaturally(position, item); } } - if (playSound) { - world.playBlockSound(position, state.settings().sounds().breakSound()); - } - if (sendParticles) { + if (sendLevelEvent) { FastNMS.INSTANCE.method$LevelAccessor$levelEvent(world.serverWorld(), WorldEvents.BLOCK_BREAK_EFFECT, LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), state.customBlockState().registryId()); } FastNMS.INSTANCE.method$Level$removeBlock(world.serverWorld(), LocationUtils.toBlockPos(location.getBlockX(), location.getBlockY(), location.getBlockZ()), isMoving); return true; } + /** + * Removes a block from the world if it's custom + * + * @param block block to remove + * @param player player who breaks the block + * @param dropLoot whether to drop block loots + * @param isMoving is moving + * @param playSound whether to play break sounds + * @param sendParticles whether to send break particles + * @return success or not + */ + @Deprecated(forRemoval = true) + public static boolean remove(@NotNull Block block, + @Nullable Player player, + boolean isMoving, + boolean dropLoot, + boolean playSound, + boolean sendParticles) { + return remove(block, player, dropLoot, isMoving, playSound || sendParticles); + } + /** * Checks if a block is custom * diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/AbstractCanSurviveBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/AbstractCanSurviveBlockBehavior.java index 2ab895fe7..851371fa6 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/AbstractCanSurviveBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/AbstractCanSurviveBlockBehavior.java @@ -7,7 +7,6 @@ import net.momirealms.craftengine.bukkit.util.LocationUtils; import net.momirealms.craftengine.bukkit.world.BukkitWorld; import net.momirealms.craftengine.core.block.CustomBlock; import net.momirealms.craftengine.core.block.ImmutableBlockState; -import net.momirealms.craftengine.core.world.BlockPos; import net.momirealms.craftengine.core.world.Vec3d; import net.momirealms.craftengine.core.world.WorldEvents; import net.momirealms.craftengine.core.world.WorldPosition; @@ -69,13 +68,8 @@ public abstract class AbstractCanSurviveBlockBehavior extends BukkitBlockBehavio FastNMS.INSTANCE.method$ScheduledTickAccess$scheduleBlockTick(level, blockPos, thisBlock, this.delay); return state; } - if (!canSurvive(thisBlock, new Object[] {state, level, blockPos}, () -> true)) { - BlockPos pos = LocationUtils.fromBlockPos(blockPos); - ImmutableBlockState customState = optionalCustomState.get(); - net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); - WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos)); - world.playBlockSound(position, customState.settings().sounds().breakSound()); - FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId()); + if (!FastNMS.INSTANCE.method$BlockStateBase$canSurvive(state, level, blockPos)) { + FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, optionalCustomState.get().customBlockState().registryId()); return MBlocks.AIR$defaultState; } return state; diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoubleHighBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoubleHighBlockBehavior.java index 14305b479..7845bddd2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoubleHighBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/DoubleHighBlockBehavior.java @@ -50,10 +50,6 @@ public class DoubleHighBlockBehavior extends BukkitBlockBehavior { if (anotherHalfCustomState != null && !anotherHalfCustomState.isEmpty()) return blockState; // 破坏 - BlockPos pos = LocationUtils.fromBlockPos(blockPos); - net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); - WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos)); - world.playBlockSound(position, customState.settings().sounds().breakSound()); FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId()); return MBlocks.AIR$defaultState; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PressurePlateBlockBehavior.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PressurePlateBlockBehavior.java index da6eb9d78..16f852fd2 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PressurePlateBlockBehavior.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/block/behavior/PressurePlateBlockBehavior.java @@ -66,10 +66,6 @@ public class PressurePlateBlockBehavior extends BukkitBlockBehavior { return MBlocks.AIR$defaultState; } ImmutableBlockState customState = optionalCustomState.get(); - BlockPos pos = LocationUtils.fromBlockPos(blockPos); - net.momirealms.craftengine.core.world.World world = new BukkitWorld(FastNMS.INSTANCE.method$Level$getCraftWorld(level)); - WorldPosition position = new WorldPosition(world, Vec3d.atCenterOf(pos)); - world.playBlockSound(position, customState.settings().sounds().breakSound()); FastNMS.INSTANCE.method$LevelAccessor$levelEvent(level, WorldEvents.BLOCK_BREAK_EFFECT, blockPos, customState.customBlockState().registryId()); return MBlocks.AIR$defaultState; } diff --git a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java index f0e46f014..9a1c5bafa 100644 --- a/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java +++ b/bukkit/src/main/java/net/momirealms/craftengine/bukkit/plugin/network/PacketConsumers.java @@ -514,6 +514,29 @@ public class PacketConsumers { int state = buf.readInt(); boolean global = buf.readBoolean(); int newState = user.clientModEnabled() ? remapMOD(state) : remap(state); + Object blockState = BlockStateUtils.idToBlockState(newState); + Object block = BlockStateUtils.getBlockOwner(blockState); + if (BukkitBlockManager.instance().isBlockSoundRemoved(block) && !FastNMS.INSTANCE.method$BlockStateBase$isAir(blockState)) { + Object soundType = FastNMS.INSTANCE.method$BlockBehaviour$BlockStateBase$getSoundType(blockState); + Object breakSound = FastNMS.INSTANCE.field$SoundType$breakSound(soundType); + Key soundId = Key.of(FastNMS.INSTANCE.field$SoundEvent$location(breakSound).toString()); + Key mappedSoundId = BukkitBlockManager.instance().replaceSoundIfExist(soundId); + if (mappedSoundId != null) { + Object mappedBreakSound = FastNMS.INSTANCE.constructor$SoundEvent(KeyUtils.toResourceLocation(mappedSoundId), Optional.empty()); + Object mappedBreakSoundHolder = FastNMS.INSTANCE.method$Holder$direct(mappedBreakSound); + Object packet = FastNMS.INSTANCE.constructor$ClientboundSoundPacket( + mappedBreakSoundHolder, + CoreReflections.instance$SoundSource$BLOCKS, + blockPos.x() + 0.5, + blockPos.y() + 0.5, + blockPos.z() + 0.5, + (FastNMS.INSTANCE.field$SoundType$volume(soundType) + 1.0F) / 2.0F, + FastNMS.INSTANCE.field$SoundType$pitch(soundType) * 0.8F, + RandomUtils.generateRandomLong() + ); + user.sendPacket(packet, true); + } + } if (newState == state) { return; } diff --git a/core/src/main/java/net/momirealms/craftengine/core/util/RandomUtils.java b/core/src/main/java/net/momirealms/craftengine/core/util/RandomUtils.java index b659d4c28..7904d1776 100644 --- a/core/src/main/java/net/momirealms/craftengine/core/util/RandomUtils.java +++ b/core/src/main/java/net/momirealms/craftengine/core/util/RandomUtils.java @@ -22,6 +22,10 @@ public final class RandomUtils { return ThreadLocalRandom.current().nextBoolean(); } + public static long generateRandomLong() { + return ThreadLocalRandom.current().nextLong(); + } + public static double triangle(double mode, double deviation) { return mode + deviation * (generateRandomDouble(0,1) - generateRandomDouble(0,1)); } diff --git a/gradle.properties b/gradle.properties index c40afd9f7..873f9bbbc 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.89 +nms_helper_version=1.0.90 evalex_version=3.5.0 reactive_streams_version=1.0.4 amazon_awssdk_version=2.33.1