AnOpenSauceDev / FastRandom

An optimized rewrite of Minecraft's RNG system, for Fabric!
Apache License 2.0
48 stars 3 forks source link

BetterEnd & BetterNether incompatibilities #34

Closed Senjosei closed 6 months ago

Senjosei commented 8 months ago

I was making a modpack when i encountered this.

So if i have BetterX installed and use BetterX world gen A. If tried to goto the nether, i just get stuck on the portal waiting for it to find a location to teleport me B. If i then disable FastRandom and use the portal again, everything works and chunks generate C. Then if i Re-enable FastRandom, I can go into the nether, but the chunks that werent generated before wont load, and if i goto an ungenerated chunk, it thread locks

Same-ish effect when going to the end but in A. it just thread locks. Heres the thread dump courtesy of ModernFix https://pastebin.com/6nVs0cri

Snip

"Worker-Main-21" daemon prio=4 Id=198 RUNNABLE
    at org.betterx.bclib.api.v2.generator.map.hex.HexBiomeChunk.<init>(HexBiomeChunk.java:49)
    at org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap.getChunk(HexBiomeMap.java:85)
    at org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap.getChunkBiome(HexBiomeMap.java:150)
    at org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap.getRawBiome(HexBiomeMap.java:125)
    at org.betterx.bclib.api.v2.generator.map.hex.HexBiomeMap.getBiome(HexBiomeMap.java:57)
    at org.betterx.bclib.api.v2.generator.BCLibEndBiomeSource.method_38109(BCLibEndBiomeSource.java:291)
    at net.minecraft.class_3195.method_41613(class_3195.java:147)
    at net.minecraft.class_3195.method_47931(class_3195.java:199)
    at net.minecraft.class_3195$$Lambda$39594/0x0000000804cd3d78.test(Unknown Source)
    at java.base@17.0.1/java.util.Optional.filter(Optional.java:218)
    at net.minecraft.class_3195.method_47932(class_3195.java:199)
    at net.minecraft.class_3195.method_41614(class_3195.java:125)
    at net.minecraft.class_2794.method_41044(class_2794.java:513)
    at net.minecraft.class_2794.method_41041(class_2794.java:466)
    at net.minecraft.class_2794$$Lambda$39580/0x0000000804cc9af0.accept(Unknown Source)
    at java.base@17.0.1/java.lang.Iterable.forEach(Iterable.java:75)
    at net.minecraft.class_2794.method_16129(class_2794.java:448)
    at net.minecraft.class_2806.method_39464(class_2806.java:54)
    at net.minecraft.class_2806$$Lambda$1770/0x000000080151b530.doWork(Unknown Source)
    at net.minecraft.class_2806.method_12154(class_2806.java:252)
    at net.minecraft.class_3898.method_17225(class_3898.java:684)
    at net.minecraft.class_3898$$Lambda$35748/0x0000000804785a90.apply(Unknown Source)
    at com.mojang.datafixers.util.Either$Left.map(Either.java:38)
    at net.minecraft.class_3898.method_17224(class_3898.java:673)
    at net.minecraft.class_3898$$Lambda$35601/0x0000000804756220.apply(Unknown Source)
    at java.base@17.0.1/java.util.concurrent.CompletableFuture$UniCompose.tryFire(CompletableFuture.java:1150)
    at java.base@17.0.1/java.util.concurrent.CompletableFuture$Completion.run(CompletableFuture.java:482)
    at net.minecraft.class_3900.method_17634(class_3900.java:62)
    at net.minecraft.class_3900$$Lambda$35747/0x0000000804785870.run(Unknown Source)
    at net.minecraft.class_3846.method_16907(class_3846.java:91)
    at net.minecraft.class_3846.method_16900(class_3846.java:146)
    at net.minecraft.class_3846.run(class_3846.java:102)
    at java.base@17.0.1/java.util.concurrent.ForkJoinTask$RunnableExecuteAction.exec(ForkJoinTask.java:1395)
    at java.base@17.0.1/java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:373)
    at java.base@17.0.1/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(ForkJoinPool.java:1182)
    at java.base@17.0.1/java.util.concurrent.ForkJoinPool.scan(ForkJoinPool.java:1655)
    at java.base@17.0.1/java.util.concurrent.ForkJoinPool.runWorker(ForkJoinPool.java:1622)
    at java.base@17.0.1/java.util.concurrent.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:165)
AnOpenSauceDev commented 8 months ago

