From d72df395224a721a97082e1746fd44e208d68141 Mon Sep 17 00:00:00 2001 From: OreCruncher Date: Sat, 17 Feb 2024 08:32:49 -0800 Subject: [PATCH] Backport changes (#88) * Changes to improve compatibility with Bungee servers (#85) * Change handling of server connect processing * Connect/disconnect based on localplayer instance * Keyhole sound pruning for miscconfigured sound origins --------- Co-authored-by: OreCruncher * Address concurrent access to randomizer * Update docs --------- Co-authored-by: OreCruncher --- CHANGELOG.md | 11 ++++ gradle.properties | 2 +- .../config/libraries/impl/TagLibrary.java | 13 +--- .../dsurround/eventing/ClientState.java | 31 +++++++++ .../dsurround/lib/MinecraftServerType.java | 4 +- .../dsurround/lib/random/Randomizer.java | 66 ++++++++++++++++--- .../lib/resources/ClientTagLoader.java | 35 +++++++--- .../events/MixinClientPacketListener.java | 23 ------- .../mixins/events/MixinMinecraftClient.java | 10 --- .../processing/AreaBlockEffects.java | 15 ++--- .../dsurround/processing/Handlers.java | 2 +- .../runtime/audio/SourceContext.java | 6 +- .../dsurround/sound/BackgroundSoundLoop.java | 6 +- .../dsurround/sound/SoundInstanceHandler.java | 7 +- .../tags/blocks/effects/straw_step.json | 3 +- .../assets/dsurround/lang/en_us.json | 2 +- src/main/resources/dsurround.mixins.json | 1 - 17 files changed, 152 insertions(+), 85 deletions(-) delete mode 100644 src/main/java/org/orecruncher/dsurround/mixins/events/MixinClientPacketListener.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 95b371df..cacb9124 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +> ### DynamicSurroundings-Fabric-1.20.1-0.3.3 +**Requirements** +* JAVA 17+ (I am using Adoptium https://adoptium.net/) +* Fabric Loader >=0.14.22 +* Fabric API >=0.91.0+1.20.1 +* 100% client side; no server side deployment needed + +**Fixes** +* Better support for BungeeCord server operations, specifically server transfer +* Fix concurrent access exception on randomizer instances + > ### DynamicSurroundings-Fabric-1.20.1-0.3.2 **Requirements** * JAVA 17+ (I am using Adoptium https://adoptium.net/) diff --git a/gradle.properties b/gradle.properties index 540ecd70..18b1a093 100644 --- a/gradle.properties +++ b/gradle.properties @@ -11,7 +11,7 @@ loader_version=0.14.22 # Mod Properties mod_id=dsurround -mod_version=0.3.2 +mod_version=0.3.3 maven_group=org.orecruncher archives_base_name=DynamicSurroundings-Fabric diff --git a/src/main/java/org/orecruncher/dsurround/config/libraries/impl/TagLibrary.java b/src/main/java/org/orecruncher/dsurround/config/libraries/impl/TagLibrary.java index 4014d6d7..0572c926 100644 --- a/src/main/java/org/orecruncher/dsurround/config/libraries/impl/TagLibrary.java +++ b/src/main/java/org/orecruncher/dsurround/config/libraries/impl/TagLibrary.java @@ -40,9 +40,8 @@ public class TagLibrary implements ITagLibrary { private final IModLog logger; private final ISystemClock systemClock; - private final Map, Collection> tagCache; - private ClientTagLoader tagLoader; + private final ClientTagLoader tagLoader; private boolean isConnected; @@ -50,6 +49,7 @@ public TagLibrary(IModLog logger, ISystemClock systemClock) { this.logger = logger; this.systemClock = systemClock; this.tagCache = new Reference2ObjectOpenHashMap<>(); + this.tagLoader = new ClientTagLoader(ResourceUtilities.createForCurrentState(), this.logger, this.systemClock); // Need to clear the tag caches on disconnect. It's possible that // cached biome information will change with the next connection. @@ -144,11 +144,7 @@ public Stream dump() { @Override public void reload(ResourceUtilities resourceUtilities, IReloadEvent.Scope scope) { - if (resourceUtilities != null) - this.tagLoader = new ClientTagLoader(resourceUtilities, this.logger, this.systemClock); - - if (scope == IReloadEvent.Scope.RESOURCES) - return; + this.tagLoader.setResourceUtilities(resourceUtilities); this.logger.info("[TagLibrary] Cache has %d elements", this.tagCache.size()); @@ -198,9 +194,6 @@ private void onDisconnect(Minecraft client) { } private void initializeTagCache() { - if (this.tagLoader == null) - return; - // Bootstrap the tag cache. We do this by zipping through our tags // and forcing the cache to initialize. var stopwatch = this.systemClock.getStopwatch(); diff --git a/src/main/java/org/orecruncher/dsurround/eventing/ClientState.java b/src/main/java/org/orecruncher/dsurround/eventing/ClientState.java index f1e3cad6..9f2a1083 100644 --- a/src/main/java/org/orecruncher/dsurround/eventing/ClientState.java +++ b/src/main/java/org/orecruncher/dsurround/eventing/ClientState.java @@ -2,7 +2,9 @@ import net.minecraft.client.Minecraft; import net.minecraft.core.RegistryAccess; +import org.orecruncher.dsurround.lib.Library; import org.orecruncher.dsurround.lib.events.EventingFactory; +import org.orecruncher.dsurround.lib.events.HandlerPriority; import org.orecruncher.dsurround.lib.events.IPhasedEvent; /** @@ -76,6 +78,35 @@ public final class ClientState { private ClientState() { } + + static { + // Connection detection is the first thing that processes, period. + TICK_START.register(ClientState::connectionDetector, HandlerPriority.VERY_HIGH); + } + + private static boolean isConnected = false; + private static void connectionDetector(Minecraft client) { + // Basically, the logic will toggle isConnected based on whether a player instance + // is present in the Minecraft client instance. Since this is a 100% client side, + // the presence of the player instance can be used as a signal as to when the + // client successfully connects to a server. If the player instance goes away, such + // as a disconnect or a BungeeCord server transfer, the disconnect event will be fired + // so dependent logic can clean up. + if (isConnected) { + if (client.player == null) { + isConnected = false; + Library.LOGGER.info("Player instance no longer present"); + ON_DISCONNECT.raise().onDisconnect(client); + } + } else { + if (client.player != null) { + isConnected = true; + Library.LOGGER.info("Player instance is now present"); + ON_CONNECT.raise().onConnect(client); + } + } + } + @FunctionalInterface public interface IClientStarted { void onStart(Minecraft client); diff --git a/src/main/java/org/orecruncher/dsurround/lib/MinecraftServerType.java b/src/main/java/org/orecruncher/dsurround/lib/MinecraftServerType.java index acc3eb04..391a52ac 100644 --- a/src/main/java/org/orecruncher/dsurround/lib/MinecraftServerType.java +++ b/src/main/java/org/orecruncher/dsurround/lib/MinecraftServerType.java @@ -5,7 +5,7 @@ public enum MinecraftServerType { PAPER(false), FABRIC(true), FORGE(true), - OTHER_MODDED(true); + OTHER(false); private final boolean isModded; @@ -27,6 +27,6 @@ public static MinecraftServerType fromBrand(String serverBrand) { return FORGE; if ("fabric".equals(brand)) return FABRIC; - return OTHER_MODDED; + return OTHER; } } diff --git a/src/main/java/org/orecruncher/dsurround/lib/random/Randomizer.java b/src/main/java/org/orecruncher/dsurround/lib/random/Randomizer.java index 693f4f3a..1804c824 100644 --- a/src/main/java/org/orecruncher/dsurround/lib/random/Randomizer.java +++ b/src/main/java/org/orecruncher/dsurround/lib/random/Randomizer.java @@ -1,5 +1,8 @@ package org.orecruncher.dsurround.lib.random; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.levelgen.PositionalRandomFactory; +import org.jetbrains.annotations.NotNull; import org.orecruncher.dsurround.lib.Library; import java.util.function.Supplier; @@ -11,26 +14,73 @@ * the number of randoms generated per tick, I sweat these details. */ @SuppressWarnings("unused") -public class Randomizer { +public final class Randomizer implements IRandomizer { private static final Supplier DEFAULT_RANDOMIZER = Randomizer::getRandomizer; - private static final ThreadLocal SHARED = ThreadLocal.withInitial(DEFAULT_RANDOMIZER); - + private static final ThreadLocal THREAD_LOCAL = ThreadLocal.withInitial(DEFAULT_RANDOMIZER); /** - * Instantiates a new instance of the default randomizer. + * Reusable instance that wraps a ThreadLocal. Guards against multiple threads trying to utilize the same + * concrete randomizer. */ - public static IRandomizer create() { - return DEFAULT_RANDOMIZER.get(); - } + private static final IRandomizer SHARED = new Randomizer(); /** * Returns a shared instance of the default randomizer. */ public static IRandomizer current() { - return SHARED.get(); + return SHARED; } private Randomizer() { + } + + @Override + public @NotNull RandomSource fork() { + return THREAD_LOCAL.get().fork(); + } + + @Override + public @NotNull PositionalRandomFactory forkPositional() { + return THREAD_LOCAL.get().forkPositional(); + } + + @Override + public void setSeed(long l) { + THREAD_LOCAL.get().setSeed(l); + } + + @Override + public int nextInt() { + return THREAD_LOCAL.get().nextInt(); + } + + @Override + public int nextInt(int i) { + return THREAD_LOCAL.get().nextInt(i); + } + + @Override + public long nextLong() { + return THREAD_LOCAL.get().nextLong(); + } + + @Override + public boolean nextBoolean() { + return THREAD_LOCAL.get().nextBoolean(); + } + + @Override + public float nextFloat() { + return THREAD_LOCAL.get().nextFloat(); + } + + @Override + public double nextDouble() { + return THREAD_LOCAL.get().nextDouble(); + } + @Override + public double nextGaussian() { + return THREAD_LOCAL.get().nextGaussian(); } private static IRandomizer getRandomizer() { diff --git a/src/main/java/org/orecruncher/dsurround/lib/resources/ClientTagLoader.java b/src/main/java/org/orecruncher/dsurround/lib/resources/ClientTagLoader.java index 11e4a0f9..8f81b2cd 100644 --- a/src/main/java/org/orecruncher/dsurround/lib/resources/ClientTagLoader.java +++ b/src/main/java/org/orecruncher/dsurround/lib/resources/ClientTagLoader.java @@ -4,7 +4,6 @@ import com.google.common.collect.ImmutableSet; import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap; import net.minecraft.core.Holder; -import net.minecraft.core.Registry; import net.minecraft.resources.ResourceLocation; import net.minecraft.tags.TagEntry; import net.minecraft.tags.TagKey; @@ -24,14 +23,15 @@ @SuppressWarnings("unused") public class ClientTagLoader { - private final ResourceUtilities resourceUtilities; private final IModLog logger; private final ISystemClock systemClock; private final Map, TagData> tagCache = new Reference2ObjectOpenHashMap<>(256); private MinecraftServerType serverType; + @NotNull + private ResourceUtilities resourceUtilities; - public ClientTagLoader(ResourceUtilities resourceUtilities, IModLog logger, ISystemClock systemClock) { + public ClientTagLoader(@NotNull ResourceUtilities resourceUtilities, IModLog logger, ISystemClock systemClock) { this.resourceUtilities = resourceUtilities; this.logger = logger; this.systemClock = systemClock; @@ -47,11 +47,23 @@ public Collection getCompleteIds(TagKey tagKey) { } public void clear() { + this.logger.debug(RESOURCE_LOADING, "Clearing client tag loader"); this.tagCache.clear(); } + public void setResourceUtilities(ResourceUtilities resourceUtilities) { + if (this.resourceUtilities != resourceUtilities) { + this.resourceUtilities = resourceUtilities; + this.clear(); + } + } + public void setServerType(MinecraftServerType serverType) { - this.serverType = serverType; + // If the server type is changing, clear the cache + if (this.serverType != serverType) { + this.clear(); + this.serverType = serverType; + } } private TagData getTagData(TagKey tagKey, Set> visited) { @@ -85,8 +97,7 @@ private TagData loadTagData(TagKey tagKey, Set> visited) { // If we can take a shortcut by looking up tag membership in the registries, do so. It's // faster than scanning resources directly. - var registry = RegistryUtils.getRegistry(tagKey.registry()).orElseThrow(); - var holderSet = this.shortcutLookup(tagKey, registry); + var holderSet = this.shortcutLookup(tagKey); if (holderSet.isPresent()) { var data = holderSet.get(); this.logger.debug(RESOURCE_LOADING, "%s - Shortcut lookup", tagKey); @@ -113,6 +124,7 @@ private TagData loadTagData(TagKey tagKey, Set> visited) { public @NotNull ResourceLocation element(@NotNull ResourceLocation id) { return id; } + @Nullable @Override public Collection tag(@NotNull ResourceLocation id) { @@ -144,7 +156,7 @@ public Collection tag(@NotNull ResourceLocation id) { return new TagData<>(ImmutableSet.copyOf(completeIds)); } - private Optional>> shortcutLookup(TagKey tagKey, Registry registry) { + private Optional>> shortcutLookup(TagKey tagKey) { var namespace = tagKey.location().getNamespace(); // If its one of our tags, we always do the long lookup. They aren't really tags. if (namespace.equals(Library.MOD_ID)) @@ -152,7 +164,12 @@ private Optional>> shortcutLookup(TagKey tagKey, Regis // If it is a modded server, or the namespace is minecraft, tag information should be // present in the local registries. if (this.serverType.isModded() || "minecraft".equals(namespace)) { - var holderSet = registry.getTag(tagKey); + // If for some reason the registry cannot be found, do a slow scan. I have seen this with + // BungeeCord when a player transitions between servers. + var registry = RegistryUtils.getRegistry(tagKey.registry()); + if (registry.isEmpty()) + return Optional.empty(); + var holderSet = registry.get().getTag(tagKey); if (holderSet.isPresent()) return Optional.of(holderSet.get()); return Optional.of(ImmutableList.of()); @@ -170,7 +187,7 @@ public static TagData empty() { @SuppressWarnings("unchecked") public static TagData cast(TagData tagData) { - return (TagData)tagData; + return (TagData) tagData; } } } \ No newline at end of file diff --git a/src/main/java/org/orecruncher/dsurround/mixins/events/MixinClientPacketListener.java b/src/main/java/org/orecruncher/dsurround/mixins/events/MixinClientPacketListener.java deleted file mode 100644 index 72bf16ea..00000000 --- a/src/main/java/org/orecruncher/dsurround/mixins/events/MixinClientPacketListener.java +++ /dev/null @@ -1,23 +0,0 @@ -package org.orecruncher.dsurround.mixins.events; - -import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.network.protocol.game.ClientboundLoginPacket; -import org.orecruncher.dsurround.eventing.ClientState; -import org.orecruncher.dsurround.lib.GameUtils; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; - -@Mixin(ClientPacketListener.class) -public class MixinClientPacketListener { - - /** - * The player is set in the Minecraft instance from this routine. Once set the mod is considered connected - * to the server. - */ - @Inject(method = "handleLogin(Lnet/minecraft/network/protocol/game/ClientboundLoginPacket;)V", at = @At("RETURN")) - public void dsurround_handleJoin(ClientboundLoginPacket clientboundLoginPacket, CallbackInfo ci) { - ClientState.ON_CONNECT.raise().onConnect(GameUtils.getMC()); - } -} diff --git a/src/main/java/org/orecruncher/dsurround/mixins/events/MixinMinecraftClient.java b/src/main/java/org/orecruncher/dsurround/mixins/events/MixinMinecraftClient.java index 14202c69..61439924 100644 --- a/src/main/java/org/orecruncher/dsurround/mixins/events/MixinMinecraftClient.java +++ b/src/main/java/org/orecruncher/dsurround/mixins/events/MixinMinecraftClient.java @@ -3,7 +3,6 @@ import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.player.LocalPlayer; import net.minecraft.world.entity.player.Abilities; import org.orecruncher.dsurround.eventing.ClientState; @@ -40,15 +39,6 @@ private void dsurround_starting(CallbackInfo ci) { ClientState.STARTED.raise().onStart((Minecraft) (Object) this); } - /** - * When Minecraft disconnects from a server disconnect() gets called to clean up state. - */ - @Inject(method = "clearLevel(Lnet/minecraft/client/gui/screens/Screen;)V", at = @At("RETURN")) - private void dsurround_leave(Screen screen, CallbackInfo ci) { - var self = (Minecraft) (Object) this; - ClientState.ON_DISCONNECT.raise().onDisconnect(self); - } - /** * Hooks getting player abilities when checking whether to play situational music or the standard * creative Minecraft music when the player is in creative mode and in a dimension other than the Nether. diff --git a/src/main/java/org/orecruncher/dsurround/processing/AreaBlockEffects.java b/src/main/java/org/orecruncher/dsurround/processing/AreaBlockEffects.java index 43ad1b09..0fd1f0ca 100644 --- a/src/main/java/org/orecruncher/dsurround/processing/AreaBlockEffects.java +++ b/src/main/java/org/orecruncher/dsurround/processing/AreaBlockEffects.java @@ -44,13 +44,9 @@ public AreaBlockEffects(IBlockLibrary blockLibrary, IAudioPlayer audioPlayer, Co @Override public void process(final Player player) { this.blockUpdateCount = 0; - if (!this.isConnected) - return; - // TODO: Reports that this reduces some crashes. Not sure how since the connected - // would prevent this logic from executing because it sets the isConnected - // flag. - if (player == null) + // Possible that a client connected to a server, but is being transferred (BungeeCord) + if (!this.isConnected || !GameUtils.isInGame()) return; if (this.effectSystems != null) @@ -77,13 +73,13 @@ public void onConnect() { @Override public void onDisconnect() { this.isConnected = false; - this.locus = null; this.effectSystems = null; } private void clear(ResourceUtilities resourceUtilities, IReloadEvent.Scope scope) { - if (this.effectSystems != null) + // Possible that a client connected to a server, but is being transferred (BungeeCord) + if (this.effectSystems != null && GameUtils.isInGame()) this.effectSystems.resetFullScan(); } @@ -91,7 +87,8 @@ private void blockUpdates(Collection blockPositions) { // Need to pump the updates through to the effect system. The cuboid scanner // will handle the details for filtering and applying updates via blockScan(). this.blockUpdateCount = blockPositions.size(); - if (this.effectSystems != null) + // Possible that a client connected to a server, but is being transferred (BungeeCord) + if (this.effectSystems != null && GameUtils.isInGame()) this.effectSystems.onBlockUpdates(blockPositions); } diff --git a/src/main/java/org/orecruncher/dsurround/processing/Handlers.java b/src/main/java/org/orecruncher/dsurround/processing/Handlers.java index 40c8e007..c63cadb1 100644 --- a/src/main/java/org/orecruncher/dsurround/processing/Handlers.java +++ b/src/main/java/org/orecruncher/dsurround/processing/Handlers.java @@ -82,7 +82,7 @@ private void init() { private void onConnect(Minecraft client) { try { this.tasking.execute(() -> { - this.logger.info("Client connecting..."); + this.logger.info("Handlers connecting..."); if (this.isConnected) { this.logger.warn("Attempt to connect when already connected; disconnecting first"); this.onDisconnect(client); diff --git a/src/main/java/org/orecruncher/dsurround/runtime/audio/SourceContext.java b/src/main/java/org/orecruncher/dsurround/runtime/audio/SourceContext.java index 05baf0af..6ed234ad 100644 --- a/src/main/java/org/orecruncher/dsurround/runtime/audio/SourceContext.java +++ b/src/main/java/org/orecruncher/dsurround/runtime/audio/SourceContext.java @@ -6,7 +6,6 @@ import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; import org.lwjgl.openal.EXTEfx; -import org.orecruncher.dsurround.lib.random.IRandomizer; import org.orecruncher.dsurround.lib.random.Randomizer; import org.orecruncher.dsurround.runtime.audio.effects.Effects; import org.orecruncher.dsurround.runtime.audio.effects.LowPassData; @@ -16,9 +15,6 @@ public final class SourceContext implements Callable { - // Randomizer used to distribute updates across an interval - private static final IRandomizer RANDOM = Randomizer.create(); - // Frequency of sound effect updates in thread schedule ticks. Works out to be 3 times a second. private static final int UPDATE_FEQUENCY_TICKS = 7; @@ -156,7 +152,7 @@ public Void call() { public void exec() { this.captureState(); this.updateImpl(); - this.updateCount = RANDOM.nextInt(UPDATE_FEQUENCY_TICKS); + this.updateCount = Randomizer.current().nextInt(UPDATE_FEQUENCY_TICKS); this.tick(); } diff --git a/src/main/java/org/orecruncher/dsurround/sound/BackgroundSoundLoop.java b/src/main/java/org/orecruncher/dsurround/sound/BackgroundSoundLoop.java index 596a04f8..16bde852 100644 --- a/src/main/java/org/orecruncher/dsurround/sound/BackgroundSoundLoop.java +++ b/src/main/java/org/orecruncher/dsurround/sound/BackgroundSoundLoop.java @@ -6,8 +6,8 @@ import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; -import net.minecraft.util.RandomSource; import org.jetbrains.annotations.NotNull; +import org.orecruncher.dsurround.lib.random.Randomizer; public class BackgroundSoundLoop extends AbstractTickableSoundInstance { @@ -19,7 +19,7 @@ public class BackgroundSoundLoop extends AbstractTickableSoundInstance { private boolean isFading; public BackgroundSoundLoop(SoundEvent soundEvent) { - super(soundEvent, SoundSource.AMBIENT, RandomSource.create()); + super(soundEvent, SoundSource.AMBIENT, Randomizer.current()); this.scale = INITIAL_SCALE; this.target = 1F; this.isFading = false; @@ -30,7 +30,7 @@ public BackgroundSoundLoop(SoundEvent soundEvent) { } public BackgroundSoundLoop(SoundEvent soundEvent, BlockPos pos) { - super(soundEvent, SoundSource.AMBIENT, RandomSource.create()); + super(soundEvent, SoundSource.AMBIENT, Randomizer.current()); this.scale = INITIAL_SCALE; this.target = 1F; this.isFading = false; diff --git a/src/main/java/org/orecruncher/dsurround/sound/SoundInstanceHandler.java b/src/main/java/org/orecruncher/dsurround/sound/SoundInstanceHandler.java index b3caca84..b20cd150 100644 --- a/src/main/java/org/orecruncher/dsurround/sound/SoundInstanceHandler.java +++ b/src/main/java/org/orecruncher/dsurround/sound/SoundInstanceHandler.java @@ -110,6 +110,11 @@ public static boolean inRange(final Vec3 listener, final SoundInstance sound, fi if (sound instanceof ElytraOnPlayerSoundInstance) return true; + // If for some reason the sound is at origin let it through. Some mods submit sound instances attached to a + // location, but do not initialize the location until it starts ticking. + if (sound.getX() == 0 && sound.getY() == 0 && sound.getZ() == 0) + return true; + // Make sure a sound is assigned so that the volume check can work sound.resolve(GameUtils.getSoundManager()); @@ -117,7 +122,7 @@ public static boolean inRange(final Vec3 listener, final SoundInstance sound, fi if (sound.getVolume() > 1F) return true; - // Get the max distance of the sound range. Pad is added because a player may move into hearing + // Get the max sound range. Pad is added because a player may move into hearing // range before the sound terminates. int distSq = sound.getSound().getAttenuationDistance() + pad; distSq *= distSq; diff --git a/src/main/resources/assets/dsurround/dsconfigs/tags/blocks/effects/straw_step.json b/src/main/resources/assets/dsurround/dsconfigs/tags/blocks/effects/straw_step.json index 5431c793..631eee58 100644 --- a/src/main/resources/assets/dsurround/dsconfigs/tags/blocks/effects/straw_step.json +++ b/src/main/resources/assets/dsurround/dsconfigs/tags/blocks/effects/straw_step.json @@ -2,6 +2,7 @@ "replace": false, "values": [ "minecraft:sugar_cane", - "minecraft:dead_bush" + "minecraft:dead_bush", + "minecraft:big_dripleaf_stem" ] } \ No newline at end of file diff --git a/src/main/resources/assets/dsurround/lang/en_us.json b/src/main/resources/assets/dsurround/lang/en_us.json index c3acdbd8..bd071d77 100644 --- a/src/main/resources/assets/dsurround/lang/en_us.json +++ b/src/main/resources/assets/dsurround/lang/en_us.json @@ -80,7 +80,7 @@ "dsurround.config.soundSystem.cullInterval": "Sound Culling Interval", "dsurround.config.soundSystem.cullInterval.tooltip": "Ticks between culled sound events (0 to disable culling)", "dsurround.config.soundSystem.enableSoundPruning": "Sound Pruning", - "dsurround.config.soundSystem.enableSoundPruning.tooltip": "Enables/disables cancellation of sound that a player will not hear. Does not apply to global, repeatable, or WEATHER sounds.", + "dsurround.config.soundSystem.enableSoundPruning.tooltip": "Enables/disables cancellation of sound that a player will not hear. Does not apply to global, non-attenuated, or WEATHER sounds.", "dsurround.config.soundOptions": "Sound Options", "dsurround.config.soundOptions.tooltip": "Options for defining how Dynamic Surroundings generate sound effects", "dsurround.config.soundOptions.ambientVolumeScaling": "Ambient sound scaling factor", diff --git a/src/main/resources/dsurround.mixins.json b/src/main/resources/dsurround.mixins.json index 7bd2ab76..159f0cbd 100644 --- a/src/main/resources/dsurround.mixins.json +++ b/src/main/resources/dsurround.mixins.json @@ -33,7 +33,6 @@ "core.MixinRaycastContextAccessor", "core.MixinSoundOptionsScreen", "core.MixinWorld", - "events.MixinClientPacketListener", "events.MixinMinecraftClient" ], "server": [],