Skip to content

Commit

Permalink
fix: missed threading fixes in stronghold and nether fortress
Browse files Browse the repository at this point in the history
  • Loading branch information
ishland committed Dec 11, 2024
1 parent 8ea3880 commit 42bcdba
Show file tree
Hide file tree
Showing 8 changed files with 97 additions and 43 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.ishland.c2me.fixes.worldgen.threading_issues.common;

public interface XPieceDataExtension {

ThreadLocal<Integer> c2me$getGeneratedCountThreadLocal();

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.ishland.c2me.fixes.worldgen.threading_issues.mixin.threading;

import com.ishland.c2me.fixes.worldgen.threading_issues.common.INetherFortressGeneratorPieceData;
import com.ishland.c2me.fixes.worldgen.threading_issues.common.XPieceDataExtension;
import net.minecraft.structure.NetherFortressGenerator;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -10,14 +10,14 @@
@Mixin(NetherFortressGenerator.Piece.class)
public class MixinNetherFortressGeneratorPiece {

@Redirect(method = "checkRemainingPieces", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/NetherFortressGenerator$PieceData;generatedCount:I", opcode = Opcodes.GETFIELD))
@Redirect(method = {"checkRemainingPieces", "pickPiece"}, at = @At(value = "FIELD", target = "Lnet/minecraft/structure/NetherFortressGenerator$PieceData;generatedCount:I", opcode = Opcodes.GETFIELD))
private int redirectGetPieceDataGeneratedCount(NetherFortressGenerator.PieceData pieceData) {
return ((INetherFortressGeneratorPieceData) pieceData).getGeneratedCountAtomic().get();
return ((XPieceDataExtension) pieceData).c2me$getGeneratedCountThreadLocal().get();
}

@Redirect(method = "pickPiece", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/NetherFortressGenerator$PieceData;generatedCount:I", opcode = Opcodes.PUTFIELD))
private void redirectIncrementPieceDataGeneratedCount(NetherFortressGenerator.PieceData pieceData, int value) { // TODO Check when updating minecraft version
((INetherFortressGeneratorPieceData) pieceData).getGeneratedCountAtomic().incrementAndGet();
((XPieceDataExtension) pieceData).c2me$getGeneratedCountThreadLocal().set(value);
}

}
Original file line number Diff line number Diff line change
@@ -1,35 +1,39 @@
package com.ishland.c2me.fixes.worldgen.threading_issues.mixin.threading;

import com.ishland.c2me.fixes.worldgen.threading_issues.common.INetherFortressGeneratorPieceData;
import com.ishland.c2me.fixes.worldgen.threading_issues.common.XPieceDataExtension;
import net.minecraft.structure.NetherFortressGenerator;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Dynamic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

import java.util.concurrent.atomic.AtomicInteger;

@Mixin(NetherFortressGenerator.PieceData.class)
public class MixinNetherFortressGeneratorPieceData implements INetherFortressGeneratorPieceData {
public class MixinNetherFortressGeneratorPieceData implements XPieceDataExtension {

private final AtomicInteger generatedCountAtomic = new AtomicInteger();
@Unique
private final ThreadLocal<Integer> generatedCountThreadLocal = ThreadLocal.withInitial(() -> 0);

@Dynamic
@Redirect(method = "*", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/NetherFortressGenerator$PieceData;generatedCount:I", opcode = Opcodes.GETFIELD))
private int redirectGetGeneratedCount(NetherFortressGenerator.PieceData pieceData) {
return this.generatedCountAtomic.get();
return this.generatedCountThreadLocal.get();
}

@SuppressWarnings("MixinAnnotationTarget")
@Dynamic
@Redirect(method = "*", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/NetherFortressGenerator$PieceData;generatedCount:I", opcode = Opcodes.PUTFIELD), require = 0, expect = 0)
private void redirectSetGeneratedCount(NetherFortressGenerator.PieceData pieceData, int value) {
this.generatedCountAtomic.set(value);
if (value == 0) {
generatedCountThreadLocal.remove();
} else {
this.generatedCountThreadLocal.set(value);
}
}

@Override
public AtomicInteger getGeneratedCountAtomic() {
return this.generatedCountAtomic;
public ThreadLocal<Integer> c2me$getGeneratedCountThreadLocal() {
return this.generatedCountThreadLocal;
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.ishland.c2me.fixes.worldgen.threading_issues.mixin.threading;

import com.ishland.c2me.fixes.worldgen.threading_issues.asm.MakeVolatile;
import com.ishland.c2me.fixes.worldgen.threading_issues.common.INetherFortressGeneratorPieceData;
import com.ishland.c2me.fixes.worldgen.threading_issues.common.XPieceDataExtension;
import net.minecraft.structure.NetherFortressGenerator;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
Expand All @@ -23,9 +23,13 @@ public class MixinNetherFortressGeneratorStart {
@MakeVolatile
@Shadow public NetherFortressGenerator.PieceData lastPiece;

@Redirect(method = "<init>(Lnet/minecraft/util/math/random/Random;II)V", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/NetherFortressGenerator$PieceData;generatedCount:I", opcode = Opcodes.PUTFIELD))
@Redirect(method = "<init>(Lnet/minecraft/util/math/random/Random;II)V", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/NetherFortressGenerator$PieceData;generatedCount:I", opcode = Opcodes.PUTFIELD), require = 2)
private void redirectSetPieceDataGeneratedCount(NetherFortressGenerator.PieceData pieceData, int value) {
((INetherFortressGeneratorPieceData) pieceData).getGeneratedCountAtomic().set(value);
if (value == 0) {
((XPieceDataExtension) pieceData).c2me$getGeneratedCountThreadLocal().remove();
} else {
((XPieceDataExtension) pieceData).c2me$getGeneratedCountThreadLocal().set(value);
}
}

@Inject(method = "<init>*", at = @At("RETURN"))
Expand Down
Original file line number Diff line number Diff line change
@@ -1,42 +1,49 @@
package com.ishland.c2me.fixes.worldgen.threading_issues.mixin.threading;

import com.ishland.c2me.fixes.worldgen.threading_issues.common.IStrongholdGenerator;
import com.ishland.c2me.fixes.worldgen.threading_issues.common.XPieceDataExtension;
import net.minecraft.structure.StrongholdGenerator;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

import java.util.Arrays;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;

@Mixin(StrongholdGenerator.class)
public class MixinStrongholdGenerator implements IStrongholdGenerator {

@Shadow @Final private static StrongholdGenerator.PieceData[] ALL_PIECES;
@Shadow private static List<StrongholdGenerator.PieceData> possiblePieces;
@Unique
private static final ThreadLocal<List<StrongholdGenerator.PieceData>> possiblePiecesThreadLocal = ThreadLocal.withInitial(() -> new ArrayList<>());
@Unique
private static final ThreadLocal<Integer> totalWeightThreadLocal = ThreadLocal.withInitial(() -> 0);
@Unique
private static final ThreadLocal<Class<? extends StrongholdGenerator.Piece>> activePieceTypeThreadLocal = new ThreadLocal<>();

@Redirect(method = "init", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/StrongholdGenerator;possiblePieces:Ljava/util/List;", opcode = Opcodes.PUTSTATIC))
private static void redirectAssignList(List<StrongholdGenerator.PieceData> value) {
possiblePieces = Collections.synchronizedList(value);
final List<StrongholdGenerator.PieceData> pieceDataList = Arrays.asList(ALL_PIECES);
pieceDataList.forEach(pieceData -> pieceData.generatedCount = 0);
possiblePieces.addAll(pieceDataList);
@Redirect(method = "init", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/StrongholdGenerator;possiblePieces:Ljava/util/List;", opcode = Opcodes.PUTSTATIC), require = 1)
private static void redirectSetPossiblePieces(List<StrongholdGenerator.PieceData> value) {
possiblePiecesThreadLocal.set(value);
}

@Redirect(method = "init", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/StrongholdGenerator$PieceData;generatedCount:I", opcode = Opcodes.PUTFIELD))
private static void redirectSetGeneratedCount(StrongholdGenerator.PieceData pieceData, int value) {
// no-op
@Redirect(method = {"init", "checkRemainingPieces", "pickPiece"}, at = @At(value = "FIELD", target = "Lnet/minecraft/structure/StrongholdGenerator;possiblePieces:Ljava/util/List;", opcode = Opcodes.GETSTATIC), require = 4)
private static List<StrongholdGenerator.PieceData> redirectGetPossiblePieces() {
return possiblePiecesThreadLocal.get();
}

@Redirect(method = {"checkRemainingPieces", "pickPiece"}, at = @At(value = "FIELD", target = "Lnet/minecraft/structure/StrongholdGenerator$PieceData;generatedCount:I", opcode = Opcodes.GETFIELD), require = 2)
private static int redirectGetGeneratedCount(StrongholdGenerator.PieceData instance) {
return ((XPieceDataExtension) instance).c2me$getGeneratedCountThreadLocal().get();
}

@Redirect(method = "init", at = @At(value = "INVOKE", target = "Ljava/util/List;add(Ljava/lang/Object;)Z"))
private static <E> boolean redirectListAdd(List<E> list, E e) {
return false; // no-op
@Redirect(method = {"init", "pickPiece"}, at = @At(value = "FIELD", target = "Lnet/minecraft/structure/StrongholdGenerator$PieceData;generatedCount:I", opcode = Opcodes.PUTFIELD), require = 2)
private static void redirectSetGeneratedCount(StrongholdGenerator.PieceData pieceData, int value) {
if (value == 0) {
((XPieceDataExtension) pieceData).c2me$getGeneratedCountThreadLocal().remove();
} else {
((XPieceDataExtension) pieceData).c2me$getGeneratedCountThreadLocal().set(value);
}
}

@Redirect(method = "checkRemainingPieces", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/StrongholdGenerator;totalWeight:I", opcode = Opcodes.PUTSTATIC))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package com.ishland.c2me.fixes.worldgen.threading_issues.mixin.threading;

import com.ishland.c2me.fixes.worldgen.threading_issues.common.XPieceDataExtension;
import net.minecraft.structure.StrongholdGenerator;
import org.objectweb.asm.Opcodes;
import org.spongepowered.asm.mixin.Dynamic;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;

@Mixin(StrongholdGenerator.PieceData.class)
public class MixinStrongholdGeneratorPieceData implements XPieceDataExtension {

@Unique
private final ThreadLocal<Integer> generatedCountThreadLocal = ThreadLocal.withInitial(() -> 0);

@Dynamic
@Redirect(method = "*", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/StrongholdGenerator$PieceData;generatedCount:I", opcode = Opcodes.GETFIELD), require = 2)
private int redirectGetGeneratedCount(StrongholdGenerator.PieceData pieceData) {
return this.generatedCountThreadLocal.get();
}

@SuppressWarnings("MixinAnnotationTarget")
@Dynamic
@Redirect(method = "*", at = @At(value = "FIELD", target = "Lnet/minecraft/structure/StrongholdGenerator$PieceData;generatedCount:I", opcode = Opcodes.PUTFIELD), require = 0, expect = 0)
private void redirectSetGeneratedCount(StrongholdGenerator.PieceData pieceData, int value) {
if (value == 0) {
generatedCountThreadLocal.remove();
} else {
this.generatedCountThreadLocal.set(value);
}
}

@Override
public ThreadLocal<Integer> c2me$getGeneratedCountThreadLocal() {
return this.generatedCountThreadLocal;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"threading.MixinShiftableStructurePiece",
"threading.MixinStrongholdGenerator",
"threading.MixinStrongholdGeneratorChestCorridor",
"threading.MixinStrongholdGeneratorPieceData",
"threading.MixinStrongholdGeneratorPortalRoom",
"threading.MixinStrongholdGeneratorSpiralStaircase",
"threading.MixinStrongholdGeneratorStart",
Expand Down

0 comments on commit 42bcdba

Please sign in to comment.