When something like this happens, please manually trigger a crash-report by holding F3 + C for 10 seconds.

here's what i got:

java.lang.ExceptionInInitializerError
    at net.minecraft.world.biome.source.FixedBiomeSource.<clinit>(FixedBiomeSource.java:17)
    at net.minecraft.world.biome.source.BiomeSources.registerAndGetDefault(BiomeSources.java:8)
    at net.minecraft.registry.Registries.method_47485(Registries.java:232)
    at net.minecraft.registry.Registries.method_47482(Registries.java:247)
    at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:721)
    at net.minecraft.registry.Registries.init(Registries.java:245)
    at net.minecraft.registry.Registries.bootstrap(Registries.java:239)
    at net.minecraft.Bootstrap.initialize(Bootstrap.java:69)
    at net.minecraft.client.main.Main.main(Main.java:170)
    at net.fabricmc.loader.impl.game.minecraft.MinecraftGameProvider.launch(MinecraftGameProvider.java:470)
    at net.fabricmc.loader.impl.launch.knot.Knot.launch(Knot.java:74)
    at net.fabricmc.loader.impl.launch.knot.KnotClient.main(KnotClient.java:23)
    at net.fabricmc.devlaunchinjector.Main.main(Main.java:86)
Caused by: java.lang.ClassCastException: class jdk.random.L64X128MixRandom cannot be cast to class net.minecraft.util.math.random.Random (jdk.random.L64X128MixRandom is in module jdk.random of loader 'app'; net.minecraft.util.math.random.Random is in unnamed module of loader net.fabricmc.loader.impl.launch.knot.KnotClassLoader @d2cc05a)
    at net.minecraft.util.math.random.ChunkRandom.handler$zza000$faster-random$test(ChunkRandom.java:525)
    at net.minecraft.util.math.random.ChunkRandom.<init>(ChunkRandom.java:19)
    at net.minecraft.world.biome.Biome.<clinit>(Biome.java:56)
    ... 13 more
Steveplays28 commented 8 months ago

Their random generator gets created here: https://github.com/quiqueck/BCLib/blob/3b23118a28bbea0363e25378aab38cbff45f9683/src/main/java/org/betterx/bclib/api/v2/generator/map/hex/HexBiomeMap.java#L85

Might be related to the way that is set up?

AnOpenSauceDev commented 8 months ago

I did find a fix after messing around with ChunkRandom, although I really don't like it.

One fix is to assign a vanilla CheckedRandom in ChunkRandom, but this will hurt worldgen performance.

package com.github.anopensaucedev.fasterrandom.mixin;

import net.minecraft.util.math.random.CheckedRandom;
import net.minecraft.util.math.random.ChunkRandom;
import net.minecraft.util.math.random.Random;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

@Mixin(ChunkRandom.class)
public class ChunkRandomMixin {

    @Mutable
    @Shadow
    @Final
    private Random baseRandom;

    @Inject(method = "<init>(Lnet/minecraft/util/math/random/Random;)V",at = @At("RETURN"))
    private void fasterrandom$fixBetterX(Random baseRandom, CallbackInfo ci){
        this.baseRandom = new CheckedRandom(0);
    }

}

I have absolutely no idea what fasterrandom$test is, as no method is ever named that in the source code, refmap or decompiled source. There is also nothing in these fields that would even have test as a member.

AnOpenSauceDev commented 8 months ago

I might push this fix as-is to resolve it for now, but ideally this should be looked into further.

Steveplays28 commented 8 months ago

Could add a compat mixin that changes their random number generator back to a normal one. Maybe a feature to disable the random generator replacement if it's instantiated from certain classes would be handy in the future for this.

Just a shout, maybe the split() method doesn't work as intended and causes the ClassCastExceptoon? https://github.com/AnOpenSauceDev/FastRandom/blob/master/src%2Fmain%2Fjava%2Fcom%2Fgithub%2Fanopensaucedev%2Ffasterrandom%2FRandomGeneratorRandom.java#L28-L31

AnOpenSauceDev commented 8 months ago

Just a shout, maybe the split() method doesn't work as intended

Actually, i think that might be it.

variants of split like split(int x, int y, int z) aren't implemented, but i think pasting them in won't work.

Also, the only test that makes sense (as in, calls split()) is all the ones in MaterialRules, which never manages to get called when entering the nether.

AnOpenSauceDev commented 6 months ago

Fixed with #41/#42 (merged)