diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SurfaceRulesContextMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SurfaceRulesContextMixin.java index c2be9c3d..71e7dfd5 100644 --- a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SurfaceRulesContextMixin.java +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SurfaceRulesContextMixin.java @@ -3,6 +3,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.Holder; import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.SurfaceRules; import org.embeddedt.modernfix.world.gen.PositionalBiomeGetter; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -12,23 +13,23 @@ import java.util.function.Function; import java.util.function.Supplier; -@Mixin(targets = {"net/minecraft/world/level/levelgen/SurfaceRules$Context"}, priority = 100) +@Mixin(value = SurfaceRules.Context.class, priority = 100) public class SurfaceRulesContextMixin { - @Shadow private long lastUpdateY; + @Shadow long lastUpdateY; - @Shadow private int blockY; + @Shadow public int blockY; - @Shadow private int waterHeight; + @Shadow public int waterHeight; - @Shadow private int stoneDepthBelow; + @Shadow public int stoneDepthBelow; - @Shadow private int stoneDepthAbove; + @Shadow public int stoneDepthAbove; - @Shadow private Supplier> biome; + @Shadow public Supplier> biome; @Shadow @Final private Function> biomeGetter; - @Shadow @Final private BlockPos.MutableBlockPos pos; + @Shadow @Final BlockPos.MutableBlockPos pos; /** * @author embeddedt diff --git a/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SurfaceRulesMixin.java b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SurfaceRulesMixin.java new file mode 100644 index 00000000..e7f80df1 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/common/mixin/perf/worldgen_allocation/SurfaceRulesMixin.java @@ -0,0 +1,113 @@ +package org.embeddedt.modernfix.common.mixin.perf.worldgen_allocation; + +import net.minecraft.resources.ResourceKey; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.PositionalRandomFactory; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.minecraft.world.level.levelgen.VerticalAnchor; +import net.minecraft.world.level.levelgen.placement.CaveSurface; +import org.embeddedt.modernfix.world.gen.SurfaceConditionRecords; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Overwrite; +import org.spongepowered.asm.mixin.Shadow; + +import java.util.function.Predicate; + + +public class SurfaceRulesMixin { + @Mixin(value = SurfaceRules.BiomeConditionSource.class, priority = 100) + public static final class BiomeConditionSource { + @Final @Shadow Predicate> biomeNameTest; + /** + * @author VoidsongDragonfly + * @reason Replacing Vanilla's use of {@link SurfaceRules.LazyYCondition LazyYCondition} that causes performance detriments due to unused caching behavior. + * This is an exact reimplementation of the surface rule, without the caching; check code and effect are identical. + */ + @Overwrite + public SurfaceRules.Condition apply(final SurfaceRules.Context pContext) { + // Return the condition; this record is kept outside the class at embeddedt's wishes due to mixin compat concerns + return new SurfaceConditionRecords.PerformantBiomeCondition(pContext, biomeNameTest); + } + } + + @Mixin(value = SurfaceRules.StoneDepthCheck.class, priority = 100) + public static final class StoneDepthCheck { + @Final @Shadow int offset; + @Final @Shadow boolean addSurfaceDepth; + @Final @Shadow int secondaryDepthRange; + @Final @Shadow private CaveSurface surfaceType; + + /** + * @author VoidsongDragonfly + * @reason Replacing Vanilla's use of {@link SurfaceRules.LazyYCondition LazyYCondition} that causes performance detriments due to unused caching behavior. + * This is an exact reimplementation of the surface rule, without the caching; check code and effect are identical. + */ + @Overwrite + public SurfaceRules.Condition apply(final SurfaceRules.Context pContext) { + // Copied Vanilla variables + final boolean flag = this.surfaceType == CaveSurface.CEILING; + // Return the condition; this record is kept outside the class at embeddedt's wishes due to mixin compat concerns + return new SurfaceConditionRecords.PerformantStoneDepthCondition(pContext, offset, addSurfaceDepth, secondaryDepthRange, flag); + } + } + + @Mixin(value = SurfaceRules.VerticalGradientConditionSource.class, priority = 100) + public static final class VerticalGradientConditionSource { + @Final @Shadow private ResourceLocation randomName; + @Final @Shadow private VerticalAnchor trueAtAndBelow; + @Final @Shadow private VerticalAnchor falseAtAndAbove; + + /** + * @author VoidsongDragonfly + * @reason Replacing Vanilla's use of {@link SurfaceRules.LazyYCondition LazyYCondition} that causes performance detriments due to unused caching behavior. + * This is an exact reimplementation of the surface rule, without the caching; check code and effect are identical. + */ + @Overwrite + public SurfaceRules.Condition apply(final SurfaceRules.Context pContext) { + // Copied Vanilla variables + final int i = trueAtAndBelow.resolveY(pContext.context); + final int j = falseAtAndAbove.resolveY(pContext.context); + final PositionalRandomFactory positionalRandomFactory = pContext.randomState.getOrCreateRandomFactory(randomName); + // Return the condition; this record is kept outside the class at embeddedt's wishes due to mixin compat concerns + return new SurfaceConditionRecords.PerformantVerticalGradientCondition(pContext, i, j, positionalRandomFactory); + } + } + + @Mixin(value = SurfaceRules.WaterConditionSource.class, priority = 100) + public static final class WaterConditionSource { + @Final @Shadow int offset; + @Final @Shadow int surfaceDepthMultiplier; + @Final @Shadow boolean addStoneDepth; + + /** + * @author VoidsongDragonfly + * @reason Replacing Vanilla's use of {@link SurfaceRules.LazyYCondition LazyYCondition} that causes performance detriments due to unused caching behavior. + * This is an exact reimplementation of the surface rule, without the caching; check code and effect are identical. + */ + @Overwrite + public SurfaceRules.Condition apply(final SurfaceRules.Context pContext) { + // Return the condition; this record is kept outside the class at embeddedt's wishes due to mixin compat concerns + return new SurfaceConditionRecords.PerformantWaterCondition(pContext, offset, surfaceDepthMultiplier, addStoneDepth); + } + + } + + @Mixin(value = SurfaceRules.YConditionSource.class, priority = 100) + public static final class YConditionSource { + @Final @Shadow VerticalAnchor anchor; + @Final @Shadow int surfaceDepthMultiplier; + @Final @Shadow boolean addStoneDepth; + /** + * @author VoidsongDragonfly + * @reason Replacing Vanilla's use of {@link SurfaceRules.LazyYCondition LazyYCondition} that causes performance detriments due to unused caching behavior. + * This is an exact reimplementation of the surface rule, without the caching; check code and effect are identical. + */ + @Overwrite + public SurfaceRules.Condition apply(final SurfaceRules.Context pContext) { + // Return the condition; this record is kept outside the class at embeddedt's wishes due to mixin compat concerns + return new SurfaceConditionRecords.PerformantYCondition(pContext, anchor, surfaceDepthMultiplier, addStoneDepth); + } + } +} diff --git a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java index c120dcd7..4b737a25 100644 --- a/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java +++ b/common/src/main/java/org/embeddedt/modernfix/core/config/ModernFixEarlyConfig.java @@ -165,7 +165,7 @@ public DefaultSettingMapBuilder put(String key, Boolean value) { .put("mixin.feature.stalled_chunk_load_detection", false) .put("mixin.perf.blast_search_trees.force", false) .put("mixin.bugfix.restore_old_dragon_movement", false) - .put("mixin.perf.worldgen_allocation", false) // experimental + .put("mixin.perf.worldgen_allocation", true) .put("mixin.feature.cause_lag_by_disabling_threads", false) .put("mixin.bugfix.missing_block_entities", false) .put("mixin.feature.blockentity_incorrect_thread", false) diff --git a/common/src/main/java/org/embeddedt/modernfix/world/gen/SurfaceConditionRecords.java b/common/src/main/java/org/embeddedt/modernfix/world/gen/SurfaceConditionRecords.java new file mode 100644 index 00000000..af8a9fa3 --- /dev/null +++ b/common/src/main/java/org/embeddedt/modernfix/world/gen/SurfaceConditionRecords.java @@ -0,0 +1,68 @@ +package org.embeddedt.modernfix.world.gen; + +import net.minecraft.resources.ResourceKey; +import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; +import net.minecraft.world.level.biome.Biome; +import net.minecraft.world.level.levelgen.PositionalRandomFactory; +import net.minecraft.world.level.levelgen.SurfaceRules; +import net.minecraft.world.level.levelgen.VerticalAnchor; + +import java.util.function.Predicate; + +public class SurfaceConditionRecords { + public record PerformantBiomeCondition(SurfaceRules.Context pContext, Predicate> biomeNameTest) implements SurfaceRules.Condition { + @Override + public boolean test() { + return pContext.biome.get().is(biomeNameTest); + } + } + + public record PerformantStoneDepthCondition(SurfaceRules.Context pContext, int offset, boolean addSurfaceDepth, int secondaryDepthRange, boolean flag) implements SurfaceRules.Condition { + @Override + public boolean test() { + int i = flag ? pContext.stoneDepthBelow : pContext.stoneDepthAbove; + int j = addSurfaceDepth ? pContext.surfaceDepth : 0; + int k = secondaryDepthRange == 0 + ? 0 + : (int) Mth.map(pContext.getSurfaceSecondary(), -1.0, 1.0, 0.0, secondaryDepthRange); + return i <= 1 + offset + j + k; + } + } + + public record PerformantVerticalGradientCondition(SurfaceRules.Context pContext, int i, int j, PositionalRandomFactory positionalRandomFactory) implements SurfaceRules.Condition { + @Override + public boolean test() { + int k = pContext.blockY; + if (k <= i) { + return true; + } else if (k >= j) { + return false; + } else { + double d0 = Mth.map(k, i, j, 1.0, 0.0); + RandomSource randomsource = positionalRandomFactory.at(pContext.blockX, k, pContext.blockZ); + return (double)randomsource.nextFloat() < d0; + } + } + } + + public record PerformantWaterCondition(SurfaceRules.Context pContext, int offset, int surfaceDepthMultiplier, boolean addStoneDepth) implements SurfaceRules.Condition { + @Override + public boolean test() { + return pContext.waterHeight == Integer.MIN_VALUE + || pContext.blockY + (addStoneDepth ? pContext.stoneDepthAbove : 0) + >= pContext.waterHeight + + offset + + pContext.surfaceDepth * surfaceDepthMultiplier; + } + } + + public record PerformantYCondition(SurfaceRules.Context pContext, VerticalAnchor anchor, int surfaceDepthMultiplier, boolean addStoneDepth) implements SurfaceRules.Condition { + @Override + public boolean test() { + return pContext.blockY + (addStoneDepth ? pContext.stoneDepthAbove : 0) + >= anchor.resolveY(pContext.context) + + pContext.surfaceDepth * surfaceDepthMultiplier; + } + } +} diff --git a/common/src/main/resources/modernfix.accesswidener b/common/src/main/resources/modernfix.accesswidener index 57322acc..61255b2b 100644 --- a/common/src/main/resources/modernfix.accesswidener +++ b/common/src/main/resources/modernfix.accesswidener @@ -11,8 +11,30 @@ accessible field net/minecraft/world/level/Level blockEntityTickers Ljava/util/L accessible class net/minecraft/client/renderer/RenderType$CompositeRenderType accessible method net/minecraft/nbt/CompoundTag (Ljava/util/Map;)V +# Non-context access necessary +accessible class net/minecraft/world/level/levelgen/SurfaceRules$Condition +accessible class net/minecraft/world/level/levelgen/SurfaceRules$LazyYCondition +accessible class net/minecraft/world/level/levelgen/SurfaceRules$StoneDepthCheck +accessible class net/minecraft/world/level/levelgen/SurfaceRules$WaterConditionSource +accessible class net/minecraft/world/level/levelgen/SurfaceRules$VerticalGradientConditionSource +accessible class net/minecraft/world/level/levelgen/SurfaceRules$YConditionSource +accessible class net/minecraft/world/level/levelgen/SurfaceRules$BiomeConditionSource accessible class net/minecraft/world/level/levelgen/SurfaceRules$SequenceRule accessible class net/minecraft/world/level/levelgen/SurfaceRules$SurfaceRule +# Access to allow working with Context +accessible class net/minecraft/world/level/levelgen/SurfaceRules$Context +accessible field net/minecraft/world/level/levelgen/SurfaceRules$Context context Lnet/minecraft/world/level/levelgen/WorldGenerationContext; +accessible field net/minecraft/world/level/levelgen/SurfaceRules$Context biome Ljava/util/function/Supplier; +accessible field net/minecraft/world/level/levelgen/SurfaceRules$Context blockX I +accessible field net/minecraft/world/level/levelgen/SurfaceRules$Context blockY I +accessible field net/minecraft/world/level/levelgen/SurfaceRules$Context blockZ I +accessible field net/minecraft/world/level/levelgen/SurfaceRules$Context stoneDepthBelow I +accessible field net/minecraft/world/level/levelgen/SurfaceRules$Context randomState Lnet/minecraft/world/level/levelgen/RandomState; +accessible field net/minecraft/world/level/levelgen/SurfaceRules$Context waterHeight I +accessible field net/minecraft/world/level/levelgen/SurfaceRules$Context stoneDepthAbove I +accessible field net/minecraft/world/level/levelgen/SurfaceRules$Context surfaceDepth I +accessible method net/minecraft/world/level/levelgen/SurfaceRules$Context getSurfaceSecondary ()D +# Density function access accessible class net/minecraft/world/level/levelgen/DensityFunctions$Marker accessible class net/minecraft/world/level/levelgen/DensityFunctions$Marker$Type accessible method net/minecraft/world/level/levelgen/DensityFunctions$Marker (Lnet/minecraft/world/level/levelgen/DensityFunctions$Marker$Type;Lnet/minecraft/world/level/levelgen/DensityFunction;)V @@ -69,4 +91,4 @@ accessible class net/minecraft/world/item/crafting/Ingredient$Value accessible field net/minecraft/world/item/crafting/Ingredient$TagValue tag Lnet/minecraft/tags/TagKey; accessible field net/minecraft/world/item/crafting/Ingredient$ItemValue item Lnet/minecraft/world/item/ItemStack; accessible class net/minecraft/world/item/crafting/Ingredient$ItemValue -accessible class net/minecraft/client/searchtree/SearchRegistry$TreeEntry \ No newline at end of file +accessible class net/minecraft/client/searchtree/SearchRegistry$TreeEntry