diff --git a/gradle.properties b/gradle.properties index 2a656019..3bb92fdd 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,5 +16,5 @@ mod_email=scribble@minecrafttas.com # TASmod properties group=com.minecrafttas artifact=TASmod-1.12.2 -version=Beta2.1 +version=Beta3 release=false diff --git a/src/main/java/com/minecrafttas/mctcommon/events/EventListenerRegistry.java b/src/main/java/com/minecrafttas/mctcommon/events/EventListenerRegistry.java index 1170342e..03d5c1f4 100644 --- a/src/main/java/com/minecrafttas/mctcommon/events/EventListenerRegistry.java +++ b/src/main/java/com/minecrafttas/mctcommon/events/EventListenerRegistry.java @@ -94,7 +94,7 @@ public interface EventBase { */ public static void register(EventBase eventListener) { if (eventListener == null) { - throw new NullPointerException("Tried to register a packethandler with value null"); + throw new NullPointerException("Tried to register an eventListener with value null"); } for (Class type : searchForInterfaces(eventListener.getClass())) { @@ -153,7 +153,7 @@ public static void register(List eventListeners) { */ public static void unregister(EventBase eventListener) { if (eventListener == null) { - throw new NullPointerException("Tried to unregister a packethandler with value null"); + throw new NullPointerException("Tried to unregister an eventListener with value null"); } for (Class type : searchForInterfaces(eventListener.getClass())) { if (EventBase.class.isAssignableFrom(type)) { diff --git a/src/main/java/com/minecrafttas/mctcommon/events/EventServer.java b/src/main/java/com/minecrafttas/mctcommon/events/EventServer.java index ea26c691..6973b2ab 100644 --- a/src/main/java/com/minecrafttas/mctcommon/events/EventServer.java +++ b/src/main/java/com/minecrafttas/mctcommon/events/EventServer.java @@ -13,6 +13,19 @@ */ public interface EventServer { + /** + * Fired, just before the server initialised, for both integrated and dedicated server. + */ + @FunctionalInterface + public static interface EventServerStart extends EventBase { + + /** + * Fired, when the server is initialised, for both integrated and dedicated server. + * @param server The server + */ + public void onServerStart(MinecraftServer server); + } + /** * Fired, when the server is initialised, for both integrated and dedicated server. */ diff --git a/src/main/java/com/minecrafttas/mctcommon/mixin/MixinMinecraftServer.java b/src/main/java/com/minecrafttas/mctcommon/mixin/MixinMinecraftServer.java index 4ea7d14f..b921efc9 100644 --- a/src/main/java/com/minecrafttas/mctcommon/mixin/MixinMinecraftServer.java +++ b/src/main/java/com/minecrafttas/mctcommon/mixin/MixinMinecraftServer.java @@ -9,6 +9,7 @@ import com.minecrafttas.mctcommon.events.EventListenerRegistry; import com.minecrafttas.mctcommon.events.EventServer.EventServerGameLoop; import com.minecrafttas.mctcommon.events.EventServer.EventServerInit; +import com.minecrafttas.mctcommon.events.EventServer.EventServerStart; import com.minecrafttas.mctcommon.events.EventServer.EventServerStop; import com.minecrafttas.mctcommon.events.EventServer.EventServerTick; @@ -17,6 +18,11 @@ @Mixin(MinecraftServer.class) public class MixinMinecraftServer { + @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;init()Z")) + public void inject_initStart(CallbackInfo ci) { + EventListenerRegistry.fireEvent(EventServerStart.class, (MinecraftServer) (Object) this); + } + @Inject(method = "run", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;init()Z", shift = Shift.AFTER)) public void inject_init(CallbackInfo ci) { EventListenerRegistry.fireEvent(EventServerInit.class, (MinecraftServer) (Object) this); diff --git a/src/main/java/com/minecrafttas/tasmod/TASmod.java b/src/main/java/com/minecrafttas/tasmod/TASmod.java index 51700db5..dca39999 100644 --- a/src/main/java/com/minecrafttas/tasmod/TASmod.java +++ b/src/main/java/com/minecrafttas/tasmod/TASmod.java @@ -8,6 +8,7 @@ import com.minecrafttas.mctcommon.CommandRegistry; import com.minecrafttas.mctcommon.events.EventListenerRegistry; import com.minecrafttas.mctcommon.events.EventServer.EventServerInit; +import com.minecrafttas.mctcommon.events.EventServer.EventServerStart; import com.minecrafttas.mctcommon.events.EventServer.EventServerStop; import com.minecrafttas.mctcommon.networking.PacketHandlerRegistry; import com.minecrafttas.mctcommon.networking.Server; @@ -24,6 +25,10 @@ import com.minecrafttas.tasmod.commands.CommandSavestate; import com.minecrafttas.tasmod.commands.CommandTickrate; import com.minecrafttas.tasmod.handlers.PlayUntilHandler; +import com.minecrafttas.tasmod.ktrng.GlobalRandomnessTimer; +import com.minecrafttas.tasmod.ktrng.builtin.MathRandomness; +import com.minecrafttas.tasmod.ktrng.builtin.WorldSeedRandomness; +import com.minecrafttas.tasmod.ktrng.events.KTRNGMonitor; import com.minecrafttas.tasmod.playback.PlaybackControllerServer; import com.minecrafttas.tasmod.playback.metadata.builtin.StartpositionMetadataExtension; import com.minecrafttas.tasmod.registries.TASmodAPIRegistry; @@ -32,6 +37,7 @@ import com.minecrafttas.tasmod.savestates.handlers.SavestateGuiHandlerServer; import com.minecrafttas.tasmod.savestates.handlers.SavestateResourcePackHandler; import com.minecrafttas.tasmod.savestates.storage.builtin.ClientMotionStorage; +import com.minecrafttas.tasmod.savestates.storage.builtin.KTRNGSeedStorage; import com.minecrafttas.tasmod.tickratechanger.TickrateChangerServer; import com.minecrafttas.tasmod.ticksync.TickSyncServer; import com.minecrafttas.tasmod.util.LoggerMarkers; @@ -48,7 +54,7 @@ * * @author Scribble */ -public class TASmod implements ModInitializer, EventServerInit, EventServerStop { +public class TASmod implements ModInitializer, EventServerStart, EventServerInit, EventServerStop { public static final Logger LOGGER = LogManager.getLogger("TASmod"); @@ -85,6 +91,16 @@ public class TASmod implements ModInitializer, EventServerInit, EventServerStop public static ClientMotionStorage motionStorage = new ClientMotionStorage(); + public static GlobalRandomnessTimer globalRandomness; + + public static KTRNGSeedStorage seedStorage = new KTRNGSeedStorage(); + + public static MathRandomness mathRandomness = new MathRandomness(0); + + public static WorldSeedRandomness worldSeedRandomness = new WorldSeedRandomness(0); + + public static KTRNGMonitor debugRand = new KTRNGMonitor(); + @Override public void onInitialize() { @@ -111,6 +127,7 @@ public void onInitialize() { EventListenerRegistry.register(ticksyncServer); EventListenerRegistry.register(tickratechanger); // EventListenerRegistry.register(ktrngHandler); + EventListenerRegistry.register(debugRand); // Register packet handlers LOGGER.info(LoggerMarkers.Networking, "Registering network handlers"); @@ -128,12 +145,18 @@ public void onInitialize() { EventListenerRegistry.register(resourcepackHandler); PacketHandlerRegistry.register(playUntil); EventListenerRegistry.register(playUntil); - EventListenerRegistry.register(TASmodAPIRegistry.SAVESTATE_STORAGE); registerSavestateStorage(); } + @Override + public void onServerStart(MinecraftServer server) { + globalRandomness = new GlobalRandomnessTimer(); + EventListenerRegistry.register(globalRandomness); + mathRandomness = new MathRandomness(0); + } + @Override public void onServerInit(MinecraftServer server) { LOGGER.info("Initializing server"); @@ -196,6 +219,7 @@ public void onServerStop(MinecraftServer mcserver) { private void registerSavestateStorage() { TASmodAPIRegistry.SAVESTATE_STORAGE.register(motionStorage); + TASmodAPIRegistry.SAVESTATE_STORAGE.register(seedStorage); } public static MinecraftServer getServerInstance() { diff --git a/src/main/java/com/minecrafttas/tasmod/events/EventSavestate.java b/src/main/java/com/minecrafttas/tasmod/events/EventSavestate.java index 51ac126b..dda3601f 100644 --- a/src/main/java/com/minecrafttas/tasmod/events/EventSavestate.java +++ b/src/main/java/com/minecrafttas/tasmod/events/EventSavestate.java @@ -27,7 +27,7 @@ interface EventServerSavestate extends EventBase { * Fired when loading a savestate, before the savestate folder is copied */ @FunctionalInterface - interface EventServerLoadstate extends EventBase { + interface EventServerLoadstatePre extends EventBase { /** * Fired when loading a savestate, before the savestate folder is copied @@ -35,7 +35,22 @@ interface EventServerLoadstate extends EventBase { * @param server The server instance * @param paths The {@link SavestatePaths} object */ - public void onServerLoadstate(MinecraftServer server, SavestatePaths paths); + public void onServerLoadstatePre(MinecraftServer server, SavestatePaths paths); + } + + /** + * Fired when loading a savestate, after the savestate folder is copied + */ + @FunctionalInterface + interface EventServerLoadstatePost extends EventBase { + + /** + * Fired when loading a savestate, after the savestate folder is copied + * + * @param server The server instance + * @param paths The {@link SavestatePaths} object + */ + public void onServerLoadstatePost(MinecraftServer server, SavestatePaths paths); } /** @@ -47,7 +62,7 @@ interface EventServerCompleteLoadstate extends EventBase { /** * Fired one tick after a loadstate was carried out */ - public void onServerLoadstateComplete(); + public void onServerLoadstateComplete(MinecraftServer server, SavestatePaths paths); } /** diff --git a/src/main/java/com/minecrafttas/tasmod/gui/InfoHud.java b/src/main/java/com/minecrafttas/tasmod/gui/InfoHud.java index 0269a886..8ad4131f 100644 --- a/src/main/java/com/minecrafttas/tasmod/gui/InfoHud.java +++ b/src/main/java/com/minecrafttas/tasmod/gui/InfoHud.java @@ -18,6 +18,7 @@ import com.minecrafttas.tasmod.TASmod; import com.minecrafttas.tasmod.TASmodClient; import com.minecrafttas.tasmod.events.EventClient.EventDrawHotbar; +import com.minecrafttas.tasmod.ktrng.handlers.KTRNGWorldHandler; import com.minecrafttas.tasmod.playback.PlaybackControllerClient; import com.minecrafttas.tasmod.playback.PlaybackControllerClient.TASstate; import com.minecrafttas.tasmod.playback.filecommands.builtin.DesyncMonitorFileCommandExtension; @@ -296,17 +297,48 @@ public boolean checkInit() { y += 14; -// if (TASmod.ktrngHandler.isLoaded()) { -// title = "ktrng_randomseed"; -// if (configuration.getProperty(title + "_x", "err").equals("err")) -// setDefaults(title, y); -// lists.add(new InfoLabel(title, Integer.parseInt(configuration.getProperty(title + "_x")), Integer.parseInt(configuration.getProperty(title + "_y")), Boolean.parseBoolean(configuration.getProperty(title -// + "_visible")), Boolean.parseBoolean(configuration.getProperty(title + "_rect")), () -> { -// if (Minecraft.getMinecraft().currentScreen == this) -// return "KTRNG"; -// return "RandomSeed: " + TASmod.ktrngHandler.getGlobalSeedClient(); -// })); -// } + title = "ktrng_randomseed"; + if (configuration.getProperty(title + "_x", "err").equals("err")) + setDefaults(title, y); + lists.add(new InfoLabel(title, Integer.parseInt(configuration.getProperty(title + "_x")), Integer.parseInt(configuration.getProperty(title + "_y")), Boolean.parseBoolean(configuration.getProperty(title + + "_visible")), Boolean.parseBoolean(configuration.getProperty(title + "_rect")), () -> { + if (Minecraft.getMinecraft().currentScreen == this) + return "KTRNG"; + return "Global RandomSeed: " + TASmod.globalRandomness.getCurrentSeed(); + })); + +// y += 14; +// title = "ktrng_entitycount"; +// if (configuration.getProperty(title + "_x", "err").equals("err")) +// setDefaults(title, y); +// lists.add(new InfoLabel(title, Integer.parseInt(configuration.getProperty(title + "_x")), Integer.parseInt(configuration.getProperty(title + "_y")), Boolean.parseBoolean(configuration.getProperty(title +// + "_visible")), Boolean.parseBoolean(configuration.getProperty(title + "_rect")), () -> { +// if (Minecraft.getMinecraft().currentScreen == this) +// return "EntityCount"; +// return "EntityCount: " + EntityRandomness.entityCounter; +// })); + + y += 14; + title = "ktrng_worldseed"; + if (configuration.getProperty(title + "_x", "err").equals("err")) + setDefaults(title, y); + lists.add(new InfoLabel(title, Integer.parseInt(configuration.getProperty(title + "_x")), Integer.parseInt(configuration.getProperty(title + "_y")), Boolean.parseBoolean(configuration.getProperty(title + + "_visible")), Boolean.parseBoolean(configuration.getProperty(title + "_rect")), () -> { + if (Minecraft.getMinecraft().currentScreen == this) + return "WorldRNG"; + return "WorldRNG: " + KTRNGWorldHandler.getWorldRandom(); + })); + + y += 14; + title = "ktrng_mathseed"; + if (configuration.getProperty(title + "_x", "err").equals("err")) + setDefaults(title, y); + lists.add(new InfoLabel(title, Integer.parseInt(configuration.getProperty(title + "_x")), Integer.parseInt(configuration.getProperty(title + "_y")), Boolean.parseBoolean(configuration.getProperty(title + + "_visible")), Boolean.parseBoolean(configuration.getProperty(title + "_rect")), () -> { + if (Minecraft.getMinecraft().currentScreen == this) + return "MathRNG"; + return "MathRNG: " + TASmod.mathRandomness.getSeed(); + })); title = "facing"; y += 14; diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/GlobalRandomnessTimer.java b/src/main/java/com/minecrafttas/tasmod/ktrng/GlobalRandomnessTimer.java new file mode 100644 index 00000000..50165528 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/GlobalRandomnessTimer.java @@ -0,0 +1,32 @@ +package com.minecrafttas.tasmod.ktrng; + +import com.minecrafttas.mctcommon.events.EventServer; + +import kaptainwutax.seedutils.rand.JRand; +import net.minecraft.server.MinecraftServer; + +public class GlobalRandomnessTimer implements EventServer.EventServerTick { + + private final JRand globalRandomness; + + private long currentSeed = 0L; + + public GlobalRandomnessTimer() { + globalRandomness = new JRand(0L); + } + + @Override + public void onServerTick(MinecraftServer server) { + globalRandomness.advance(1); + currentSeed = globalRandomness.getSeed(); + } + + public long getCurrentSeed() { + return currentSeed; + } + + public void setSeed(long newSeed) { + globalRandomness.setSeed(newSeed); + currentSeed = newSeed; + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/GlobalRandomnessTimerClient.java b/src/main/java/com/minecrafttas/tasmod/ktrng/GlobalRandomnessTimerClient.java new file mode 100644 index 00000000..85bb41d8 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/GlobalRandomnessTimerClient.java @@ -0,0 +1,39 @@ +package com.minecrafttas.tasmod.ktrng; + +import com.minecrafttas.mctcommon.events.EventClient; + +import kaptainwutax.seedutils.rand.JRand; +import net.minecraft.client.Minecraft; + +public class GlobalRandomnessTimerClient implements EventClient.EventClientTick { + + private final JRand globalRandomness; + private final JRand uuidRandomness; + + private long currentSeed = 0L; + + public GlobalRandomnessTimerClient() { + globalRandomness = new JRand(0L); + uuidRandomness = new JRand(0L); + } + + @Override + public void onClientTick(Minecraft mc) { + currentSeed = globalRandomness.nextLong(); + uuidRandomness.setSeed(currentSeed); + } + + public long getCurrentSeed() { + return currentSeed; + } + + public JRand getUUIDRandom() { + return uuidRandomness; + } + + public void setSeed(long newSeed) { + globalRandomness.setSeed(newSeed); + currentSeed = newSeed; + } + +} diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/KTRNGMonitor.java b/src/main/java/com/minecrafttas/tasmod/ktrng/KTRNGMonitor.java deleted file mode 100644 index 7cf6fa98..00000000 --- a/src/main/java/com/minecrafttas/tasmod/ktrng/KTRNGMonitor.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.minecrafttas.tasmod.ktrng; - -@Deprecated -public class KTRNGMonitor { - -// @CaptureRandomness(name = "jukeboxRecordDropPosition") - public static void monitor(long seed, String value) { -// System.out.println(String.format("Seed: %s, Value: %s", seed, value)); - } -} diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/KillTheRNGHandler.java b/src/main/java/com/minecrafttas/tasmod/ktrng/KillTheRNGHandler.java index d071cd81..501501af 100644 --- a/src/main/java/com/minecrafttas/tasmod/ktrng/KillTheRNGHandler.java +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/KillTheRNGHandler.java @@ -39,8 +39,8 @@ public class KillTheRNGHandler implements EventServerTick, EventPlayerJoinedClie * * @param isLoaded If the KillTheRNG mod is loaded */ + @Deprecated public KillTheRNGHandler(boolean isLoaded) { - this.isLoaded = isLoaded; if (isLoaded) { @@ -54,6 +54,7 @@ public KillTheRNGHandler(boolean isLoaded) { } } + @Deprecated public long advanceGlobalSeedServer() { // if (isLoaded()) { // return KillTheRNG.commonRandom.nextSeed(); @@ -62,6 +63,7 @@ public long advanceGlobalSeedServer() { // } } + @Deprecated public long getGlobalSeedServer() { // if (isLoaded()) { // return KillTheRNG.commonRandom.GlobalServer.getSeed(); @@ -70,6 +72,7 @@ public long getGlobalSeedServer() { // } } + @Deprecated public boolean isLoaded() { return isLoaded; } diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/KillTheRNGRegistry.java b/src/main/java/com/minecrafttas/tasmod/ktrng/KillTheRNGRegistry.java new file mode 100644 index 00000000..89d50774 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/KillTheRNGRegistry.java @@ -0,0 +1,13 @@ +package com.minecrafttas.tasmod.ktrng; + +import java.util.HashMap; + +import com.minecrafttas.mctcommon.registry.AbstractRegistry; + +public class KillTheRNGRegistry extends AbstractRegistry { + + public KillTheRNGRegistry() { + super("KillTheRNG", new HashMap<>()); + } + +} diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/RandomBase.java b/src/main/java/com/minecrafttas/tasmod/ktrng/RandomBase.java new file mode 100644 index 00000000..2c1230ba --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/RandomBase.java @@ -0,0 +1,179 @@ +package com.minecrafttas.tasmod.ktrng; + +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +import com.minecrafttas.mctcommon.registry.Registerable; +import com.minecrafttas.tasmod.TASmod; + +import kaptainwutax.seedutils.lcg.LCG; +import kaptainwutax.seedutils.rand.JRand; + +public abstract class RandomBase extends Random implements Registerable { + + RNGSide side; + private long initialSeed; + private JRand jrand; + + private List eventHandler = new ArrayList<>(); + + public RandomBase() { + super(TASmod.globalRandomness.getCurrentSeed()); + } + + public RandomBase(long seed) { + super(seed); + this.initialSeed = seed; + jrand = new JRand(seed, false); + } + + @Override + public void setSeed(long seedIn) { + super.setSeed(seedIn); + if (jrand != null) + jrand.setSeed(seedIn, false); +// super.setSeed(seedIn ^ 0x5deece66dL); + } + + public long getSeed() { +// long saved = timesCalled; +// long seed = reverse(super.nextLong()) ^ 0x5deece66dL; +// super.setSeed(seed); +// timesCalled = saved; +// return seed ^ 0x5deece66dL; + return jrand.getSeed(); + } + +// public static long reverse(long in) { +// return (((7847617 * ((24667315 * (in >>> 32) + 18218081 * (in & 0xffffffffL) + 67552711) >> 32) - 18218081 * ((-4824621 * (in >>> 32) + 7847617 * (in & 0xffffffffL) + 7847617) >> 32)) - 11) * 246154705703781L) & 0xffffffffffffL; +// } + +// public String getName() { +// return this.name; +// } +// +// public String getDescription() { +// return description; +// } + +// public long getTimesCalled() { +// return timesCalled; +// } + + @Override + public long nextLong() { +// timesCalled++; + long seedstored = getSeed(); + long value = jrand.nextLong(); + fireGetEvent("nextLong()", seedstored, Long.toString(value)); + return value; + } + + @Override + public double nextDouble() { +// timesCalled++; + long seedstored = getSeed(); + double value = jrand.nextDouble(); + fireGetEvent("nextDouble()", seedstored, Double.toString(value)); + return value; + } + + @Override + public boolean nextBoolean() { +// timesCalled++; + long seedstored = getSeed(); + boolean value = jrand.nextBoolean(); + fireGetEvent("nextBoolean()", seedstored, Boolean.toString(value)); + return value; + } + + @Override + public int nextInt() { +// timesCalled++; + long seedstored = getSeed(); + int value = jrand.nextInt(); + fireGetEvent("nextInt()", seedstored, Integer.toString(value)); + return value; + } + + @Override + public int nextInt(int bound) { +// timesCalled++; + long seedstored = getSeed(); + int value = jrand.nextInt(bound); + fireGetEvent(String.format("nextInt(%s)", bound), seedstored, Integer.toString(value)); + return value; + } + + @Override + public float nextFloat() { + return jrand.nextFloat(); + } + + @Override + public double nextGaussian() { + double value = 0; + value = jrand.nextGaussian(); + return value; + } + + public void advance() { + advance(1); + } + + public void advance(long i) { + jrand.advance(i); + } + + public long distance(RandomBase random) { + return RandomBase.distance(this.getSeed(), random.getSeed()); + } + + public long distance(long seed) { + return RandomBase.distance(this.getSeed(), seed); + } + + public static long distance(RandomBase random1, RandomBase random2) { + return RandomBase.distance(random1.getSeed(), random2.getSeed()); + } + + public static long distance(long seed, long seed2) { + return LCG.JAVA.distance(seed, seed2); + } + + @Override + public String toString() { + return Long.toString(getSeed()); + } + + public void fireSetEvent(String eventType, long seed, String value, int stackTraceOffset) { + fireRNGEvent(eventType, seed, value, stackTraceOffset); + } + + public void fireGetEvent(String eventType, long seed, String value) { + fireRNGEvent(eventType, seed, value, 3); + } + + public void fireRNGEvent(String eventType, long seed, String value, int stackTraceOffset) { + + StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); + this.eventHandler.forEach(handler -> { + handler.onRNGEvent(side, eventType, seed, value, stackTraceElements); + }); + } + + public long getInitialSeed() { + return initialSeed; + } + + public enum RNGSide { + Server, + Client + } + + @FunctionalInterface + public static interface RNGEventHandler { + public void onRNGEvent(RNGSide side, String eventType, long seed, String value, StackTraceElement[] stackTraceElements); + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/EntityRandomness.java b/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/EntityRandomness.java new file mode 100644 index 00000000..81eddf81 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/EntityRandomness.java @@ -0,0 +1,24 @@ +package com.minecrafttas.tasmod.ktrng.builtin; + +import com.minecrafttas.tasmod.ktrng.RandomBase; + +public class EntityRandomness extends RandomBase { + + public EntityRandomness() { + super(); + } + + public EntityRandomness(long seed) { + super(seed); + } + + @Override + public void fireRNGEvent(String eventType, long seed, String value, int stackTraceOffset) { +// super.fireEvent(eventType, seed, value, stackTraceOffset); + } + + @Override + public String getExtensionName() { + return "EntityRNG"; + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/MathRandomness.java b/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/MathRandomness.java new file mode 100644 index 00000000..c2d5a878 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/MathRandomness.java @@ -0,0 +1,29 @@ +package com.minecrafttas.tasmod.ktrng.builtin; + +import com.minecrafttas.tasmod.ktrng.RandomBase; + +/** + *

