diff --git a/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/concurrency/ForgeRegistryTagManagerMixin.java b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/concurrency/ForgeRegistryTagManagerMixin.java new file mode 100644 index 00000000..1367ff67 --- /dev/null +++ b/forge/src/main/java/org/embeddedt/modernfix/forge/mixin/bugfix/concurrency/ForgeRegistryTagManagerMixin.java @@ -0,0 +1,31 @@ +package org.embeddedt.modernfix.forge.mixin.bugfix.concurrency; + +import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import net.minecraft.tags.TagKey; +import net.minecraftforge.registries.tags.ITag; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.Map; + +@Mixin(targets = {"net/minecraftforge/registries/ForgeRegistryTagManager"}) +public class ForgeRegistryTagManagerMixin { + @Shadow private volatile Map, ITag> tags; + + /** + * @author embeddedt (issue found by Uncandango) + * @reason vanilla does not use the correct double-checked locking paradigm, which leads to race conditions + */ + @WrapMethod(method = "getTag", remap = false) + private ITag getTagSafe(@NotNull TagKey name, Operation> original) { + ITag tag = this.tags.get(name); + if (tag == null) { + synchronized (this) { + tag = original.call(name); + } + } + return tag; + } +}