From 897d9e59c81a16bb8204ad84f21fb473ba0c0192 Mon Sep 17 00:00:00 2001 From: QiuShui1012 <150409561+QiuShui1012@users.noreply.github.com> Date: Tue, 17 Feb 2026 00:52:55 +0800 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E5=87=8F=E5=B0=91=E5=9B=A0=E5=90=8C?= =?UTF-8?q?=E6=AD=A5=E9=97=AE=E9=A2=98=E4=BA=A7=E7=94=9F=E7=9A=84=E4=B8=BB?= =?UTF-8?q?=E5=8A=A8=E6=B6=88=E9=9F=B3=E5=99=A8=E5=A4=B1=E6=95=88=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 增加了双端发声事件监听器,允许服务端禁用发声 - 将声音相关仅客户端代码改为双端实现 --- .../api/sound/ISoundEventListener.java | 2 +- .../anvilcraft/api/sound/SoundHelper.java | 35 ++++++++----------- .../entity/ActiveSilencerBlockEntity.java | 8 ++--- .../anvilcraft/event/LevelEventListener.java | 1 + .../event/ServerLifecycleEventListener.java | 2 ++ .../anvilcraft/event/SoundEventListener.java | 31 ++++++++++++++++ .../anvilcraft/mixin/SoundEngineMixin.java | 7 +++- 7 files changed, 59 insertions(+), 27 deletions(-) create mode 100644 src/main/java/dev/dubhe/anvilcraft/event/SoundEventListener.java diff --git a/src/main/java/dev/dubhe/anvilcraft/api/sound/ISoundEventListener.java b/src/main/java/dev/dubhe/anvilcraft/api/sound/ISoundEventListener.java index d02a8bbe1d..a99c8d021b 100644 --- a/src/main/java/dev/dubhe/anvilcraft/api/sound/ISoundEventListener.java +++ b/src/main/java/dev/dubhe/anvilcraft/api/sound/ISoundEventListener.java @@ -7,5 +7,5 @@ * 声音事件监听器 */ public interface ISoundEventListener { - boolean shouldPlay(ResourceLocation sound, Vec3 pos); + boolean shouldMute(ResourceLocation sound, Vec3 pos); } diff --git a/src/main/java/dev/dubhe/anvilcraft/api/sound/SoundHelper.java b/src/main/java/dev/dubhe/anvilcraft/api/sound/SoundHelper.java index 191f067534..5eda66e6c2 100644 --- a/src/main/java/dev/dubhe/anvilcraft/api/sound/SoundHelper.java +++ b/src/main/java/dev/dubhe/anvilcraft/api/sound/SoundHelper.java @@ -1,48 +1,41 @@ package dev.dubhe.anvilcraft.api.sound; import lombok.Getter; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; +import javax.annotation.Nullable; @Getter public class SoundHelper { - public static SoundHelper INSTANCE = new SoundHelper(); + public static final SoundHelper INSTANCE = new SoundHelper(); - private final Map> eventListeners = new HashMap<>(); + private final Map, List> eventListeners = new HashMap<>(); - public boolean shouldPlay(ResourceLocation sound, Vec3 pos) { - ClientLevel level = Minecraft.getInstance().level; - if (level == null) return true; - return eventListeners.computeIfAbsent(level, k -> new CopyOnWriteArrayList<>()) + public boolean shouldMute(@Nullable Level level, ResourceLocation sound, Vec3 pos) { + if (level == null) return false; + return this.eventListeners.computeIfAbsent(level.dimension(), k -> new CopyOnWriteArrayList<>()) .stream() - .allMatch(it -> it.shouldPlay(sound, pos)); + .allMatch(it -> it.shouldMute(sound, pos)); } - public void register(ISoundEventListener eventListener) { - ClientLevel level = Minecraft.getInstance().level; - if (level == null) return; - eventListeners.computeIfAbsent(level, k -> new CopyOnWriteArrayList<>()) + public void register(Level level, ISoundEventListener eventListener) { + this.eventListeners.computeIfAbsent(level.dimension(), k -> new CopyOnWriteArrayList<>()) .add(eventListener); } - public void unregister(ISoundEventListener eventListener) { - ClientLevel level = Minecraft.getInstance().level; - if (level == null) { - eventListeners.values().forEach(list -> list.remove(eventListener)); - return; - } - eventListeners.computeIfAbsent(level, k -> new CopyOnWriteArrayList<>()) + public void unregister(Level level, ISoundEventListener eventListener) { + this.eventListeners.computeIfAbsent(level.dimension(), k -> new CopyOnWriteArrayList<>()) .remove(eventListener); } public void clear() { - eventListeners.clear(); + this.eventListeners.clear(); } } diff --git a/src/main/java/dev/dubhe/anvilcraft/block/entity/ActiveSilencerBlockEntity.java b/src/main/java/dev/dubhe/anvilcraft/block/entity/ActiveSilencerBlockEntity.java index 2e8e1f7425..57c118bae8 100644 --- a/src/main/java/dev/dubhe/anvilcraft/block/entity/ActiveSilencerBlockEntity.java +++ b/src/main/java/dev/dubhe/anvilcraft/block/entity/ActiveSilencerBlockEntity.java @@ -93,13 +93,13 @@ public CompoundTag getUpdateTag(HolderLookup.Provider provider) { @Override public void setRemoved() { super.setRemoved(); - DistExecutor.run(Dist.CLIENT, () -> () -> SoundHelper.INSTANCE.unregister(this)); + DistExecutor.run(Dist.CLIENT, () -> () -> SoundHelper.INSTANCE.unregister(this.level, this)); } @Override public void setLevel(Level level) { super.setLevel(level); - DistExecutor.run(Dist.CLIENT, () -> () -> SoundHelper.INSTANCE.register(this)); + DistExecutor.run(Dist.CLIENT, () -> () -> SoundHelper.INSTANCE.register(level, this)); } @Override @@ -128,11 +128,11 @@ public void removeSound(ResourceLocation soundId) { } @Override - public boolean shouldPlay(ResourceLocation sound, Vec3 pos) { + public boolean shouldMute(ResourceLocation sound, Vec3 pos) { if (getBlockState().getValue(ActiveSilencerBlock.POWERED)) return true; boolean inRange = range.contains(pos); boolean inList = mutedSound.contains(sound); - return !inRange || !inList; + return inRange && inList; } public void sync(List sounds) { diff --git a/src/main/java/dev/dubhe/anvilcraft/event/LevelEventListener.java b/src/main/java/dev/dubhe/anvilcraft/event/LevelEventListener.java index 7b59f893a3..b1f9b0f8d5 100644 --- a/src/main/java/dev/dubhe/anvilcraft/event/LevelEventListener.java +++ b/src/main/java/dev/dubhe/anvilcraft/event/LevelEventListener.java @@ -5,6 +5,7 @@ import dev.dubhe.anvilcraft.api.entity.fakeplayer.AnvilCraftDestroyerFakePlayer; import dev.dubhe.anvilcraft.api.entity.fakeplayer.AnvilCraftFakePlayers; import dev.dubhe.anvilcraft.api.entity.fakeplayer.AnvilCraftKillerFakePlayer; +import dev.dubhe.anvilcraft.api.sound.SoundHelper; import dev.dubhe.anvilcraft.api.world.load.LevelLoadManager; import dev.dubhe.anvilcraft.block.entity.DeflectionRingBlockEntity; import net.minecraft.server.level.ServerLevel; diff --git a/src/main/java/dev/dubhe/anvilcraft/event/ServerLifecycleEventListener.java b/src/main/java/dev/dubhe/anvilcraft/event/ServerLifecycleEventListener.java index e30b2ad036..aaff45819c 100644 --- a/src/main/java/dev/dubhe/anvilcraft/event/ServerLifecycleEventListener.java +++ b/src/main/java/dev/dubhe/anvilcraft/event/ServerLifecycleEventListener.java @@ -5,6 +5,7 @@ import dev.dubhe.anvilcraft.api.heat.HeaterManager; import dev.dubhe.anvilcraft.api.heat.collector.HeatCollectorManager; import dev.dubhe.anvilcraft.api.power.PowerGrid; +import dev.dubhe.anvilcraft.api.sound.SoundHelper; import dev.dubhe.anvilcraft.api.world.load.LevelLoadManager; import dev.dubhe.anvilcraft.api.world.load.RandomChuckTickLoadManager; import dev.dubhe.anvilcraft.init.ModHammerInits; @@ -38,6 +39,7 @@ public static void onServerStopped(ServerStoppedEvent event) { PowerGrid.isServerClosing = false; PowerGrid.clear(); RecipeCaches.unload(); + SoundHelper.INSTANCE.clear(); } @SubscribeEvent diff --git a/src/main/java/dev/dubhe/anvilcraft/event/SoundEventListener.java b/src/main/java/dev/dubhe/anvilcraft/event/SoundEventListener.java new file mode 100644 index 0000000000..5217d06d97 --- /dev/null +++ b/src/main/java/dev/dubhe/anvilcraft/event/SoundEventListener.java @@ -0,0 +1,31 @@ +package dev.dubhe.anvilcraft.event; + +import dev.dubhe.anvilcraft.AnvilCraft; +import dev.dubhe.anvilcraft.api.sound.SoundHelper; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.phys.Vec3; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.event.PlayLevelSoundEvent; + +@EventBusSubscriber(modid = AnvilCraft.MOD_ID) +public class SoundEventListener { + @SubscribeEvent + public static void onPlaySoundAtEntity(PlayLevelSoundEvent.AtEntity event) { + Entity entity = event.getEntity(); + event.setCanceled(SoundHelper.INSTANCE.shouldMute( + event.getLevel(), + event.getSound().value().getLocation(), + new Vec3(entity.getX(), entity.getY(), entity.getZ()) + )); + } + + @SubscribeEvent + public static void onPlaySoundAtPosition(PlayLevelSoundEvent.AtPosition event) { + event.setCanceled(SoundHelper.INSTANCE.shouldMute( + event.getLevel(), + event.getSound().value().getLocation(), + event.getPosition() + )); + } +} diff --git a/src/main/java/dev/dubhe/anvilcraft/mixin/SoundEngineMixin.java b/src/main/java/dev/dubhe/anvilcraft/mixin/SoundEngineMixin.java index 26ed8028af..138fb5e527 100644 --- a/src/main/java/dev/dubhe/anvilcraft/mixin/SoundEngineMixin.java +++ b/src/main/java/dev/dubhe/anvilcraft/mixin/SoundEngineMixin.java @@ -1,6 +1,7 @@ package dev.dubhe.anvilcraft.mixin; import dev.dubhe.anvilcraft.api.sound.SoundHelper; +import net.minecraft.client.Minecraft; import net.minecraft.client.resources.sounds.SoundInstance; import net.minecraft.client.sounds.SoundEngine; import net.minecraft.world.phys.Vec3; @@ -13,7 +14,11 @@ abstract class SoundEngineMixin { @Inject(method = "play", at = @At(value = "HEAD"), cancellable = true) private void onSoundPlay(SoundInstance sound, CallbackInfo ci) { - if (!SoundHelper.INSTANCE.shouldPlay(sound.getLocation(), new Vec3(sound.getX(), sound.getY(), sound.getZ()))) { + if (SoundHelper.INSTANCE.shouldMute( + Minecraft.getInstance().level, + sound.getLocation(), + new Vec3(sound.getX(), sound.getY(), sound.getZ()) + )) { ci.cancel(); } } From ee92b8e96c76ff6e30055a6e64b5dd1706811558 Mon Sep 17 00:00:00 2001 From: QiuShui1012 <150409561+QiuShui1012@users.noreply.github.com> Date: Tue, 17 Feb 2026 01:06:50 +0800 Subject: [PATCH 2/2] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20InspectionSuppo?= =?UTF-8?q?rt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修复了 InspectionSupport --- .../dubhe/anvilcraft/client/support/InspectionSupport.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/dev/dubhe/anvilcraft/client/support/InspectionSupport.java b/src/main/java/dev/dubhe/anvilcraft/client/support/InspectionSupport.java index 170d2c5a96..671f1f2d18 100644 --- a/src/main/java/dev/dubhe/anvilcraft/client/support/InspectionSupport.java +++ b/src/main/java/dev/dubhe/anvilcraft/client/support/InspectionSupport.java @@ -18,7 +18,9 @@ import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.core.BlockPos; +import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import net.minecraft.world.phys.shapes.Shapes; @@ -34,8 +36,8 @@ public class InspectionSupport { public static void initializeClient() { INSTANCE.registerActionClient(AnvilCraft.of("silencer"), (p, r, c, d) -> { - Map> map = SoundHelper.INSTANCE.getEventListeners(); - List listeners = map.get(Minecraft.getInstance().level); + Map, List> map = SoundHelper.INSTANCE.getEventListeners(); + List listeners = map.get(Minecraft.getInstance().level.dimension()); MultiBufferSource.BufferSource buf = r.renderBuffers.bufferSource(); VertexConsumer vertex = buf.getBuffer(RenderType.LINES); if (listeners == null || listeners.isEmpty()) return;