Randomness instance for hooking into {@link Math#random()} + * + * @author Scribble + */ +public class MathRandomness extends RandomBase { + + public MathRandomness() { + super(); + } + + public MathRandomness(long seed) { + super(seed); + } + + @Override + public void fireRNGEvent(String eventType, long seed, String value, int stackTraceOffset) { +// super.fireEvent(eventType, seed, value, 6); + } + + @Override + public String getExtensionName() { + return "MathRNG"; + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/WorldRandomness.java b/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/WorldRandomness.java new file mode 100644 index 00000000..db66efa8 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/WorldRandomness.java @@ -0,0 +1,24 @@ +package com.minecrafttas.tasmod.ktrng.builtin; + +import com.minecrafttas.tasmod.ktrng.RandomBase; + +public class WorldRandomness extends RandomBase { + + public WorldRandomness() { + super(); + } + + public WorldRandomness(long seed) { + super(seed); + } + + @Override + public void fireRNGEvent(String val, long seed, String value, int offset) { + super.fireRNGEvent(val, seed, value, 5); + } + + @Override + public String getExtensionName() { + return "WorldRNG"; + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/WorldSeedRandomness.java b/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/WorldSeedRandomness.java new file mode 100644 index 00000000..be7a6dcc --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/builtin/WorldSeedRandomness.java @@ -0,0 +1,23 @@ +package com.minecrafttas.tasmod.ktrng.builtin; + +import com.minecrafttas.tasmod.ktrng.RandomBase; + +public class WorldSeedRandomness extends RandomBase { + + public WorldSeedRandomness() { + super(); + } + + public WorldSeedRandomness(long seed) { + super(seed); + } + + @Override + public void fireRNGEvent(String eventType, long seed, String value, int stackTraceOffset) { + } + + @Override + public String getExtensionName() { + return "WorldSeedRNG"; + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/events/KTRNGMonitor.java b/src/main/java/com/minecrafttas/tasmod/ktrng/events/KTRNGMonitor.java new file mode 100644 index 00000000..34012f26 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/events/KTRNGMonitor.java @@ -0,0 +1,27 @@ +package com.minecrafttas.tasmod.ktrng.events; + +import com.minecrafttas.mctcommon.events.EventServer; +import com.minecrafttas.tasmod.events.EventPlaybackServer; +import com.minecrafttas.tasmod.ktrng.RandomBase.RNGEventHandler; +import com.minecrafttas.tasmod.ktrng.RandomBase.RNGSide; +import com.minecrafttas.tasmod.playback.PlaybackControllerClient.TASstate; + +import net.minecraft.server.MinecraftServer; + +public class KTRNGMonitor implements EventPlaybackServer.EventControllerStateChange, EventServer.EventServerTick, RNGEventHandler { + + @Override + public void onServerTick(MinecraftServer server) { + + } + + @Override + public void onControllerStateChange(TASstate newstate, TASstate oldstate) { + + } + + @Override + public void onRNGEvent(RNGSide side, String eventType, long seed, String value, StackTraceElement[] stackTraceElements) { + + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/handlers/KTRNGEntityHandler.java b/src/main/java/com/minecrafttas/tasmod/ktrng/handlers/KTRNGEntityHandler.java new file mode 100644 index 00000000..db66af07 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/handlers/KTRNGEntityHandler.java @@ -0,0 +1,39 @@ +package com.minecrafttas.tasmod.ktrng.handlers; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +import com.minecrafttas.tasmod.TASmod; +import com.minecrafttas.tasmod.ktrng.builtin.EntityRandomness; + +import net.minecraft.entity.Entity; +import net.minecraft.world.WorldServer; + +public class KTRNGEntityHandler { + + public static Map getRandomnessList() { + Map out = new HashMap<>(); + WorldServer[] worlds = TASmod.getServerInstance().worlds; + for (WorldServer worldServer : worlds) { + for (Entity entity : worldServer.loadedEntityList) { + UUID entityUUID = entity.getUniqueID(); + EntityRandomness entityRandomness = (EntityRandomness) entity.rand; + out.put(entityUUID, entityRandomness); + } + } + return out; + } + + public static void setRandomnessList(Map randomnessList) { + WorldServer[] worlds = TASmod.getServerInstance().worlds; + for (WorldServer worldServer : worlds) { + for (Entity entity : worldServer.loadedEntityList) { + UUID uuid = entity.getUniqueID(); + EntityRandomness rand = randomnessList.get(uuid); + if (rand != null) + entity.rand = rand; + } + } + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/ktrng/handlers/KTRNGWorldHandler.java b/src/main/java/com/minecrafttas/tasmod/ktrng/handlers/KTRNGWorldHandler.java new file mode 100644 index 00000000..0136aeee --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/ktrng/handlers/KTRNGWorldHandler.java @@ -0,0 +1,65 @@ +package com.minecrafttas.tasmod.ktrng.handlers; + +import java.util.HashMap; +import java.util.Map; + +import com.minecrafttas.tasmod.TASmod; +import com.minecrafttas.tasmod.ktrng.builtin.WorldRandomness; + +import net.minecraft.world.WorldServer; + +public class KTRNGWorldHandler { + + public static Map getWorldRandomnessMap() { + Map out = new HashMap<>(); + WorldServer[] worlds = TASmod.getServerInstance().worlds; + int id = 0; + for (WorldServer worldServer : worlds) { + WorldRandomness worldRandomness = (WorldRandomness) worldServer.rand; + out.put(id, worldRandomness); + id++; + } + return out; + } + + public static Map getWorldLCGMap() { + Map out = new HashMap<>(); + WorldServer[] worlds = TASmod.getServerInstance().worlds; + int id = 0; + for (WorldServer worldServer : worlds) { + int updateLCG = worldServer.updateLCG; + out.put(id, updateLCG); + id++; + } + return out; + } + + public static void setWorldRandomnessMap(Map randomnessList) { + WorldServer[] worlds = TASmod.getServerInstance().worlds; + int id = 0; + for (WorldServer worldServer : worlds) { + WorldRandomness worldRandomness = randomnessList.get(id); + if (worldRandomness != null) + worldServer.rand = worldRandomness; + id++; + } + } + + public static void setWorldLCGMap(Map lcgList) { + WorldServer[] worlds = TASmod.getServerInstance().worlds; + int id = 0; + for (WorldServer worldServer : worlds) { + Integer updateLCG = lcgList.get(id); + if (updateLCG != null) + worldServer.updateLCG = updateLCG; + id++; + } + } + + public static String getWorldRandom() { + if (TASmod.getServerInstance().worlds[0] != null) + return Long.toString(((WorldRandomness) TASmod.getServerInstance().worlds[0].rand).getSeed()); + else + return ""; + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/MixinEntity.java b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/MixinEntity.java new file mode 100644 index 00000000..6db86d40 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/MixinEntity.java @@ -0,0 +1,32 @@ +package com.minecrafttas.tasmod.mixin.killtherng; + +import java.util.Random; +import java.util.UUID; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.minecrafttas.tasmod.ktrng.builtin.EntityRandomness; + +import net.minecraft.entity.Entity; +import net.minecraft.world.World; + +@Mixin(Entity.class) +public class MixinEntity { + + @ModifyExpressionValue(method = "", at = @At(value = "NEW", target = "Ljava/util/Random;")) + public Random modify_entityRandom(Random original, World world) { + if (!world.isRemote) { + return new EntityRandomness(); + } + return original; + } + + @WrapOperation(method = "", at = @At(value = "INVOKE", target = "Lnet/minecraft/util/math/MathHelper;getRandomUUID(Ljava/util/Random;)Ljava/util/UUID;")) + private UUID wrap_getRandomUUID(Random rand, Operation original) { + return original.call(new Random()); + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/MixinRenderLivingBase.java b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/MixinRenderLivingBase.java new file mode 100644 index 00000000..f7953eb3 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/MixinRenderLivingBase.java @@ -0,0 +1,44 @@ +package com.minecrafttas.tasmod.mixin.killtherng; + +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.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.minecrafttas.tasmod.TASmod; +import com.minecrafttas.tasmod.ktrng.RandomBase; + +import net.minecraft.client.renderer.GlStateManager; +import net.minecraft.client.renderer.entity.Render; +import net.minecraft.client.renderer.entity.RenderLivingBase; +import net.minecraft.client.renderer.entity.RenderManager; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; + +@SuppressWarnings("rawtypes") +@Mixin(RenderLivingBase.class) +public abstract class MixinRenderLivingBase extends Render { + + @Unique + private long previousSeed = 0; + + protected MixinRenderLivingBase(RenderManager renderManager) { + super(renderManager); + } + + @SuppressWarnings("unchecked") + @Inject(method = "renderName", at = @At(value = "HEAD")) + public void inject_renderName(EntityLivingBase entity, double d, double e, double f, CallbackInfo ci) { + Entity serverEntity = TASmod.getServerInstance().getEntityFromUuid(entity.getUniqueID()); + if (serverEntity == null) + return; + RandomBase random = (RandomBase) serverEntity.rand; + long seed = random.getSeed(); + long distance = -random.distance(random.getInitialSeed()); + GlStateManager.alphaFunc(516, 0.1F); + this.renderEntityName(entity, d, e + 0.69D, f, Long.toString(random.getInitialSeed()), 64); + this.renderEntityName(entity, d, e + 0.46D, f, Long.toString(seed), 64); + this.renderEntityName(entity, d, e + 0.23D, f, Long.toString(distance), 64); + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/MixinWorld.java b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/MixinWorld.java new file mode 100644 index 00000000..9e50b82c --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/MixinWorld.java @@ -0,0 +1,37 @@ +package com.minecrafttas.tasmod.mixin.killtherng; + +import java.util.Random; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.ModifyExpressionValue; +import com.llamalad7.mixinextras.injector.ModifyReceiver; +import com.llamalad7.mixinextras.injector.ModifyReturnValue; +import com.minecrafttas.tasmod.TASmod; +import com.minecrafttas.tasmod.ktrng.builtin.WorldRandomness; + +import net.minecraft.world.World; +import net.minecraft.world.WorldServer; + +@Mixin(World.class) +public class MixinWorld { + + @ModifyExpressionValue(method = "", at = @At(value = "NEW", target = "Ljava/util/Random;")) + public Random modify_worldRandom(Random original) { + if (((World) (Object) this) instanceof WorldServer) + return new WorldRandomness(); + else + return original; + } + + @ModifyReceiver(method = "setRandomSeed", at = @At(value = "INVOKE", target = "Ljava/util/Random;setSeed(J)V")) + public Random modify_worldSetRNGRandom(Random original, long seed) { + return TASmod.worldSeedRandomness; + } + + @ModifyReturnValue(method = "setRandomSeed", at = @At(value = "RETURN")) + public Random modify_worldSetRNGReturn(Random original) { + return TASmod.worldSeedRandomness; + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityItem.java b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityItem.java new file mode 100644 index 00000000..a94c9bf5 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityItem.java @@ -0,0 +1,20 @@ +package com.minecrafttas.tasmod.mixin.killtherng.mathrand; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.minecrafttas.tasmod.TASmod; + +import net.minecraft.entity.item.EntityItem; +import net.minecraft.world.World; + +@Mixin(EntityItem.class) +public class MixinEntityItem { + + @WrapOperation(method = "", at = @At(value = "INVOKE", target = "Ljava/lang/Math;random()D")) + private double wrap_entityItemInit(Operation original, World world, double d, double e, double f) { + return TASmod.mathRandomness.nextDouble(); + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityLivingBase.java b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityLivingBase.java new file mode 100644 index 00000000..2d882de9 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityLivingBase.java @@ -0,0 +1,25 @@ +package com.minecrafttas.tasmod.mixin.killtherng.mathrand; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.minecrafttas.tasmod.TASmod; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.world.World; + +@Mixin(EntityLivingBase.class) +public class MixinEntityLivingBase { + + @WrapOperation(method = "", at = @At(value = "INVOKE", target = "Ljava/lang/Math;random()D")) + private double wrap_entityLivingBase(Operation original, World world) { + return TASmod.mathRandomness.nextDouble(); + } + + @WrapOperation(method = "attackEntityFrom", at = @At(value = "INVOKE", target = "Ljava/lang/Math;random()D")) + private double wrap_attackEntityFrom(Operation original) { + return TASmod.mathRandomness.nextDouble(); + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityTNTPrimed.java b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityTNTPrimed.java new file mode 100644 index 00000000..bd8fec2d --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityTNTPrimed.java @@ -0,0 +1,21 @@ +package com.minecrafttas.tasmod.mixin.killtherng.mathrand; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.minecrafttas.tasmod.TASmod; + +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityTNTPrimed; +import net.minecraft.world.World; + +@Mixin(EntityTNTPrimed.class) +public class MixinEntityTNTPrimed { + + @WrapOperation(method = "", at = @At(value = "INVOKE", target = "Ljava/lang/Math;random()D")) + private double wrap_entityTNTPrimedInit(Operation original, World world, double d, double e, double f, EntityLivingBase entityLivingBase) { + return TASmod.mathRandomness.nextDouble(); + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityXPOrb.java b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityXPOrb.java new file mode 100644 index 00000000..ed776195 --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinEntityXPOrb.java @@ -0,0 +1,20 @@ +package com.minecrafttas.tasmod.mixin.killtherng.mathrand; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; +import com.minecrafttas.tasmod.TASmod; + +import net.minecraft.entity.item.EntityXPOrb; +import net.minecraft.world.World; + +@Mixin(EntityXPOrb.class) +public class MixinEntityXPOrb { + + @WrapOperation(method = "", at = @At(value = "INVOKE", target = "Ljava/lang/Math;random()D")) + private double wrap_entityXPOrb(Operation original, World world, double d, double e, double f, int i) { + return TASmod.mathRandomness.nextDouble(); + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinWorldEntitySpawner.java b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinWorldEntitySpawner.java new file mode 100644 index 00000000..3d9223da --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/mixin/killtherng/mathrand/MixinWorldEntitySpawner.java @@ -0,0 +1,19 @@ +package com.minecrafttas.tasmod.mixin.killtherng.mathrand; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; + +import com.llamalad7.mixinextras.injector.wrapoperation.Operation; +import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; + +import net.minecraft.world.WorldEntitySpawner; +import net.minecraft.world.WorldServer; + +@Mixin(WorldEntitySpawner.class) +public class MixinWorldEntitySpawner { + + @WrapOperation(method = "findChunksForSpawning", at = @At(value = "INVOKE", target = "Ljava/lang/Math;random()D")) + private double wrap_worldEntitySpawnerFindChunks(Operation original, WorldServer worldServer, boolean bl, boolean bl2, boolean bl3) { + return worldServer.rand.nextDouble(); + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/registries/TASmodAPIRegistry.java b/src/main/java/com/minecrafttas/tasmod/registries/TASmodAPIRegistry.java index 33816e55..ccca1d05 100644 --- a/src/main/java/com/minecrafttas/tasmod/registries/TASmodAPIRegistry.java +++ b/src/main/java/com/minecrafttas/tasmod/registries/TASmodAPIRegistry.java @@ -2,6 +2,7 @@ import com.minecrafttas.tasmod.commands.client.ClientCommandBase; import com.minecrafttas.tasmod.commands.client.ClientCommandRegistry; +import com.minecrafttas.tasmod.ktrng.KillTheRNGRegistry; import com.minecrafttas.tasmod.playback.filecommands.PlaybackFileCommandsRegistry; import com.minecrafttas.tasmod.playback.metadata.PlaybackMetadataRegistry; import com.minecrafttas.tasmod.playback.tasfile.flavor.SerialiserFlavorBase; @@ -20,6 +21,7 @@ public class TASmodAPIRegistry { * savestate/rerecord count and category. * *

Any custom class has to implement PlaybackMetadataExtension + *

Side: Client

*/ public static final PlaybackMetadataRegistry PLAYBACK_METADATA = new PlaybackMetadataRegistry(); @@ -28,7 +30,7 @@ public class TASmodAPIRegistry { * *

File commands give the opportunity to run commands on each recorded tick and each played back tick.
* File commands also have access to the TASfile so that data can be stored and read in/from the TASfile. - * + *

Side: Client

*/ public static final PlaybackFileCommandsRegistry PLAYBACK_FILE_COMMAND = new PlaybackFileCommandsRegistry(); @@ -39,6 +41,7 @@ public class TASmodAPIRegistry { * or extend an existing flavor (like {@link Beta1Flavor}) and overwrite parts of the methods. * *

The resulting flavor can be registered here and can be found as a saving option with /saveTAS + *

Side: Client

*/ public static final SerialiserFlavorRegistry SERIALISER_FLAVOR = new SerialiserFlavorRegistry(); @@ -47,6 +50,7 @@ public class TASmodAPIRegistry { * *

Create a new ClientCommand by extending {@link ClientCommandBase},
* then create a command like normal, as it extends from the vanilla {@link CommandBase} + *

Side: Client

*/ public static final ClientCommandRegistry CLIENT_COMMANDS = new ClientCommandRegistry(); @@ -56,4 +60,9 @@ public class TASmodAPIRegistry { *

Create a new SavestateStorageExtension by extending {@link SavestateStorageExtensionBase} */ public static final SavestateStorageExtensionRegistry SAVESTATE_STORAGE = new SavestateStorageExtensionRegistry(); + + /** + *

Registry for registering RNGs which should be deterministic. + */ + public static final KillTheRNGRegistry KILLTHERNG = new KillTheRNGRegistry(); } diff --git a/src/main/java/com/minecrafttas/tasmod/registries/TASmodKeybinds.java b/src/main/java/com/minecrafttas/tasmod/registries/TASmodKeybinds.java index 7c486dbf..bbd88526 100644 --- a/src/main/java/com/minecrafttas/tasmod/registries/TASmodKeybinds.java +++ b/src/main/java/com/minecrafttas/tasmod/registries/TASmodKeybinds.java @@ -46,7 +46,6 @@ public enum TASmodKeybinds implements KeybindID { TASmodClient.virtual.CAMERA_ANGLE.updateNextCameraAngle(0, 45); }), TEST1("Various Testing", "TASmod", Keyboard.KEY_F12, () -> { - Minecraft.getMinecraft().displayGuiScreen(null); }, VirtualKeybindings::isKeyDown), TEST2("Various Testing2", "TASmod", Keyboard.KEY_F7, () -> { }, VirtualKeybindings::isKeyDown); diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerServer.java b/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerServer.java index 150b67d5..ea4d0745 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerServer.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/SavestateHandlerServer.java @@ -384,7 +384,7 @@ private void loadStateInner(SavestatePaths paths, SavestateCallback cb, Savestat Path sourcefolder = paths.getSourceFolder(); Path targetfolder = paths.getTargetFolder(); - EventListenerRegistry.fireEvent(EventSavestate.EventServerLoadstate.class, server, paths); + EventListenerRegistry.fireEvent(EventSavestate.EventServerLoadstatePre.class, server, paths); /* * Prevents loading an InputSavestate when loading index 0 (Index 0 is the @@ -445,6 +445,8 @@ private void loadStateInner(SavestatePaths paths, SavestateCallback cb, Savestat worldHandler.sendChunksToClient(); + EventListenerRegistry.fireEvent(EventSavestate.EventServerLoadstatePost.class, server, paths); + if (SavestateFlags.BLOCK_PAUSE_TICKRATE.isBlocked(flags)) { TASmod.tickratechanger.pauseGame(false); } else { @@ -467,7 +469,7 @@ private void loadStateInner(SavestatePaths paths, SavestateCallback cb, Savestat * Rn it's not a problem, but this should be looked at... */ TASmod.tickSchedulerServer.add(() -> { - EventListenerRegistry.fireEvent(EventSavestate.EventServerCompleteLoadstate.class); + EventListenerRegistry.fireEvent(EventSavestate.EventServerCompleteLoadstate.class, server, paths); onLoadstateComplete(); }); } diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/files/SavestateDataFile.java b/src/main/java/com/minecrafttas/tasmod/savestates/files/SavestateDataFile.java index 86be2b42..faabe05e 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/files/SavestateDataFile.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/files/SavestateDataFile.java @@ -7,13 +7,18 @@ @Deprecated public class SavestateDataFile extends AbstractDataFile { + @Deprecated public SavestateDataFile(Path file) { super(file, "savestatedata", "Data for this savestate from TASmod"); } + @Deprecated public enum DataValues { + @Deprecated INDEX("currentIndex"), + @Deprecated NAME("savestateName"), + @Deprecated SEED("ktrngSeed"); private String configname; @@ -22,15 +27,18 @@ private DataValues(String configname) { this.configname = configname; } + @Deprecated public String getConfigName() { return configname; } } + @Deprecated public void set(DataValues key, String val) { properties.setProperty(key.getConfigName(), val); } + @Deprecated public String get(DataValues key) { return properties.getProperty(key.getConfigName()); } diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestatePlayerHandlerClient.java b/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestatePlayerHandlerClient.java index 878ec01f..a1bc64b7 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestatePlayerHandlerClient.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestatePlayerHandlerClient.java @@ -36,45 +36,8 @@ public void loadPlayer(NBTTagCompound compound) { // Clear any accidental applied potion particles on the client ((AccessorEntityLivingBase) player).clearPotionEffects(); - /* - * TODO - * The following 20 lines are all one - * gross workaround for correctly applying the player motion - * to the client... - * - * The motion is applied - * to the player in a previous step and unfortunately - * player.readFromNBT(compound) overwrites the - * previously applied motion... - * - * So this workaround makes sure that the motion is not overwritten - * Fixing this, requires restructuring the steps for loadstating - * and since I plan to do this anyway at some point, I will - * leave this here and be done for today*/ - double x = player.motionX; - double y = player.motionY; - double z = player.motionZ; - - float rx = player.moveForward; - float ry = player.moveVertical; - float rz = player.moveStrafing; - - boolean sprinting = player.isSprinting(); - float jumpVector = player.jumpMovementFactor; - player.readFromNBT(compound); - player.motionX = x; - player.motionY = y; - player.motionZ = z; - - player.moveForward = rx; - player.moveVertical = ry; - player.moveStrafing = rz; - - player.setSprinting(sprinting); - player.jumpMovementFactor = jumpVector; - LOGGER.trace(LoggerMarkers.Savestate, "Setting client gamemode"); // #86 int gamemode = compound.getInteger("playerGameType"); diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateResourcePackHandler.java b/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateResourcePackHandler.java index dcd76051..54c23313 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateResourcePackHandler.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateResourcePackHandler.java @@ -35,7 +35,7 @@ * * @author Scribble */ -public class SavestateResourcePackHandler implements EventSavestate.EventServerLoadstate, ServerPacketHandler, ClientPacketHandler { +public class SavestateResourcePackHandler implements EventSavestate.EventServerLoadstatePre, ServerPacketHandler, ClientPacketHandler { /** * The server future for waiting until the client is done unloading the RP @@ -48,7 +48,7 @@ public class SavestateResourcePackHandler implements EventSavestate.EventServerL public static CountDownLatch clientRPLatch; @Override - public void onServerLoadstate(MinecraftServer server, SavestatePaths paths) { + public void onServerLoadstatePre(MinecraftServer server, SavestatePaths paths) { if (server.getResourcePackUrl().isEmpty() || server.isDedicatedServer()) return; diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateTempHandler.java b/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateTempHandler.java index 619985e8..0474b760 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateTempHandler.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/handlers/SavestateTempHandler.java @@ -29,7 +29,7 @@ * * @author Scribble */ -public class SavestateTempHandler implements EventControllerStateChange, EventRecordClear, EventSavestate.EventServerLoadstate { +public class SavestateTempHandler implements EventControllerStateChange, EventRecordClear, EventSavestate.EventServerLoadstatePre { private final Logger logger; private final SavestateHandlerServer handler; @@ -149,7 +149,7 @@ public void setNoSave(boolean noSave) { } @Override - public void onServerLoadstate(MinecraftServer server, SavestatePaths paths) { + public void onServerLoadstatePre(MinecraftServer server, SavestatePaths paths) { createState = false; } } diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/storage/SavestateStorageExtensionBase.java b/src/main/java/com/minecrafttas/tasmod/savestates/storage/SavestateStorageExtensionBase.java index 1f911302..3e1b5b3a 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/storage/SavestateStorageExtensionBase.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/storage/SavestateStorageExtensionBase.java @@ -25,5 +25,12 @@ public SavestateStorageExtensionBase(String fileName) { public abstract JsonObject onSavestate(MinecraftServer server, JsonObject dataToSave); - public abstract void onLoadstate(MinecraftServer server, JsonObject loadedData); + public void onLoadstatePre(MinecraftServer server, JsonObject loadedData) { + } + + public void onLoadstatePost(MinecraftServer server, JsonObject loadedData) { + } + + public void onLoadstateComplete(MinecraftServer server, JsonObject loadedData) { + } } diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/storage/SavestateStorageExtensionRegistry.java b/src/main/java/com/minecrafttas/tasmod/savestates/storage/SavestateStorageExtensionRegistry.java index 8ab26bec..cdab59a6 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/storage/SavestateStorageExtensionRegistry.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/storage/SavestateStorageExtensionRegistry.java @@ -3,13 +3,14 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.HashMap; import java.util.LinkedHashMap; +import java.util.Map; import com.google.gson.JsonObject; import com.minecrafttas.mctcommon.registry.AbstractRegistry; import com.minecrafttas.tasmod.TASmod; -import com.minecrafttas.tasmod.events.EventSavestate.EventServerLoadstate; -import com.minecrafttas.tasmod.events.EventSavestate.EventServerSavestate; +import com.minecrafttas.tasmod.events.EventSavestate; import com.minecrafttas.tasmod.savestates.SavestateIndexer; import com.minecrafttas.tasmod.savestates.SavestateIndexer.SavestatePaths; import com.minecrafttas.tasmod.savestates.exceptions.LoadstateException; @@ -18,7 +19,9 @@ import net.minecraft.server.MinecraftServer; -public class SavestateStorageExtensionRegistry extends AbstractRegistry implements EventServerSavestate, EventServerLoadstate { +public class SavestateStorageExtensionRegistry extends AbstractRegistry implements EventSavestate.EventServerSavestate, EventSavestate.EventServerLoadstatePre, EventSavestate.EventServerLoadstatePost, EventSavestate.EventServerCompleteLoadstate { + + Map jsonMap = new HashMap<>(); public SavestateStorageExtensionRegistry() { super("SAVESTATESTORAGE_REGISTRY", new LinkedHashMap<>()); @@ -47,9 +50,9 @@ public void onServerSavestate(MinecraftServer server, SavestatePaths paths) { } } - @Override - public void onServerLoadstate(MinecraftServer server, SavestatePaths paths) { - Path storageDir = paths.getTargetFolder().resolve(SavestateIndexer.savestateDataDir); + private void load(SavestatePaths paths) { + jsonMap.clear(); + Path storageDir = paths.getSourceFolder().resolve(SavestateIndexer.savestateDataDir); if (!Files.exists(storageDir)) { try { Files.createDirectory(storageDir); @@ -72,8 +75,29 @@ public void onServerLoadstate(MinecraftServer server, SavestatePaths paths) { } catch (IOException e) { throw new LoadstateException(e, "Can't load %s in %s extension", storage.fileName, storage.getExtensionName()); } + jsonMap.put(storage, loadedData); + } + } - storage.onLoadstate(server, loadedData); + @Override + public void onServerLoadstatePre(MinecraftServer server, SavestatePaths paths) { + load(paths); + for (SavestateStorageExtensionBase storage : REGISTRY.values()) { + storage.onLoadstatePre(server, jsonMap.get(storage)); + } + } + + @Override + public void onServerLoadstatePost(MinecraftServer server, SavestatePaths paths) { + for (SavestateStorageExtensionBase storage : REGISTRY.values()) { + storage.onLoadstatePost(server, jsonMap.get(storage)); + } + } + + @Override + public void onServerLoadstateComplete(MinecraftServer server, SavestatePaths paths) { + for (SavestateStorageExtensionBase storage : REGISTRY.values()) { + storage.onLoadstateComplete(TASmod.getServerInstance(), jsonMap.get(storage)); } } } diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/storage/builtin/ClientMotionStorage.java b/src/main/java/com/minecrafttas/tasmod/savestates/storage/builtin/ClientMotionStorage.java index 26b7151b..81f89e55 100644 --- a/src/main/java/com/minecrafttas/tasmod/savestates/storage/builtin/ClientMotionStorage.java +++ b/src/main/java/com/minecrafttas/tasmod/savestates/storage/builtin/ClientMotionStorage.java @@ -87,7 +87,7 @@ public JsonObject onSavestate(MinecraftServer server, JsonObject dataToSave) { } @Override - public void onLoadstate(MinecraftServer server, JsonObject loadedData) { + public void onLoadstatePost(MinecraftServer server, JsonObject loadedData) { PlayerList list = server.getPlayerList(); for (Entry motionDataJsonElement : loadedData.entrySet()) { @@ -97,17 +97,16 @@ public void onLoadstate(MinecraftServer server, JsonObject loadedData) { EntityPlayerMP player; if (playerUUID.equals("singleplayer")) { String ownerName = server.getServerOwner(); - if (ownerName == null) { + if (ownerName == null) continue; - } + player = list.getPlayerByUsername(ownerName); } else { player = list.getPlayerByUUID(UUID.fromString(playerUUID)); } - if (player == null) { + if (player == null) continue; - } try { TASmod.server.sendTo(player, new TASmodBufferBuilder(SAVESTATE_SET_MOTION).writeMotionData(motionData)); diff --git a/src/main/java/com/minecrafttas/tasmod/savestates/storage/builtin/KTRNGSeedStorage.java b/src/main/java/com/minecrafttas/tasmod/savestates/storage/builtin/KTRNGSeedStorage.java new file mode 100644 index 00000000..8d332aaf --- /dev/null +++ b/src/main/java/com/minecrafttas/tasmod/savestates/storage/builtin/KTRNGSeedStorage.java @@ -0,0 +1,117 @@ +package com.minecrafttas.tasmod.savestates.storage.builtin; + +import java.util.HashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.UUID; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.minecrafttas.tasmod.TASmod; +import com.minecrafttas.tasmod.ktrng.builtin.EntityRandomness; +import com.minecrafttas.tasmod.ktrng.builtin.WorldRandomness; +import com.minecrafttas.tasmod.ktrng.handlers.KTRNGEntityHandler; +import com.minecrafttas.tasmod.ktrng.handlers.KTRNGWorldHandler; +import com.minecrafttas.tasmod.savestates.storage.SavestateStorageExtensionBase; + +import net.minecraft.server.MinecraftServer; + +public class KTRNGSeedStorage extends SavestateStorageExtensionBase { + + public KTRNGSeedStorage() { + super("killtherngSeeds.json"); + } + + @Override + public JsonObject onSavestate(MinecraftServer server, JsonObject dataToSave) { + long currentSeed = TASmod.globalRandomness.getCurrentSeed(); + dataToSave.addProperty("globalSeed", currentSeed); + + JsonObject entityRandomDataJson = new JsonObject(); + + JsonObject entityRandomListJson = new JsonObject(); + Map randomList = KTRNGEntityHandler.getRandomnessList(); + for (Entry entry : randomList.entrySet()) { + entityRandomListJson.addProperty(entry.getKey().toString(), entry.getValue().getSeed()); + } + + entityRandomDataJson.add("entityList", entityRandomListJson); + + dataToSave.add("entityRandom", entityRandomDataJson); + + JsonObject worldRandomDataJson = new JsonObject(); + + JsonObject worldListJson = new JsonObject(); + Map worldRandom = KTRNGWorldHandler.getWorldRandomnessMap(); + for (Entry entry : worldRandom.entrySet()) { + worldListJson.addProperty(entry.getKey().toString(), entry.getValue().getSeed()); + } + + worldRandomDataJson.add("worldList", worldListJson); + + JsonObject lcgListJson = new JsonObject(); + Map lcgMap = KTRNGWorldHandler.getWorldLCGMap(); + for (Entry entry : lcgMap.entrySet()) { + lcgListJson.addProperty(entry.getKey().toString(), entry.getValue()); + } + + worldRandomDataJson.add("lcgList", lcgListJson); + + dataToSave.add("worldRandom", worldRandomDataJson); + + dataToSave.addProperty("mathRandom", TASmod.mathRandomness.getSeed()); + + return dataToSave; + } + + @Override + public void onLoadstateComplete(MinecraftServer server, JsonObject loadedData) { + TASmod.LOGGER.debug("Loading KTRNG seeds"); + long newSeed = loadedData.get("globalSeed").getAsLong(); + TASmod.globalRandomness.setSeed(newSeed); + + JsonObject entityRandomDataJson = loadedData.get("entityRandom").getAsJsonObject(); + + JsonObject entityRandomListJson = entityRandomDataJson.get("entityList").getAsJsonObject(); + + Map randomList = new HashMap<>(); + for (Entry entry : entityRandomListJson.entrySet()) { + UUID uuid = UUID.fromString(entry.getKey().toString()); + EntityRandomness entityRandomness = new EntityRandomness(entry.getValue().getAsLong()); + + randomList.put(uuid, entityRandomness); + } + + KTRNGEntityHandler.setRandomnessList(randomList); + + JsonObject worldRandomJson = loadedData.get("worldRandom").getAsJsonObject(); + JsonObject worldListJson = worldRandomJson.get("worldList").getAsJsonObject(); + + Map worldList = new HashMap<>(); + for (Entry entry : worldListJson.entrySet()) { + int id = Integer.parseInt(entry.getKey()); + WorldRandomness worldRandomness = new WorldRandomness(entry.getValue().getAsLong()); + + worldList.put(id, worldRandomness); + } + + JsonObject worldLCGList = worldRandomJson.get("lcgList").getAsJsonObject(); + Map lcgList = new HashMap<>(); + for (Entry entry : worldLCGList.entrySet()) { + int id = Integer.parseInt(entry.getKey()); + int lcg = entry.getValue().getAsInt(); + + lcgList.put(id, lcg); + } + + KTRNGWorldHandler.setWorldRandomnessMap(worldList); + + long mathSeed = loadedData.get("mathRandom").getAsLong(); + TASmod.mathRandomness.setSeed(mathSeed); + } + + @Override + public String getExtensionName() { + return "KTRNGSeedStorage"; + } +} diff --git a/src/main/java/com/minecrafttas/tasmod/util/LoggerMarkers.java b/src/main/java/com/minecrafttas/tasmod/util/LoggerMarkers.java index 1d2951ed..1a08fe30 100644 --- a/src/main/java/com/minecrafttas/tasmod/util/LoggerMarkers.java +++ b/src/main/java/com/minecrafttas/tasmod/util/LoggerMarkers.java @@ -47,6 +47,8 @@ public class LoggerMarkers implements EventDrawHotbarAlways { public static final Marker Mouse = MarkerManager.getMarker("Mouse"); + public static final Marker KillTheRNG = MarkerManager.getMarker("KillTheRNG"); + @Override public void onDrawHotbarAlways() { ScaledResolution scaledresolution = new ScaledResolution(Minecraft.getMinecraft()); diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 2a4bea59..105e907c 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -26,8 +26,8 @@ ] }, "mixins": [ - "tasmod.mixin.json", - "mctcommon.mixin.json" + "mctcommon.mixin.json", + "tasmod.mixin.json" ], "depends": { "fabricloader": ">=0.14.19", diff --git a/src/main/resources/log4j.xml b/src/main/resources/log4j.xml index 88fd9007..d2826b99 100644 --- a/src/main/resources/log4j.xml +++ b/src/main/resources/log4j.xml @@ -15,6 +15,8 @@ onMatch="${sys:tasmod.marker.keyboard:-DENY}" onMismatch="NEUTRAL" /> + diff --git a/src/main/resources/tasmod.accesswidener b/src/main/resources/tasmod.accesswidener index 0029bc11..1f287702 100644 --- a/src/main/resources/tasmod.accesswidener +++ b/src/main/resources/tasmod.accesswidener @@ -11,4 +11,9 @@ accessible field net/minecraft/world/World worldInfo Lnet/minecraft/world/storag accessible method net/minecraft/world/storage/SaveHandler setSessionLock ()V -accessible field net/minecraft/client/settings/KeyBinding CATEGORY_ORDER Ljava/util/Map; \ No newline at end of file +accessible field net/minecraft/client/settings/KeyBinding CATEGORY_ORDER Ljava/util/Map; + +#KillTheRNG +accessible field net/minecraft/entity/Entity rand Ljava/util/Random; +accessible field net/minecraft/world/World updateLCG I +mutable field net/minecraft/world/World rand Ljava/util/Random; \ No newline at end of file diff --git a/src/main/resources/tasmod.mixin.json b/src/main/resources/tasmod.mixin.json index b500e7d6..2daed941 100644 --- a/src/main/resources/tasmod.mixin.json +++ b/src/main/resources/tasmod.mixin.json @@ -21,7 +21,15 @@ "events.MixinEntityPlayerMP", // Fixing forge and vanilla stuff - "fixes.MixinDragonFightManager" + "fixes.MixinDragonFightManager", + + "killtherng.MixinEntity", + "killtherng.MixinWorld", + "killtherng.mathrand.MixinEntityLivingBase", + "killtherng.mathrand.MixinEntityItem", + "killtherng.mathrand.MixinEntityXPOrb", + "killtherng.mathrand.MixinEntityTNTPrimed", + "killtherng.mathrand.MixinWorldEntitySpawner" ], "client": [ @@ -68,6 +76,9 @@ // Fixes "fixes.MixinMinecraftFullscreen", "fixes.MixinNetworkManager", - "fixes.MixinMouseHelper" + "fixes.MixinMouseHelper", + + // KTRNG + "killtherng.MixinRenderLivingBase" ] } \ No newline at end of file diff --git a/src/test/java/tasmod/killtherng/RNGTest.java b/src/test/java/tasmod/killtherng/RNGTest.java new file mode 100644 index 00000000..296524e4 --- /dev/null +++ b/src/test/java/tasmod/killtherng/RNGTest.java @@ -0,0 +1,40 @@ +package tasmod.killtherng; + +import com.minecrafttas.tasmod.ktrng.RandomBase; + +public class RNGTest { + + public static void main(String[] args) { + long[] longlist = new long[] { + //@formatter:off + 221103401599600L, + 145180429625787L, + 179651266561706L + //@formatter:on + }; + + printDistance(longlist); + + longlist = new long[] { + //@formatter:off + 161845404674820L, + 107865211428631L, + 252587169991970L, + 223075662074294L, + 66246869218509L, + 81210955942352L, + 183553865074233L, + 11371681017552L + //@formatter:on + }; +// printDistance(longlist); + } + + private static void printDistance(long[] list) { + long prev = list[0]; + for (long l : list) { + System.out.println(RandomBase.distance(prev, l)); + } + System.out.println(""); + } +} diff --git a/src/test/java/tasmod/killtherng/RandomBaseTest.java b/src/test/java/tasmod/killtherng/RandomBaseTest.java new file mode 100644 index 00000000..1845241f --- /dev/null +++ b/src/test/java/tasmod/killtherng/RandomBaseTest.java @@ -0,0 +1,94 @@ +package tasmod.killtherng; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import com.minecrafttas.tasmod.ktrng.RandomBase; + +import kaptainwutax.seedutils.rand.JRand; + +class TestRNGTest { + + class TestRNG extends RandomBase { + + public TestRNG() { + super(); + } + + public TestRNG(long seed) { + super(seed); + } + + @Override + public String getExtensionName() { + return "TestRNG"; + } + + } + + @BeforeEach + void setUp() throws Exception { + } + + @Test + void testInitialSeed() { + long expected = 12345L; + TestRNG testRandom = new TestRNG(expected); + long actual = testRandom.getSeed(); + assertEquals(12345L, actual); + } + + @Test + void testSetSeed() { + TestRNG testRandom = new TestRNG(1L); + testRandom.setSeed(12345L); + assertEquals(12345L, testRandom.getSeed()); + } + + @Test + void testAdvance() { + JRand thing = JRand.ofInternalSeed(12345L); + TestRNG testRandom = new TestRNG(12345L); + + testRandom.advance(); + thing.advance(1); + + assertEquals(thing.getSeed(), testRandom.getSeed()); + } + + @Test + void testAdvancingLong() { + JRand thing = JRand.ofInternalSeed(12345L); + TestRNG testRandom = new TestRNG(12345L); + + long expectedValue = thing.nextLong(); + long actualValue = testRandom.nextLong(); + + assertEquals(expectedValue, actualValue); + assertEquals(thing.getSeed(), testRandom.getSeed()); + } + + @Test + void testAdvancingLong2() { + JRand thing = JRand.ofInternalSeed(12345L); + TestRNG testRandom = new TestRNG(12345L); + + testRandom.nextLong(); + thing.advance(2); + + assertEquals(thing.getSeed(), testRandom.getSeed()); + } + + @Test + void testAdvancingDifferentRNGs() { + TestRNG testRandom1 = new TestRNG(12345L); + TestRNG testRandom2 = new TestRNG(12345L); + + testRandom1.nextInt(); + testRandom2.nextInt(6); + + assertEquals(testRandom1.getSeed(), testRandom2.getSeed()); + } +}