From 3e3606441d80228ec5fc3d381f205e42af5ff7dc Mon Sep 17 00:00:00 2001 From: RTTV Date: Wed, 29 May 2024 17:34:42 -0400 Subject: [PATCH 01/78] temp changes --- .../mixin/rngevents/EntityMixin.java | 21 +++++++++++++++++- .../rngevents/LocateHidingPlaceMixin.java | 22 +++++++++++++++++++ .../VillageBoundRandomStrollMixin.java | 18 +++++++++++++++ src/main/resources/mixins.clientcommands.json | 2 ++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LocateHidingPlaceMixin.java create mode 100644 src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/VillageBoundRandomStrollMixin.java diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java index 60e43cb18..088b5541c 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java @@ -2,15 +2,25 @@ import net.earthcomputer.clientcommands.features.PlayerRandCracker; import net.minecraft.client.player.LocalPlayer; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.tags.FluidTags; +import net.minecraft.tags.TagKey; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.schedule.Activity; +import net.minecraft.world.level.material.Fluid; 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.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Arrays; + @Mixin(Entity.class) -public class EntityMixin { +public abstract class EntityMixin { @Inject(method = "doWaterSplashEffect", at = @At("HEAD")) public void onDoWaterSplashEffect(CallbackInfo ci) { if (isThePlayer()) { @@ -36,4 +46,13 @@ public void onSprinting(CallbackInfo ci) { private boolean isThePlayer() { return (Object) this instanceof LocalPlayer; } + + @Redirect(method = "doWaterSplashEffect", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V")) + private void playSound(Entity instance, SoundEvent sound, float volume, float pitch) { + if ((Object) this instanceof Villager villager && !instance.level().isClientSide) { + System.out.println(Arrays.toString(villager.getBrain().getActiveActivities().toArray(Activity[]::new))); +// System.out.println("Villager splash sound pitch: " + pitch); + } + instance.playSound(sound, volume, pitch); + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LocateHidingPlaceMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LocateHidingPlaceMixin.java new file mode 100644 index 000000000..c1c0b4021 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LocateHidingPlaceMixin.java @@ -0,0 +1,22 @@ +package net.earthcomputer.clientcommands.mixin.rngevents; + +import net.minecraft.core.BlockPos; +import net.minecraft.core.Position; +import net.minecraft.world.entity.ai.behavior.LocateHidingPlace; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +@Mixin(LocateHidingPlace.class) +public class LocateHidingPlaceMixin { + @Redirect(method = "lambda$create$2", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;closerToCenterThan(Lnet/minecraft/core/Position;D)Z")) + private static boolean isCloseEnough(BlockPos instance, Position position, double v) { + boolean result = instance.closerToCenterThan(position, v); +// System.out.println("Close enough? " + result); +// if (!result) { +// System.out.println("BlockPos: " + instance + ", Position: " + new Vec3(position.x(), position.y(), position.z()) + ", Distance: " + v); +// } + return result; + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/VillageBoundRandomStrollMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/VillageBoundRandomStrollMixin.java new file mode 100644 index 000000000..62e54c3fd --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/VillageBoundRandomStrollMixin.java @@ -0,0 +1,18 @@ +package net.earthcomputer.clientcommands.mixin.rngevents; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.PathfinderMob; +import net.minecraft.world.entity.ai.behavior.VillageBoundRandomStroll; +import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +@Mixin(VillageBoundRandomStroll.class) +public class VillageBoundRandomStrollMixin { + @Inject(method = "lambda$create$1", at = @At("HEAD")) + private static void youFuckedUp(int i, int j, MemoryAccessor memoryAccessor, float f, ServerLevel level, PathfinderMob mob, long gameTime, CallbackInfoReturnable cir) { + System.out.println("rand called [x30]"); + } +} diff --git a/src/main/resources/mixins.clientcommands.json b/src/main/resources/mixins.clientcommands.json index cf16db199..317d3bd05 100644 --- a/src/main/resources/mixins.clientcommands.json +++ b/src/main/resources/mixins.clientcommands.json @@ -41,11 +41,13 @@ "rngevents.ItemStackMixin", "rngevents.LivingEntityMixin", "rngevents.LocalPlayerMixin", + "rngevents.LocateHidingPlaceMixin", "rngevents.MultiPlayerGameModeMixin", "rngevents.PlayerMixin", "rngevents.PumpkinBlockMixin", "rngevents.ServerboundContainerClosePacketMixin", "rngevents.ShearsItemMixin", + "rngevents.VillageBoundRandomStrollMixin", "rngevents.droppableinventory.CartographyTableMenuMixin", "rngevents.droppableinventory.CraftingMenuMixin", "rngevents.droppableinventory.EnchantmentMenuMixin", From b935782af873aef087a26c2892f9c8630b0536a7 Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 30 May 2024 21:38:34 -0400 Subject: [PATCH 02/78] finally i can hold on to a villager's rng state --- .../clientcommands/codegen/CodeGenerator.java | 14 +++- .../clientcommands/ClientCommands.java | 1 + .../command/VillagerCommand.java | 49 +++++++++++ .../clientcommands/features/CCrackRngGen.java | 2 +- .../features/CrackVillagerRngGen.java | 43 ++++++++++ .../features/VillagerCracker.java | 82 +++++++++++++++++++ .../features/VillagerRngSimulator.java | 62 ++++++++++++++ .../clientcommands/interfaces/IVillager.java | 14 ++++ .../commands/villager/VillagerMixin.java | 46 +++++++++++ .../rngevents/ClientPacketListenerMixin.java | 35 ++++++++ .../mixin/rngevents/EntityMixin.java | 19 ----- .../mixin/rngevents/LivingEntityMixin.java | 2 + .../rngevents/LocateHidingPlaceMixin.java | 22 ----- .../VillageBoundRandomStrollMixin.java | 18 ---- .../clientcommands/util/DebugRandom.java | 17 +++- .../assets/clientcommands/lang/en_us.json | 6 ++ src/main/resources/mixins.clientcommands.json | 3 +- 17 files changed, 369 insertions(+), 66 deletions(-) create mode 100644 src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java create mode 100644 src/main/java/net/earthcomputer/clientcommands/features/CrackVillagerRngGen.java create mode 100644 src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java create mode 100644 src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java create mode 100644 src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java create mode 100644 src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java delete mode 100644 src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LocateHidingPlaceMixin.java delete mode 100644 src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/VillageBoundRandomStrollMixin.java diff --git a/src/codeGen/java/net/earthcomputer/clientcommands/codegen/CodeGenerator.java b/src/codeGen/java/net/earthcomputer/clientcommands/codegen/CodeGenerator.java index cf5b82606..2c40de19a 100644 --- a/src/codeGen/java/net/earthcomputer/clientcommands/codegen/CodeGenerator.java +++ b/src/codeGen/java/net/earthcomputer/clientcommands/codegen/CodeGenerator.java @@ -19,10 +19,20 @@ public static void main(String[] args) throws IOException { } Path destDir = Path.of(args[0]); - genLattiCG(destDir); + genPlayerLattiCG(destDir); + genVillagerLattiCG(destDir); } - private static void genLattiCG(Path destDir) throws IOException { + private static void genVillagerLattiCG(Path destDir) throws IOException { + ProgramBuilder program = Program.builder(LCG.JAVA); + + program.skip(-2); + program.add(JavaCalls.nextLong()); + + writeLattiCGClass(program.build(), "net.earthcomputer.clientcommands.features.CrackVillagerRngGen", destDir); + } + + private static void genPlayerLattiCG(Path destDir) throws IOException { ProgramBuilder program = Program.builder(LCG.JAVA); program.skip(-CCrackRng.NUM_THROWS * 4); for (int i = 0; i < CCrackRng.NUM_THROWS; i++) { diff --git a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java index 830978ac8..ef179bac3 100644 --- a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java +++ b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java @@ -168,6 +168,7 @@ public static void registerCommands(CommandDispatcher UsageTreeCommand.register(dispatcher); UuidCommand.register(dispatcher); VarCommand.register(dispatcher); + VillagerCommand.register(dispatcher); WeatherCommand.register(dispatcher); WhisperEncryptedCommand.register(dispatcher); WikiCommand.register(dispatcher); diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java new file mode 100644 index 000000000..cf4e3a4c4 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -0,0 +1,49 @@ +package net.earthcomputer.clientcommands.command; + +import com.mojang.brigadier.Command; +import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import net.earthcomputer.clientcommands.features.VillagerCracker; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.Villager; + +import static dev.xpple.clientarguments.arguments.CBlockPosArgument.*; +import static dev.xpple.clientarguments.arguments.CEntityArgument.*; +import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; + +public class VillagerCommand { + private static final SimpleCommandExceptionType NOT_A_VILLAGER_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notAVillager")); + + public static void register(CommandDispatcher dispatcher) { + dispatcher.register( + literal("cvillager") + .then(literal("timer") + .then(argument("value", blockPos()) + .executes(ctx -> setTimerBlockPos(ctx.getSource(), getBlockPos(ctx, "value"))))) + .then(literal("target") + .then(argument("value", entity()) + .executes(ctx -> setVillagerTarget(ctx.getSource(), getEntity(ctx, "value")))))); + } + + private static int setTimerBlockPos(FabricClientCommandSource source, BlockPos pos) { + VillagerCracker.timerBlockPos = pos; + Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.timerSet", pos.getX(), pos.getY(), pos.getZ())); + return Command.SINGLE_SUCCESS; + } + + private static int setVillagerTarget(FabricClientCommandSource source, Entity target) throws CommandSyntaxException { + if (!(target instanceof Villager villager)) { + throw NOT_A_VILLAGER_EXCEPTION.create(); + } + + VillagerCracker.setTargetVillager(villager); + Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.targetSet")); + + return Command.SINGLE_SUCCESS; + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/features/CCrackRngGen.java b/src/main/java/net/earthcomputer/clientcommands/features/CCrackRngGen.java index 74c8c23fd..d136e0049 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/CCrackRngGen.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/CCrackRngGen.java @@ -26,7 +26,7 @@ private CCrackRngGen() {} private static final BigVector ORIGIN = DeserializeRt.vec( "\u0a00ʈ뒦벎츖ʐ駗질긾ʘ뾖黱덪ʠ뚊ꃪ쀆ʨ躛\ue6d4锦ʰ힒볩ﱁʸꆽ\uaaf8葉ˀﲈ쎉錏ˈ\uf8a5\uf19e똠Ȁ"); private static final BigVector ROOT_ORIGIN = DeserializeRt.vec( - "\u0ad7醌뗤ꪜހ肀肀耠횑貵\ue4aaﰃ肀肀肀‟ࣞ뚂\uf1e0뮚Ҁ肀肀耠骤蟓ꊳ輆肀肀肀⃟뚂\uf1e0뭲肀肀肀ဦ\u089aꒇ펢뎧ڀ肀肀耠\udeb6英\ue0bb㺀肀肀耐\udfb6英\ue0bbʀ肀肀耠"); + "\u0ad7醌뗤ꪜހ肀肀耠횑貵\ue4aaﰃ肀肀肀‟ࣞ뚂\uf1e0뮚Ҁ肀肀耠骤蟓ꊳ輆肀肀肀⃟뚂\uf1e0뭲肀肀肀ဦ࢚ꒇ펢뎧ڀ肀肀耠\udeb6英\ue0bb㺀肀肀耐\udfb6英\ue0bbʀ肀肀耠"); /** * Finds all values of {@code seed} that could produce the given results in the following code: diff --git a/src/main/java/net/earthcomputer/clientcommands/features/CrackVillagerRngGen.java b/src/main/java/net/earthcomputer/clientcommands/features/CrackVillagerRngGen.java new file mode 100644 index 000000000..cfefd00e8 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/features/CrackVillagerRngGen.java @@ -0,0 +1,43 @@ +package net.earthcomputer.clientcommands.features; + +import com.seedfinding.latticg.math.component.BigMatrix; +import com.seedfinding.latticg.math.component.BigVector; +import com.seedfinding.latticg.math.lattice.enumerate.EnumerateRt; +import com.seedfinding.latticg.math.optimize.Optimize; +import com.seedfinding.latticg.util.DeserializeRt; +import java.util.stream.LongStream; + +// CLASS GENERATED BY LATTICG, DO NOT EDIT MANUALLY +public final class CrackVillagerRngGen { + private CrackVillagerRngGen() {} + private static final BigMatrix BASIS = DeserializeRt.mat( + "Ȃ苻봇˃\uf1afᄂ\udaf8찄˦鋃ᜂ"); + private static final BigMatrix ROOT_INV = DeserializeRt.mat( + "Ȃ\ue692쌗肀肀肀老싱꼑肀肀肀老\udbf8찄肀肀肀老苻봇肀肀肀老"); + private static final BigVector ORIGIN = DeserializeRt.vec( + "ȀȖȀ"); + private static final BigVector ROOT_ORIGIN = DeserializeRt.vec( + "˖\ue08e뼁肀肀肀老雉ꥒ肀肀肀老"); + + /** + * Finds all values of {@code seed} that could produce the given results in the following code: + *
{@code
+     *    Random rand = new Random(seed ^ 0x5DEECE66DL);
+     *    // Go backwards by 2 random calls
+     *    long nextLong1 = rand.nextLong();
+     * }
+ * + *

This code skips 0.000000% of seeds in its search. + */ + public static LongStream getSeeds(long nextLong1) { + Optimize.Builder builder = Optimize.Builder.ofSize(2); + long longFirstSeed1 = nextLong1 >>> 32 << 16; + if (nextLong1 < 0) { + longFirstSeed1 += (1L << 16); + } + builder.withLowerBound(0, longFirstSeed1).withUpperBound(0, longFirstSeed1 + (1L << 16) - 1); + builder.withLowerBound(1, (nextLong1 & 0xffffffffL) << 16).withUpperBound(1, (((nextLong1 & 0xffffffffL) + 1) << 16) - 1); + return EnumerateRt.enumerate(BASIS, ORIGIN, builder.build(), ROOT_INV, ROOT_ORIGIN) + .mapToLong(vec -> (vec.get(0).getNumerator().longValue() * 0x5deece66dL + 0xbL) & ((1L << 48) - 1)); + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java new file mode 100644 index 000000000..a136d5663 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -0,0 +1,82 @@ +package net.earthcomputer.clientcommands.features; + +import net.earthcomputer.clientcommands.command.ClientCommandHelper; +import net.earthcomputer.clientcommands.interfaces.IVillager; +import net.minecraft.client.Minecraft; +import net.minecraft.core.BlockPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.Villager; +import org.jetbrains.annotations.Nullable; + +import java.lang.ref.WeakReference; +import java.util.UUID; + +public class VillagerCracker { + @Nullable + private static UUID villagerUuid = null; + @Nullable + private static WeakReference cachedVillager = null; + + @Nullable + public static BlockPos timerBlockPos = null; + + @Nullable + public static Villager getVillager() { + if (villagerUuid == null) { + cachedVillager = null; + return null; + } + if (cachedVillager != null) { + Villager villager = cachedVillager.get(); + if (villager != null && !villager.isRemoved()) { + return villager; + } + } + for (Entity entity : Minecraft.getInstance().level.entitiesForRendering()) { + if (entity.getUUID() == villagerUuid && entity instanceof Villager villager) { + cachedVillager = new WeakReference<>(villager); + return villager; + } + } + return null; + } + + public static void setTargetVillager(Villager villager) { + VillagerCracker.cachedVillager = new WeakReference<>(villager); + VillagerCracker.villagerUuid = villager.getUUID(); + } + + public static void onSoundEventPlayed(ClientboundSoundPacket packet) { + Villager targetVillager = getVillager(); + if (targetVillager == null) { + return; + } + + if (packet.getSound().value().getLocation().getPath().startsWith("item.armor.equip_")) { + long seed = packet.getSeed(); + long[] possible = CrackVillagerRngGen.getSeeds(seed).toArray(); + if (possible.length == 0) { + ClientCommandHelper.sendError(Component.translatable("commands.cvillager.crackFailed")); + } else { + ((IVillager) targetVillager).clientcommands_setCrackedRandom(RandomSource.create(possible[0] ^ 0x5deece66dL)); + Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.crackSuccess", Long.toHexString(possible[0]))); + } + } + + if (packet.getSound().value().getLocation().getPath().equals("entity.villager.ambient")) { + ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(); + } + } + + public static void onServerTick() { + Villager targetVillager = getVillager(); + if (targetVillager == null) { + return; + } + + ((IVillager) targetVillager).clientcommands_onServerTick(); + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java new file mode 100644 index 000000000..9829e6dbf --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -0,0 +1,62 @@ +package net.earthcomputer.clientcommands.features; + +import net.minecraft.world.level.levelgen.LegacyRandomSource; +import org.jetbrains.annotations.Nullable; + +public class VillagerRngSimulator { + @Nullable + private final LegacyRandomSource random; + private int ambientSoundTime; + + public VillagerRngSimulator(@Nullable LegacyRandomSource random, int ambientSoundTime) { + this.random = random; + this.ambientSoundTime = ambientSoundTime; + } + + @Override + protected Object clone() { + return new VillagerRngSimulator(random == null ? null : new LegacyRandomSource(random.seed.get() ^ 0x5deece66dL), ambientSoundTime); + } + + public boolean simulateTick() { + boolean madeSound; + + if (random == null) { + return false; + } + + if (random.nextInt(1000) < ambientSoundTime++) { + random.nextFloat(); + random.nextFloat(); + ambientSoundTime = -80; + madeSound = true; + } else { + madeSound = false; + } + + return madeSound; + } + + public LegacyRandomSource random() { + return random; + } + + public int getAmbientSoundTime() { + return ambientSoundTime; + } + + @Override + public String toString() { + return "VillagerRngSimulator[" + + "seed=" + (random == null ? "null" : random.seed.get()) + ", " + + "ambientSoundTime=" + ambientSoundTime + ']'; + } + + public void onAmbientSoundPlayed() { + ambientSoundTime = -80; + if (random != null) { + random.nextFloat(); + random.nextFloat(); + } + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java new file mode 100644 index 000000000..3cdeae936 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java @@ -0,0 +1,14 @@ +package net.earthcomputer.clientcommands.interfaces; + +import net.earthcomputer.clientcommands.features.VillagerRngSimulator; +import net.minecraft.util.RandomSource; + +public interface IVillager { + void clientcommands_setCrackedRandom(RandomSource random); + + VillagerRngSimulator clientcommands_getCrackedRandom(); + + void clientcommands_onAmbientSoundPlayed(); + + void clientcommands_onServerTick(); +} diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java new file mode 100644 index 000000000..7d8a5e138 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -0,0 +1,46 @@ +package net.earthcomputer.clientcommands.mixin.commands.villager; + +import net.earthcomputer.clientcommands.features.VillagerRngSimulator; +import net.earthcomputer.clientcommands.interfaces.IVillager; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.level.levelgen.LegacyRandomSource; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; + +@Mixin(Villager.class) +public class VillagerMixin implements IVillager { + @Unique + VillagerRngSimulator rng = new VillagerRngSimulator(null, 0); + + @Unique + boolean hasSetCrackedAmbientSoundTime = false; + + @Override + public void clientcommands_setCrackedRandom(RandomSource random) { + rng = new VillagerRngSimulator((LegacyRandomSource) random, rng.getAmbientSoundTime()); + hasSetCrackedAmbientSoundTime = false; + } + + @Override + public VillagerRngSimulator clientcommands_getCrackedRandom() { + return rng; + } + + @Override + public void clientcommands_onAmbientSoundPlayed() { + if (!hasSetCrackedAmbientSoundTime) { + rng.onAmbientSoundPlayed(); + } + } + + @Override + public void clientcommands_onServerTick() { + if (rng.simulateTick()) { + hasSetCrackedAmbientSoundTime = true; + Minecraft.getInstance().player.sendSystemMessage(Component.literal("hrmm")); + } + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java index cd0ff704f..08ac67b41 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java @@ -2,14 +2,25 @@ import com.mojang.brigadier.StringReader; import net.earthcomputer.clientcommands.features.PlayerRandCracker; +import net.earthcomputer.clientcommands.features.VillagerCracker; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; +import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; +import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; +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(ClientPacketListener.class) public abstract class ClientPacketListenerMixin { + @Shadow + private ClientLevel level; + @Inject(method = "sendCommand", at = @At("HEAD")) private void onSendCommand(String command, CallbackInfo ci) { StringReader reader = new StringReader(command); @@ -18,4 +29,28 @@ private void onSendCommand(String command, CallbackInfo ci) { PlayerRandCracker.onGiveCommand(); } } + + @Inject(method = "handleSoundEvent", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void onHandleSoundEvent(ClientboundSoundPacket packet, CallbackInfo ci) { + Villager targetVillager = VillagerCracker.getVillager(); + if (targetVillager != null && new Vec3(packet.getX(), packet.getY(), packet.getZ()).distanceToSqr(targetVillager.position()) <= 0.1f) { + VillagerCracker.onSoundEventPlayed(packet); + } + } + + @Inject(method = "handleBlockUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackInfo ci) { + if (packet.getPos().equals(VillagerCracker.timerBlockPos)) { + VillagerCracker.onServerTick(); + } + } + + @Inject(method = "handleChunkBlocksUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void onHandleChunkBlocksUpdate(ClientboundSectionBlocksUpdatePacket packet, CallbackInfo ci) { + packet.runUpdates((pos, state) -> { + if (pos.equals(VillagerCracker.timerBlockPos)) { + VillagerCracker.onServerTick(); + } + }); + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java index 088b5541c..a7d51f9ce 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java @@ -2,23 +2,13 @@ import net.earthcomputer.clientcommands.features.PlayerRandCracker; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.sounds.SoundEvent; -import net.minecraft.tags.FluidTags; -import net.minecraft.tags.TagKey; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.entity.schedule.Activity; -import net.minecraft.world.level.material.Fluid; 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.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.Arrays; - @Mixin(Entity.class) public abstract class EntityMixin { @Inject(method = "doWaterSplashEffect", at = @At("HEAD")) @@ -46,13 +36,4 @@ public void onSprinting(CallbackInfo ci) { private boolean isThePlayer() { return (Object) this instanceof LocalPlayer; } - - @Redirect(method = "doWaterSplashEffect", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;playSound(Lnet/minecraft/sounds/SoundEvent;FF)V")) - private void playSound(Entity instance, SoundEvent sound, float volume, float pitch) { - if ((Object) this instanceof Villager villager && !instance.level().isClientSide) { - System.out.println(Arrays.toString(villager.getBrain().getActiveActivities().toArray(Activity[]::new))); -// System.out.println("Villager splash sound pitch: " + pitch); - } - instance.playSound(sound, volume, pitch); - } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java index 1a40023c0..f392d784f 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java @@ -6,6 +6,7 @@ import net.minecraft.core.BlockPos; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.EnchantmentHelper; @@ -14,6 +15,7 @@ import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.FrostedIceBlock; import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.levelgen.LegacyRandomSource; import net.minecraft.world.phys.shapes.CollisionContext; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LocateHidingPlaceMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LocateHidingPlaceMixin.java deleted file mode 100644 index c1c0b4021..000000000 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LocateHidingPlaceMixin.java +++ /dev/null @@ -1,22 +0,0 @@ -package net.earthcomputer.clientcommands.mixin.rngevents; - -import net.minecraft.core.BlockPos; -import net.minecraft.core.Position; -import net.minecraft.world.entity.ai.behavior.LocateHidingPlace; -import net.minecraft.world.phys.Vec3; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -@Mixin(LocateHidingPlace.class) -public class LocateHidingPlaceMixin { - @Redirect(method = "lambda$create$2", at = @At(value = "INVOKE", target = "Lnet/minecraft/core/BlockPos;closerToCenterThan(Lnet/minecraft/core/Position;D)Z")) - private static boolean isCloseEnough(BlockPos instance, Position position, double v) { - boolean result = instance.closerToCenterThan(position, v); -// System.out.println("Close enough? " + result); -// if (!result) { -// System.out.println("BlockPos: " + instance + ", Position: " + new Vec3(position.x(), position.y(), position.z()) + ", Distance: " + v); -// } - return result; - } -} diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/VillageBoundRandomStrollMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/VillageBoundRandomStrollMixin.java deleted file mode 100644 index 62e54c3fd..000000000 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/VillageBoundRandomStrollMixin.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.earthcomputer.clientcommands.mixin.rngevents; - -import net.minecraft.server.level.ServerLevel; -import net.minecraft.world.entity.PathfinderMob; -import net.minecraft.world.entity.ai.behavior.VillageBoundRandomStroll; -import net.minecraft.world.entity.ai.behavior.declarative.MemoryAccessor; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -@Mixin(VillageBoundRandomStroll.class) -public class VillageBoundRandomStrollMixin { - @Inject(method = "lambda$create$1", at = @At("HEAD")) - private static void youFuckedUp(int i, int j, MemoryAccessor memoryAccessor, float f, ServerLevel level, PathfinderMob mob, long gameTime, CallbackInfoReturnable cir) { - System.out.println("rand called [x30]"); - } -} diff --git a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java index 994adb583..111ce3d6e 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java @@ -1,5 +1,6 @@ package net.earthcomputer.clientcommands.util; +import com.mojang.blaze3d.platform.ClipboardManager; import com.mojang.logging.LogUtils; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; @@ -16,6 +17,7 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.levelgen.LegacyRandomSource; import net.minecraft.world.level.levelgen.RandomSupport; +import org.apache.commons.lang3.mutable.MutableInt; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -30,9 +32,8 @@ import java.io.StringWriter; import java.nio.file.Files; import java.nio.file.Path; -import java.util.ArrayList; +import java.util.*; import java.util.List; -import java.util.Vector; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; @@ -267,7 +268,19 @@ class DebugRandomSourcePanel extends JPanel { } }); bottomPanel.add(dumpStackTraceButton); + JButton dumpStackTracesWithQuantitiesButton = new JButton("Dump stack traces with quantities"); + dumpStackTracesWithQuantitiesButton.addActionListener(e -> { + if (selectedTick == null) { + return; + } + LinkedHashMap map = new LinkedHashMap<>(); + for (RandomCall call : selectedTick) { + map.computeIfAbsent(call, k -> new MutableInt(1)).add(1); + } + DebugRandom.LOGGER.info(String.join("\n\n", map.entrySet().stream().map(entry -> String.format("[x%d] %s", entry.getValue().getValue(), DebugRandom.stackTraceById.get(entry.getKey().stackTrace()))).toArray(String[]::new))); + }); + bottomPanel.add(dumpStackTracesWithQuantitiesButton); add(bottomPanel, BorderLayout.SOUTH); } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index ec1169c12..3725711f4 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -45,6 +45,12 @@ "commands.ccrackrng.starting": "Cracking player seed", "commands.ccrackrng.success": "Player RNG cracked: %d", + "commands.cvillager.notAVillager": "Target was not a villager", + "commands.cvillager.targetSet": "Target set", + "commands.cvillager.timerSet": "Timer block position set to %d %d %d", + "commands.cvillager.crackFailed": "Failed to crack villager seed", + "commands.cvillager.crackSuccess": "Successfully cracked villager seed: %d", + "commands.ccreativetab.addStack.success": "Successfully added %s to \"%s\"", "commands.ccreativetab.addTab.alreadyExists": "Creative tab \"%s\" already exists", "commands.ccreativetab.addTab.illegalCharacter": "Creative tab can only contain [a-z0-9/._-] characters", diff --git a/src/main/resources/mixins.clientcommands.json b/src/main/resources/mixins.clientcommands.json index b3f0481d0..c201c2628 100644 --- a/src/main/resources/mixins.clientcommands.json +++ b/src/main/resources/mixins.clientcommands.json @@ -22,6 +22,7 @@ "commands.relog.ClientPacketListenerMixin", "commands.render.EntityRendererDispatcherMixin", "commands.time.ClientLevelDataMixin", + "commands.villager.VillagerMixin", "commands.weather.LevelMixin", "debug.EntityMixin", "debug.ServerLevelMixin", @@ -43,13 +44,11 @@ "rngevents.ItemStackMixin", "rngevents.LivingEntityMixin", "rngevents.LocalPlayerMixin", - "rngevents.LocateHidingPlaceMixin", "rngevents.MultiPlayerGameModeMixin", "rngevents.PlayerMixin", "rngevents.PumpkinBlockMixin", "rngevents.ServerboundContainerClosePacketMixin", "rngevents.ShearsItemMixin", - "rngevents.VillageBoundRandomStrollMixin", "rngevents.droppableinventory.CartographyTableMenuMixin", "rngevents.droppableinventory.CraftingMenuMixin", "rngevents.droppableinventory.EnchantmentMenuMixin", From fe4133a6ce3524fb90cde401aca61539113fb892 Mon Sep 17 00:00:00 2001 From: RTTV Date: Fri, 31 May 2024 14:55:45 -0400 Subject: [PATCH 03/78] ok, now that it's been held on to, i can try to predict it, but for some reason it's not working, idk why --- .../command/VillagerCommand.java | 19 ++- .../features/VillagerCracker.java | 2 +- .../features/VillagerRngSimulator.java | 122 ++++++++++++++++-- .../commands/villager/VillagerMixin.java | 87 +++++++++++-- .../rngevents/ClientPacketListenerMixin.java | 4 +- .../assets/clientcommands/lang/en_us.json | 7 +- 6 files changed, 201 insertions(+), 40 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index cf4e3a4c4..9db385ac4 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -6,7 +6,6 @@ import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.client.Minecraft; import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; @@ -22,17 +21,17 @@ public class VillagerCommand { public static void register(CommandDispatcher dispatcher) { dispatcher.register( literal("cvillager") - .then(literal("timer") - .then(argument("value", blockPos()) - .executes(ctx -> setTimerBlockPos(ctx.getSource(), getBlockPos(ctx, "value"))))) + .then(literal("clock") + .then(argument("pos", blockPos()) + .executes(ctx -> setClockBlockPos(ctx.getSource(), getBlockPos(ctx, "pos"))))) .then(literal("target") - .then(argument("value", entity()) - .executes(ctx -> setVillagerTarget(ctx.getSource(), getEntity(ctx, "value")))))); + .then(argument("entity", entity()) + .executes(ctx -> setVillagerTarget(ctx.getSource(), getEntity(ctx, "entity")))))); } - private static int setTimerBlockPos(FabricClientCommandSource source, BlockPos pos) { - VillagerCracker.timerBlockPos = pos; - Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.timerSet", pos.getX(), pos.getY(), pos.getZ())); + private static int setClockBlockPos(FabricClientCommandSource source, BlockPos pos) { + VillagerCracker.clockBlockPos = pos; + source.getPlayer().sendSystemMessage(Component.translatable("commands.cvillager.clockSet", pos.getX(), pos.getY(), pos.getZ())); return Command.SINGLE_SUCCESS; } @@ -42,7 +41,7 @@ private static int setVillagerTarget(FabricClientCommandSource source, Entity ta } VillagerCracker.setTargetVillager(villager); - Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.targetSet")); + source.getPlayer().sendSystemMessage(Component.translatable("commands.cvillager.targetSet")); return Command.SINGLE_SUCCESS; } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index a136d5663..b932ac03f 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -21,7 +21,7 @@ public class VillagerCracker { private static WeakReference cachedVillager = null; @Nullable - public static BlockPos timerBlockPos = null; + public static BlockPos clockBlockPos = null; @Nullable public static Villager getVillager() { diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 9829e6dbf..764eb6499 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -1,12 +1,31 @@ package net.earthcomputer.clientcommands.features; +import com.mojang.logging.LogUtils; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.VillagerData; +import net.minecraft.world.entity.npc.VillagerTrades; +import net.minecraft.world.item.trading.MerchantOffer; +import net.minecraft.world.item.trading.MerchantOffers; import net.minecraft.world.level.levelgen.LegacyRandomSource; import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; + +import java.util.ArrayList; +import java.util.List; public class VillagerRngSimulator { + private static final Logger LOGGER = LogUtils.getLogger(); + @Nullable - private final LegacyRandomSource random; + private LegacyRandomSource random; private int ambientSoundTime; + private int waitingTicks = 0; + private boolean madeSound = false; + private boolean firstAmbientNoise = true; public VillagerRngSimulator(@Nullable LegacyRandomSource random, int ambientSoundTime) { this.random = random; @@ -14,18 +33,28 @@ public VillagerRngSimulator(@Nullable LegacyRandomSource random, int ambientSoun } @Override - protected Object clone() { - return new VillagerRngSimulator(random == null ? null : new LegacyRandomSource(random.seed.get() ^ 0x5deece66dL), ambientSoundTime); + public VillagerRngSimulator clone() { + VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : new LegacyRandomSource(random.seed.get() ^ 0x5deece66dL), ambientSoundTime); + that.waitingTicks = this.waitingTicks; + that.madeSound = this.madeSound; + that.firstAmbientNoise = this.firstAmbientNoise; + return that; } - public boolean simulateTick() { - boolean madeSound; + public void simulateTick() { + if (waitingTicks > 0) { + waitingTicks--; + return; + } + + LOGGER.info("Client (pre-tick): {}", this); if (random == null) { - return false; + return; } - if (random.nextInt(1000) < ambientSoundTime++) { + // we have the server receiving ambient noise tell us if we have to do this to increment the random, this is so that our ambient sound time is synced up. + if (random.nextInt(1000) < ambientSoundTime++ && !firstAmbientNoise) { random.nextFloat(); random.nextFloat(); ambientSoundTime = -80; @@ -34,15 +63,47 @@ public boolean simulateTick() { madeSound = false; } - return madeSound; + random.nextInt(100); + } + + @Nullable + public MerchantOffers simulateTrades(Villager villager) { + VillagerData villagerData = villager.getVillagerData(); + Int2ObjectMap map = VillagerTrades.TRADES.get(villagerData.getProfession()); + + if (map == null || map.isEmpty()) { + return null; + } + + return simulateOffers(map.get(villagerData.getLevel()), villager); } - public LegacyRandomSource random() { + private MerchantOffers simulateOffers(VillagerTrades.ItemListing[] listings, Entity trader) { + if (random == null) { + return null; + } + + MerchantOffers offers = new MerchantOffers(); + ArrayList newListings = new ArrayList<>(List.of(listings)); + int i = 0; + while (i < 2 && !newListings.isEmpty()) { + VillagerTrades.ItemListing listing = newListings.remove(random.nextInt(newListings.size())); + MerchantOffer offer = listing.getOffer(trader, random); + if (offer != null) { + offers.add(offer); + i++; + } + } + return offers; + } + + @Nullable + public LegacyRandomSource getRandom() { return random; } - public int getAmbientSoundTime() { - return ambientSoundTime; + public void setRandom(@Nullable LegacyRandomSource random) { + this.random = random; } @Override @@ -53,10 +114,45 @@ public String toString() { } public void onAmbientSoundPlayed() { - ambientSoundTime = -80; - if (random != null) { + if (firstAmbientNoise) { + if (random == null) { + return; + } + + firstAmbientNoise = false; + ambientSoundTime = -80; random.nextFloat(); random.nextFloat(); + madeSound = true; + } + + // is in sync + if (madeSound) { + Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.perfectlyInSync")); + return; + } + + // is not in sync, needs to be re-synced + VillagerRngSimulator clone = clone(); + int i = 0; + while (!clone.madeSound) { + i++; + clone.simulateTick(); + } + // todo, use ping if it's meant to be used (the idea here is to sync up to when the server says the villager makes a noise) + if (0 < i && i < 30) { + // in this case, it's a believable jump that we're less than 30 ticks behind, so we'll advance by the amount we calculated to be what this tick should've been + Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.tooManyTicksBehind", i)); + this.random = clone.random; + this.ambientSoundTime = clone.ambientSoundTime; + this.waitingTicks = clone.waitingTicks; + this.madeSound = clone.madeSound; + } else if (i > 30) { + // in this case, it took so many ticks to advance to rsync, that it's safe to assume we are ahead of the server, so we'll let the server catch up by 30 ticks + Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.tooManyTicksAhead")); + waitingTicks += 30; + } else { + Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.perfectlyInSync")); } } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index 7d8a5e138..3acdd61e1 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -1,27 +1,47 @@ package net.earthcomputer.clientcommands.mixin.commands.villager; +import com.mojang.logging.LogUtils; +import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; -import net.minecraft.client.Minecraft; +import net.minecraft.client.resources.language.I18n; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.npc.AbstractVillager; import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.trading.MerchantOffer; +import net.minecraft.world.item.trading.MerchantOffers; +import net.minecraft.world.level.Level; import net.minecraft.world.level.levelgen.LegacyRandomSource; +import org.slf4j.Logger; 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 java.util.stream.Collectors; @Mixin(Villager.class) -public class VillagerMixin implements IVillager { +public abstract class VillagerMixin extends AbstractVillager implements IVillager { @Unique - VillagerRngSimulator rng = new VillagerRngSimulator(null, 0); + private static final Logger LOGGER = LogUtils.getLogger(); + + public VillagerMixin(EntityType entityType, Level level) { + super(entityType, level); + } @Unique - boolean hasSetCrackedAmbientSoundTime = false; + VillagerRngSimulator rng = new VillagerRngSimulator(null, -80); @Override public void clientcommands_setCrackedRandom(RandomSource random) { - rng = new VillagerRngSimulator((LegacyRandomSource) random, rng.getAmbientSoundTime()); - hasSetCrackedAmbientSoundTime = false; + rng.setRandom((LegacyRandomSource) random); } @Override @@ -31,16 +51,59 @@ public VillagerRngSimulator clientcommands_getCrackedRandom() { @Override public void clientcommands_onAmbientSoundPlayed() { - if (!hasSetCrackedAmbientSoundTime) { - rng.onAmbientSoundPlayed(); - } + rng.onAmbientSoundPlayed(); } @Override public void clientcommands_onServerTick() { - if (rng.simulateTick()) { - hasSetCrackedAmbientSoundTime = true; - Minecraft.getInstance().player.sendSystemMessage(Component.literal("hrmm")); + rng.simulateTick(); + } + + @Inject(method = "updateTrades", at = @At("HEAD")) + public void onUpdateTrades(CallbackInfo ci) { + if (!level().isClientSide) { + LOGGER.info("Server Seed (b4 trade): {}", ((LegacyRandomSource) random).seed.get()); + + Villager targetVillager = VillagerCracker.getVillager(); + if (targetVillager != null && this.getUUID().equals(targetVillager.getUUID()) && ((IVillager) targetVillager).clientcommands_getCrackedRandom() != null) { + VillagerRngSimulator randomBranch = ((IVillager) targetVillager).clientcommands_getCrackedRandom().clone(); + LOGGER.info("Client Seed (pre-interact): {}", randomBranch); + randomBranch.simulateTick(); + LOGGER.info("Client Seed (post-tick): {}", randomBranch); + targetVillager.setVillagerData(targetVillager.getVillagerData().setProfession(VillagerProfession.LIBRARIAN)); + MerchantOffers offers = randomBranch.simulateTrades(targetVillager); + targetVillager.setVillagerData(targetVillager.getVillagerData().setProfession(VillagerProfession.NONE)); + if (offers == null) { + return; + } + for (MerchantOffer offer : offers) { + if (offer.getItemCostB().isPresent()) { + LOGGER.info("[x{}] {} + [x{}] {} = [x{}] {} ({})", + offer.getItemCostA().count(), + Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostA().item().value()).getPath()).getString(), + offer.getItemCostB().get().count(), + Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostB().get().item().value()).getPath()).getString(), + offer.getResult().getCount(), + I18n.get(BuiltInRegistries.ITEM.getKey(offer.getResult().getItem()).getPath()), + offer.getResult().getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL).stream().map(Component::getString).skip(1).collect(Collectors.joining(", "))); + } else { + LOGGER.info("[x{}] {} = [x{}] {} ({})", + offer.getItemCostA().count(), + Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostA().item().value()).getPath()).getString(), + offer.getResult().getCount(), + Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getResult().getItem()).getPath()).getString(), + offer.getResult().getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL).stream().map(Component::getString).skip(1).collect(Collectors.joining(", "))); + } + } + LOGGER.info("Client Seed (post-interact): {}", randomBranch); + } + } + } + + @Inject(method = "tick", at = @At("HEAD")) + private void startTick(CallbackInfo ci) { + if (!level().isClientSide) { + LOGGER.info("Server Seed (pre-tick): {}", ((LegacyRandomSource) random).seed.get()); } } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java index 08ac67b41..ae7ee2a02 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java @@ -40,7 +40,7 @@ private void onHandleSoundEvent(ClientboundSoundPacket packet, CallbackInfo ci) @Inject(method = "handleBlockUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackInfo ci) { - if (packet.getPos().equals(VillagerCracker.timerBlockPos)) { + if (packet.getPos().equals(VillagerCracker.clockBlockPos)) { VillagerCracker.onServerTick(); } } @@ -48,7 +48,7 @@ private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackIn @Inject(method = "handleChunkBlocksUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) private void onHandleChunkBlocksUpdate(ClientboundSectionBlocksUpdatePacket packet, CallbackInfo ci) { packet.runUpdates((pos, state) -> { - if (pos.equals(VillagerCracker.timerBlockPos)) { + if (pos.equals(VillagerCracker.clockBlockPos)) { VillagerCracker.onServerTick(); } }); diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 3725711f4..b719b0311 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -46,10 +46,13 @@ "commands.ccrackrng.success": "Player RNG cracked: %d", "commands.cvillager.notAVillager": "Target was not a villager", - "commands.cvillager.targetSet": "Target set", - "commands.cvillager.timerSet": "Timer block position set to %d %d %d", + "commands.cvillager.targetSet": "Target entity set", + "commands.cvillager.clockSet": "Clock set to %d %d %d", "commands.cvillager.crackFailed": "Failed to crack villager seed", "commands.cvillager.crackSuccess": "Successfully cracked villager seed: %d", + "commands.cvillager.tooManyTicksAhead": "Was too many ticks ahead of villager cracking, awaiting the next 30 ticks of processing. Will likely need another ambient sound to resync", + "commands.cvillager.tooManyTicksBehind": "Was too many ticks behind of villager cracking, simulating by %d ticks, should be in sync.", + "commands.cvillager.perfectlyInSync": "Your villager's random is perfectly in sync", "commands.ccreativetab.addStack.success": "Successfully added %s to \"%s\"", "commands.ccreativetab.addTab.alreadyExists": "Creative tab \"%s\" already exists", From 800fd92b32eb0308ad83d373dcdaf2220b82f42f Mon Sep 17 00:00:00 2001 From: RTTV Date: Sat, 1 Jun 2024 18:06:21 -0400 Subject: [PATCH 04/78] ok now i can crack it, gotta figure out how to --- .../clientcommands/ClientCommands.java | 2 +- .../earthcomputer/clientcommands/Configs.java | 6 + .../command/VillagerCommand.java | 147 ++++++++++++++++-- .../arguments/PredicatedRangeArgument.java | 82 ++++++++++ .../features/VillagerCracker.java | 12 +- .../features/VillagerRngSimulator.java | 84 +++++----- .../clientcommands/interfaces/IVillager.java | 10 +- .../commands/villager/VillagerMixin.java | 118 +++++++------- .../assets/clientcommands/lang/en_us.json | 8 +- 9 files changed, 344 insertions(+), 125 deletions(-) create mode 100644 src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java diff --git a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java index ef179bac3..a4f8bd391 100644 --- a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java +++ b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java @@ -168,7 +168,7 @@ public static void registerCommands(CommandDispatcher UsageTreeCommand.register(dispatcher); UuidCommand.register(dispatcher); VarCommand.register(dispatcher); - VillagerCommand.register(dispatcher); + VillagerCommand.register(dispatcher, context); WeatherCommand.register(dispatcher); WhisperEncryptedCommand.register(dispatcher); WikiCommand.register(dispatcher); diff --git a/src/main/java/net/earthcomputer/clientcommands/Configs.java b/src/main/java/net/earthcomputer/clientcommands/Configs.java index 1af26d7a0..fbf073e36 100644 --- a/src/main/java/net/earthcomputer/clientcommands/Configs.java +++ b/src/main/java/net/earthcomputer/clientcommands/Configs.java @@ -169,4 +169,10 @@ public enum PacketDumpMethod { @Config public static int maximumPacketFieldDepth = 10; + + @Config(temporary = true, setter = @Config.Setter("setMaxVillagerSimulationTicks")) + public static int maxVillagerSimulationTicks = 16384; + public static void setMaxVillagerSimulationTicks(int maxVillagerSimulationTicks) { + Configs.maxVillagerSimulationTicks = Mth.clamp(maxVillagerSimulationTicks, 0, 65536); + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 9db385ac4..f4271d9ba 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -4,45 +4,162 @@ import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; +import com.mojang.logging.LogUtils; +import net.earthcomputer.clientcommands.Configs; +import net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument; +import net.earthcomputer.clientcommands.command.arguments.WithStringArgument; +import net.earthcomputer.clientcommands.features.FishingCracker; import net.earthcomputer.clientcommands.features.VillagerCracker; +import net.earthcomputer.clientcommands.interfaces.IVillager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.ChatFormatting; +import net.minecraft.advancements.critereon.MinMaxBounds; +import net.minecraft.commands.CommandBuildContext; import net.minecraft.core.BlockPos; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.ai.village.poi.PoiTypes; import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.entity.npc.VillagerTrades; +import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; import static dev.xpple.clientarguments.arguments.CBlockPosArgument.*; import static dev.xpple.clientarguments.arguments.CEntityArgument.*; +import static dev.xpple.clientarguments.arguments.CItemPredicateArgument.*; +import static net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument.*; +import static net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument.Ints.*; +import static net.earthcomputer.clientcommands.command.arguments.WithStringArgument.*; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; public class VillagerCommand { private static final SimpleCommandExceptionType NOT_A_VILLAGER_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notAVillager")); + private static final SimpleCommandExceptionType SELECTED_ITEM_NOT_WORKSTATION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.selected_item_not_workstation")); + private static final SimpleCommandExceptionType NO_CRACKED_VILLAGER_PRESENT = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.no_cracked_villager_present")); + public static final List goals = new ArrayList<>(); - public static void register(CommandDispatcher dispatcher) { - dispatcher.register( - literal("cvillager") - .then(literal("clock") - .then(argument("pos", blockPos()) - .executes(ctx -> setClockBlockPos(ctx.getSource(), getBlockPos(ctx, "pos"))))) - .then(literal("target") - .then(argument("entity", entity()) - .executes(ctx -> setVillagerTarget(ctx.getSource(), getEntity(ctx, "entity")))))); + public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { + dispatcher.register(literal("cvillager") + .then(literal("add-goal") + .then(argument("first-item", withString(itemPredicate(context))) + .then(argument("first-item-quantity", withString(intRange(1, 64))) + .then(argument("result-item", withString(itemPredicate(context))) + .then(argument("result-item-quantity", withString(intRange(1, 64))) + .executes(ctx -> addGoal(getWithString(ctx, "first-item", CItemStackPredicateArgument.class), getWithString(ctx, "first-item-quantity", MinMaxBounds.Ints.class), null, null, getWithString(ctx, "result-item", CItemStackPredicateArgument.class), getWithString(ctx, "result-item-quantity", MinMaxBounds.Ints.class)))))))) + .then(literal("add-three-item-goal") + .then(argument("first-item", withString(itemPredicate(context))) + .then(argument("first-item-quantity", withString(intRange(1, 64))) + .then(argument("second-item", withString(itemPredicate(context))) + .then(argument("second-item-quantity", withString(intRange(1, 64))) + .then(argument("result-item", withString(itemPredicate(context))) + .then(argument("result-item-quantity", withString(intRange(1, 64))) + .executes(ctx -> addGoal(getWithString(ctx, "first-item", CItemStackPredicateArgument.class), getWithString(ctx, "first-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "second-item", CItemStackPredicateArgument.class), getWithString(ctx, "second-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "result-item", CItemStackPredicateArgument.class), getWithString(ctx, "result-item-quantity", MinMaxBounds.Ints.class)))))))))) + .then(literal("list-goals") + .executes(ctx -> listGoals(ctx.getSource()))) + .then(literal("clock") + .then(argument("pos", blockPos()) + .executes(ctx -> setClockBlockPos(getBlockPos(ctx, "pos"))))) + .then(literal("target") + .executes(ctx -> setVillagerTarget(null)) + .then(argument("entity", entity()) + .executes(ctx -> setVillagerTarget(getEntity(ctx, "entity"))))) + .then(literal("crack") + .executes(ctx -> crack(ctx.getSource())))); } - private static int setClockBlockPos(FabricClientCommandSource source, BlockPos pos) { + private static int setClockBlockPos(BlockPos pos) { VillagerCracker.clockBlockPos = pos; - source.getPlayer().sendSystemMessage(Component.translatable("commands.cvillager.clockSet", pos.getX(), pos.getY(), pos.getZ())); + ClientCommandHelper.sendFeedback("commands.cvillager.clockSet", pos.getX(), pos.getY(), pos.getZ()); return Command.SINGLE_SUCCESS; } - private static int setVillagerTarget(FabricClientCommandSource source, Entity target) throws CommandSyntaxException { - if (!(target instanceof Villager villager)) { + private static int setVillagerTarget(@Nullable Entity target) throws CommandSyntaxException { + if (!(target instanceof Villager) && target != null) { throw NOT_A_VILLAGER_EXCEPTION.create(); } - VillagerCracker.setTargetVillager(villager); - source.getPlayer().sendSystemMessage(Component.translatable("commands.cvillager.targetSet")); + VillagerCracker.setTargetVillager((Villager) target); + if (target == null) { + ClientCommandHelper.sendFeedback("commands.cvillager.targetCleared"); + } else { + ClientCommandHelper.sendFeedback("commands.cvillager.targetSet"); + } + + return Command.SINGLE_SUCCESS; + } + + private static int listGoals(FabricClientCommandSource source) { + if (goals.isEmpty()) { + source.sendFeedback(Component.translatable("commands.cvillager.listGoals.noGoals").withStyle(style -> style.withColor(ChatFormatting.RED))); + } else { + source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", FishingCracker.goals.size())); + for (int i = 0; i < goals.size(); i++) { + Goal goal = goals.get(i); + if (goal.secondPredicate != null) { + source.sendFeedback(Component.literal(String.format("%d: %s + %s = %s", i + 1, goal.firstString, goal.secondString, goal.resultString))); + } else { + source.sendFeedback(Component.literal(String.format("%d: %s = %s", i + 1, goal.firstString, goal.resultString))); + } + } + } + return Command.SINGLE_SUCCESS; + } + + private static int crack(FabricClientCommandSource source) throws CommandSyntaxException { + Villager targetVillager = VillagerCracker.getVillager(); + + if (!(targetVillager instanceof IVillager iVillager) || iVillager.clientcommands_getCrackedRandom() == null) { + throw NO_CRACKED_VILLAGER_PRESENT.create(); + } + + ItemStack selectedItem = source.getPlayer().getInventory().getSelected(); + if (selectedItem.getItem() instanceof BlockItem blockItem) { + VillagerProfession profession = PoiTypes.forState(blockItem.getBlock().defaultBlockState()) + .flatMap(poi -> BuiltInRegistries.VILLAGER_PROFESSION.stream().filter(p -> p.heldJobSite().test(poi)).findAny()) + .orElseThrow(SELECTED_ITEM_NOT_WORKSTATION::create); + VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(1, new VillagerTrades.ItemListing[0]); + int i = iVillager.clientcommands_bruteForceOffers(listings, profession, Configs.maxVillagerSimulationTicks, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))); + if (i == -1) { + LogUtils.getLogger().info("Could not find any matches"); + } else { + LogUtils.getLogger().info("Found a match at {} ticks in", i); + } + } else { + throw SELECTED_ITEM_NOT_WORKSTATION.create(); + } + + return Command.SINGLE_SUCCESS; + } + + private static int addGoal(WithStringArgument.Result firstPredicate, WithStringArgument.Result firstItemQuantityRange, @Nullable WithStringArgument.Result secondPredicate, @Nullable WithStringArgument.Result secondItemQuantityRange, WithStringArgument.Result resultPredicate, WithStringArgument.Result resultItemQuantityRange) { + goals.add(new Goal( + String.format("[%s] %s", firstItemQuantityRange.string(), firstPredicate.string()), + item -> firstPredicate.value().test(item) && firstItemQuantityRange.value().matches(item.getCount()), + + secondPredicate == null ? null : String.format("[%s] %s", secondItemQuantityRange.string(), secondPredicate.string()), + secondPredicate == null ? null : item -> secondPredicate.value().test(item) && secondItemQuantityRange.value().matches(item.getCount()), + + String.format("[%s] %s", resultItemQuantityRange.string(), resultPredicate.string()), + item -> resultPredicate.value().test(item) && resultItemQuantityRange.value().matches(item.getCount()))); + ClientCommandHelper.sendFeedback("commands.cvillager.goalAdded"); return Command.SINGLE_SUCCESS; } + + public record Goal(String firstString, Predicate firstPredicate, @Nullable String secondString, @Nullable Predicate secondPredicate, String resultString, Predicate resultPredicate) { + public boolean matches(ItemStack firstItem, @Nullable ItemStack secondItem, ItemStack result) { + return firstPredicate.test(firstItem) + && ((secondPredicate == null && secondItem == null) || secondItem != null && secondPredicate != null && secondPredicate.test(secondItem)) + && resultPredicate.test(result); + } + } + + public record Offer(ItemStack first, @Nullable ItemStack second, ItemStack result) {} } diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java new file mode 100644 index 000000000..81cb1d3d5 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java @@ -0,0 +1,82 @@ +package net.earthcomputer.clientcommands.command.arguments; + +import com.mojang.brigadier.StringReader; +import com.mojang.brigadier.arguments.ArgumentType; +import com.mojang.brigadier.context.CommandContext; +import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; +import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; +import net.minecraft.advancements.critereon.MinMaxBounds; +import net.minecraft.network.chat.Component; +import org.jetbrains.annotations.Nullable; + +public interface PredicatedRangeArgument> extends ArgumentType { + Dynamic2CommandExceptionType INTEGER_VALUE_TOO_LOW = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("argument.integer.low", a, b)); + Dynamic2CommandExceptionType INTEGER_VALUE_TOO_HIGH = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("argument.integer.low", a, b)); + Dynamic2CommandExceptionType FLOAT_VALUE_TOO_LOW = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("argument.float.low", a, b)); + Dynamic2CommandExceptionType FLOAT_VALUE_TOO_HIGH = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("argument.float.low", a, b)); + + static Ints intRange(@Nullable Integer min, @Nullable Integer max) { + return new Ints(min, max); + } + + static Floats floatRange(@Nullable Double min, @Nullable Double max) { + return new Floats(min, max); + } + + class Ints implements PredicatedRangeArgument { + @Nullable + private final Integer min; + @Nullable + private final Integer max; + + public Ints(@Nullable Integer min, @Nullable Integer max) { + this.min = min; + this.max = max; + } + + public static MinMaxBounds.Ints getRangeArgument(final CommandContext context, final String name) { + return context.getArgument(name, MinMaxBounds.Ints.class); + } + + @Override + public MinMaxBounds.Ints parse(StringReader reader) throws CommandSyntaxException { + MinMaxBounds.Ints range = MinMaxBounds.Ints.fromReader(reader); + if (min != null && (range.min().isEmpty() || range.min().get() < min)) { + throw INTEGER_VALUE_TOO_LOW.create(min, range.min().orElse(Integer.MIN_VALUE)); + } + if (max != null && (range.max().isEmpty() || range.max().get() > max)) { + throw INTEGER_VALUE_TOO_HIGH.create(max, range.max().orElse(Integer.MAX_VALUE)); + } + return range; + } + } + + class Floats implements PredicatedRangeArgument { + @Nullable + private final Double min; + @Nullable + private final Double max; + + public Floats(@Nullable Double min, @Nullable Double max) { + this.min = min; + this.max = max; + } + + public static MinMaxBounds.Doubles getRangeArgument(final CommandContext context, final String name) { + return context.getArgument(name, MinMaxBounds.Doubles.class); + } + + @Override + public MinMaxBounds.Doubles parse(StringReader reader) throws CommandSyntaxException { + MinMaxBounds.Doubles range = MinMaxBounds.Doubles.fromReader(reader); + if (min != null && (range.min().isEmpty() || range.min().get() < min)) { + throw FLOAT_VALUE_TOO_LOW.create(min, range.min().orElse(-Double.MAX_VALUE)); + } + if (max != null && (range.max().isEmpty() || range.max().get() < max)) { + throw FLOAT_VALUE_TOO_HIGH.create(max, range.max().orElse(Double.MAX_VALUE)); + } + return range; + } + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index b932ac03f..f5527531a 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -44,9 +44,14 @@ public static Villager getVillager() { return null; } - public static void setTargetVillager(Villager villager) { + public static void setTargetVillager(@Nullable Villager villager) { + Villager oldVillager = getVillager(); + if (oldVillager != null) { + ((IVillager) oldVillager).clientcommands_setCrackedRandom(null); + } + VillagerCracker.cachedVillager = new WeakReference<>(villager); - VillagerCracker.villagerUuid = villager.getUUID(); + VillagerCracker.villagerUuid = villager == null ? null : villager.getUUID(); } public static void onSoundEventPlayed(ClientboundSoundPacket packet) { @@ -62,7 +67,7 @@ public static void onSoundEventPlayed(ClientboundSoundPacket packet) { ClientCommandHelper.sendError(Component.translatable("commands.cvillager.crackFailed")); } else { ((IVillager) targetVillager).clientcommands_setCrackedRandom(RandomSource.create(possible[0] ^ 0x5deece66dL)); - Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.crackSuccess", Long.toHexString(possible[0]))); + ClientCommandHelper.sendFeedback("commands.cvillager.crackSuccess", Long.toHexString(possible[0])); } } @@ -79,4 +84,5 @@ public static void onServerTick() { ((IVillager) targetVillager).clientcommands_onServerTick(); } + } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 764eb6499..912b44d9b 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -1,25 +1,18 @@ package net.earthcomputer.clientcommands.features; -import com.mojang.logging.LogUtils; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; -import net.minecraft.client.Minecraft; -import net.minecraft.network.chat.Component; +import net.earthcomputer.clientcommands.command.ClientCommandHelper; +import net.earthcomputer.clientcommands.command.VillagerCommand; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.entity.npc.VillagerData; import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.item.trading.MerchantOffer; -import net.minecraft.world.item.trading.MerchantOffers; import net.minecraft.world.level.levelgen.LegacyRandomSource; import org.jetbrains.annotations.Nullable; -import org.slf4j.Logger; import java.util.ArrayList; import java.util.List; +import java.util.function.Predicate; public class VillagerRngSimulator { - private static final Logger LOGGER = LogUtils.getLogger(); - @Nullable private LegacyRandomSource random; private int ambientSoundTime; @@ -32,8 +25,7 @@ public VillagerRngSimulator(@Nullable LegacyRandomSource random, int ambientSoun this.ambientSoundTime = ambientSoundTime; } - @Override - public VillagerRngSimulator clone() { + public VillagerRngSimulator copy() { VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : new LegacyRandomSource(random.seed.get() ^ 0x5deece66dL), ambientSoundTime); that.waitingTicks = this.waitingTicks; that.madeSound = this.madeSound; @@ -42,13 +34,20 @@ public VillagerRngSimulator clone() { } public void simulateTick() { + if (random == null) { + return; + } + + simulateBaseTick(); + simulateServerAiStep(); + } + + public void simulateBaseTick() { if (waitingTicks > 0) { waitingTicks--; return; } - LOGGER.info("Client (pre-tick): {}", this); - if (random == null) { return; } @@ -62,39 +61,35 @@ public void simulateTick() { } else { madeSound = false; } - - random.nextInt(100); } - @Nullable - public MerchantOffers simulateTrades(Villager villager) { - VillagerData villagerData = villager.getVillagerData(); - Int2ObjectMap map = VillagerTrades.TRADES.get(villagerData.getProfession()); - - if (map == null || map.isEmpty()) { - return null; + public void simulateServerAiStep() { + if (random == null) { + return; } - return simulateOffers(map.get(villagerData.getLevel()), villager); + random.nextInt(100); } - private MerchantOffers simulateOffers(VillagerTrades.ItemListing[] listings, Entity trader) { - if (random == null) { - return null; + public boolean anyOffersMatch(VillagerTrades.ItemListing[] listings, Entity trader, Predicate predicate) { + if (!isCracked()) { + return false; } - MerchantOffers offers = new MerchantOffers(); ArrayList newListings = new ArrayList<>(List.of(listings)); int i = 0; while (i < 2 && !newListings.isEmpty()) { VillagerTrades.ItemListing listing = newListings.remove(random.nextInt(newListings.size())); MerchantOffer offer = listing.getOffer(trader, random); if (offer != null) { - offers.add(offer); - i++; + if (predicate.test(new VillagerCommand.Offer(offer.getBaseCostA(), offer.getCostB(), offer.getResult()))) { + return true; + } else { + i++; + } } } - return offers; + return false; } @Nullable @@ -102,6 +97,10 @@ public LegacyRandomSource getRandom() { return random; } + public boolean isCracked() { + return random != null && !firstAmbientNoise; + } + public void setRandom(@Nullable LegacyRandomSource random) { this.random = random; } @@ -128,31 +127,30 @@ public void onAmbientSoundPlayed() { // is in sync if (madeSound) { - Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.perfectlyInSync")); + ClientCommandHelper.sendFeedback("commands.cvillager.perfectlyInSync"); return; } // is not in sync, needs to be re-synced - VillagerRngSimulator clone = clone(); + VillagerRngSimulator copy = copy(); int i = 0; - while (!clone.madeSound) { + while (!copy.madeSound) { i++; - clone.simulateTick(); + copy.simulateTick(); } - // todo, use ping if it's meant to be used (the idea here is to sync up to when the server says the villager makes a noise) if (0 < i && i < 30) { // in this case, it's a believable jump that we're less than 30 ticks behind, so we'll advance by the amount we calculated to be what this tick should've been - Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.tooManyTicksBehind", i)); - this.random = clone.random; - this.ambientSoundTime = clone.ambientSoundTime; - this.waitingTicks = clone.waitingTicks; - this.madeSound = clone.madeSound; + ClientCommandHelper.sendFeedback("commands.cvillager.tooManyTicksBehind", i); + this.random = copy.random; + this.ambientSoundTime = copy.ambientSoundTime; + this.waitingTicks = copy.waitingTicks; + this.madeSound = copy.madeSound; } else if (i > 30) { // in this case, it took so many ticks to advance to rsync, that it's safe to assume we are ahead of the server, so we'll let the server catch up by 30 ticks - Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.tooManyTicksAhead")); + ClientCommandHelper.sendFeedback("commands.cvillager.tooManyTicksAhead"); waitingTicks += 30; } else { - Minecraft.getInstance().player.sendSystemMessage(Component.translatable("commands.cvillager.perfectlyInSync")); + ClientCommandHelper.sendFeedback("commands.cvillager.perfectlyInSync"); } } } diff --git a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java index 3cdeae936..ac97f03c1 100644 --- a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java +++ b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java @@ -1,14 +1,22 @@ package net.earthcomputer.clientcommands.interfaces; +import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.minecraft.util.RandomSource; +import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.entity.npc.VillagerTrades; +import org.jetbrains.annotations.Nullable; + +import java.util.function.Predicate; public interface IVillager { - void clientcommands_setCrackedRandom(RandomSource random); + void clientcommands_setCrackedRandom(@Nullable RandomSource random); VillagerRngSimulator clientcommands_getCrackedRandom(); void clientcommands_onAmbientSoundPlayed(); void clientcommands_onServerTick(); + + int clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int maxTicks, Predicate predicate); } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index 3acdd61e1..25383b166 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -1,36 +1,25 @@ package net.earthcomputer.clientcommands.mixin.commands.villager; -import com.mojang.logging.LogUtils; -import net.earthcomputer.clientcommands.features.VillagerCracker; +import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; -import net.minecraft.client.resources.language.I18n; -import net.minecraft.core.registries.BuiltInRegistries; -import net.minecraft.network.chat.Component; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.npc.AbstractVillager; -import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.entity.npc.VillagerProfession; -import net.minecraft.world.item.Item; -import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.trading.MerchantOffer; -import net.minecraft.world.item.trading.MerchantOffers; +import net.minecraft.world.entity.npc.*; import net.minecraft.world.level.Level; import net.minecraft.world.level.levelgen.LegacyRandomSource; -import org.slf4j.Logger; +import org.jetbrains.annotations.Nullable; 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.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.stream.Collectors; +import java.util.function.Predicate; @Mixin(Villager.class) public abstract class VillagerMixin extends AbstractVillager implements IVillager { - @Unique - private static final Logger LOGGER = LogUtils.getLogger(); + @Shadow public abstract VillagerData getVillagerData(); + + @Shadow public abstract void setVillagerData(VillagerData data); public VillagerMixin(EntityType entityType, Level level) { super(entityType, level); @@ -40,7 +29,7 @@ public VillagerMixin(EntityType entityType, Level le VillagerRngSimulator rng = new VillagerRngSimulator(null, -80); @Override - public void clientcommands_setCrackedRandom(RandomSource random) { + public void clientcommands_setCrackedRandom(@Nullable RandomSource random) { rng.setRandom((LegacyRandomSource) random); } @@ -54,56 +43,63 @@ public void clientcommands_onAmbientSoundPlayed() { rng.onAmbientSoundPlayed(); } +// public void clientcommands_onProfessionUpdate(VillagerProfession newProfession) { +// Villager targetVillager = VillagerCracker.getVillager(); +// if (targetVillager instanceof IVillager iVillager && iVillager.clientcommands_getCrackedRandom().isCracked()) { +// +// if (offers == null) { +// return; +// } +// for (MerchantOffer offer : offers) { +// if (offer.getItemCostB().isPresent()) { +// LOGGER.info("[x{}] {} + [x{}] {} = [x{}] {} ({})", +// offer.getItemCostA().count(), +// Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostA().item().value()).getPath()).getString(), +// offer.getItemCostB().get().count(), +// Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostB().get().item().value()).getPath()).getString(), +// offer.getResult().getCount(), +// I18n.get(BuiltInRegistries.ITEM.getKey(offer.getResult().getItem()).getPath()), +// offer.getResult().getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL).stream().map(Component::getString).skip(1).collect(Collectors.joining(", "))); +// } else { +// LOGGER.info("[x{}] {} = [x{}] {} ({})", +// offer.getItemCostA().count(), +// Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostA().item().value()).getPath()).getString(), +// offer.getResult().getCount(), +// Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getResult().getItem()).getPath()).getString(), +// offer.getResult().getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL).stream().map(Component::getString).skip(1).collect(Collectors.joining(", "))); +// } +// } +// } +// } + @Override public void clientcommands_onServerTick() { rng.simulateTick(); } - @Inject(method = "updateTrades", at = @At("HEAD")) - public void onUpdateTrades(CallbackInfo ci) { - if (!level().isClientSide) { - LOGGER.info("Server Seed (b4 trade): {}", ((LegacyRandomSource) random).seed.get()); + @Override + public int clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int maxTicks, Predicate predicate) { + if (this instanceof IVillager iVillager && iVillager.clientcommands_getCrackedRandom().isCracked()) { + VillagerProfession oldProfession = getVillagerData().getProfession(); + setVillagerData(getVillagerData().setProfession(profession)); - Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager != null && this.getUUID().equals(targetVillager.getUUID()) && ((IVillager) targetVillager).clientcommands_getCrackedRandom() != null) { - VillagerRngSimulator randomBranch = ((IVillager) targetVillager).clientcommands_getCrackedRandom().clone(); - LOGGER.info("Client Seed (pre-interact): {}", randomBranch); - randomBranch.simulateTick(); - LOGGER.info("Client Seed (post-tick): {}", randomBranch); - targetVillager.setVillagerData(targetVillager.getVillagerData().setProfession(VillagerProfession.LIBRARIAN)); - MerchantOffers offers = randomBranch.simulateTrades(targetVillager); - targetVillager.setVillagerData(targetVillager.getVillagerData().setProfession(VillagerProfession.NONE)); - if (offers == null) { - return; + VillagerRngSimulator rng = this.rng.copy(); + int i = 0; + while (i < maxTicks) { + VillagerRngSimulator randomBranch = rng.copy(); + randomBranch.simulateBaseTick(); + if (randomBranch.anyOffersMatch(listings, (Villager) (Object) this, predicate)) { + setVillagerData(getVillagerData().setProfession(oldProfession)); + return i; } - for (MerchantOffer offer : offers) { - if (offer.getItemCostB().isPresent()) { - LOGGER.info("[x{}] {} + [x{}] {} = [x{}] {} ({})", - offer.getItemCostA().count(), - Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostA().item().value()).getPath()).getString(), - offer.getItemCostB().get().count(), - Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostB().get().item().value()).getPath()).getString(), - offer.getResult().getCount(), - I18n.get(BuiltInRegistries.ITEM.getKey(offer.getResult().getItem()).getPath()), - offer.getResult().getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL).stream().map(Component::getString).skip(1).collect(Collectors.joining(", "))); - } else { - LOGGER.info("[x{}] {} = [x{}] {} ({})", - offer.getItemCostA().count(), - Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostA().item().value()).getPath()).getString(), - offer.getResult().getCount(), - Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getResult().getItem()).getPath()).getString(), - offer.getResult().getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL).stream().map(Component::getString).skip(1).collect(Collectors.joining(", "))); - } - } - LOGGER.info("Client Seed (post-interact): {}", randomBranch); + randomBranch.simulateServerAiStep(); + rng.simulateTick(); + i++; } - } - } - @Inject(method = "tick", at = @At("HEAD")) - private void startTick(CallbackInfo ci) { - if (!level().isClientSide) { - LOGGER.info("Server Seed (pre-tick): {}", ((LegacyRandomSource) random).seed.get()); + setVillagerData(getVillagerData().setProfession(oldProfession)); } + + return -1; } } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index b719b0311..10f63c68d 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -46,10 +46,16 @@ "commands.ccrackrng.success": "Player RNG cracked: %d", "commands.cvillager.notAVillager": "Target was not a villager", + "commands.cvillager.selected_item_not_workstation": "Your selected item was not a valid workstation block", + "commands.cvillager.no_cracked_villager_present": "There was no cracked villager available to use", + "commands.cvillager.listGoals.noGoals": "There are no villager goals.", + "commands.cvillager.listGoals.success": "There are %d villager goals:", "commands.cvillager.targetSet": "Target entity set", + "commands.cvillager.targetCleared": "Target entity cleared", "commands.cvillager.clockSet": "Clock set to %d %d %d", "commands.cvillager.crackFailed": "Failed to crack villager seed", - "commands.cvillager.crackSuccess": "Successfully cracked villager seed: %d", + "commands.cvillager.crackSuccess": "Villager RNG cracked: %d", + "commands.cvillager.goalAdded": "Added goal successfully.", "commands.cvillager.tooManyTicksAhead": "Was too many ticks ahead of villager cracking, awaiting the next 30 ticks of processing. Will likely need another ambient sound to resync", "commands.cvillager.tooManyTicksBehind": "Was too many ticks behind of villager cracking, simulating by %d ticks, should be in sync.", "commands.cvillager.perfectlyInSync": "Your villager's random is perfectly in sync", From 5fcbf158d30a51ea217e41d4bc2e8d9b99777294 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sun, 2 Jun 2024 15:19:23 -0400 Subject: [PATCH 05/78] ok, now it works - i need to fix for ping tho - i can probably remove the clock requirement and use the day/night packets --- .../earthcomputer/clientcommands/Configs.java | 11 +- .../command/ClientCommandHelper.java | 15 ++ .../command/VillagerCommand.java | 146 +++++++++++------- .../features/EnchantmentCracker.java | 15 +- .../features/VillagerRngSimulator.java | 95 ++++++++---- .../clientcommands/interfaces/IVillager.java | 3 +- .../commands/villager/VillagerMixin.java | 75 ++++----- .../assets/clientcommands/lang/en_us.json | 22 +-- 8 files changed, 221 insertions(+), 161 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/Configs.java b/src/main/java/net/earthcomputer/clientcommands/Configs.java index fbf073e36..60b03797d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/Configs.java +++ b/src/main/java/net/earthcomputer/clientcommands/Configs.java @@ -170,9 +170,12 @@ public enum PacketDumpMethod { @Config public static int maximumPacketFieldDepth = 10; - @Config(temporary = true, setter = @Config.Setter("setMaxVillagerSimulationTicks")) - public static int maxVillagerSimulationTicks = 16384; - public static void setMaxVillagerSimulationTicks(int maxVillagerSimulationTicks) { - Configs.maxVillagerSimulationTicks = Mth.clamp(maxVillagerSimulationTicks, 0, 65536); + @Config(temporary = true, setter = @Config.Setter("setMaxVillagerBruteForceSimulationCalls")) + public static int maxVillagerBruteForceSimulationCalls = 16384; + public static void setMaxVillagerBruteForceSimulationCalls(int maxVillagerBruteForceSimulationCalls) { + Configs.maxVillagerBruteForceSimulationCalls = Mth.clamp(maxVillagerBruteForceSimulationCalls, 0, 65536); } + + @Config(temporary = true) + public static int villagerAdjustment = 1; } diff --git a/src/main/java/net/earthcomputer/clientcommands/command/ClientCommandHelper.java b/src/main/java/net/earthcomputer/clientcommands/command/ClientCommandHelper.java index 676a39eb2..96e5a2103 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/ClientCommandHelper.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/ClientCommandHelper.java @@ -12,6 +12,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.chat.HoverEvent; import net.minecraft.network.chat.MutableComponent; +import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; import java.util.HashMap; @@ -101,4 +102,18 @@ public static String registerCode(Runnable code) { runnables.put(randomString, code); return randomString; } + + public static void updateOverlayProgressBar(int current, int total, int width, int time) { + MutableComponent builder = Component.empty(); + int color = Mth.hsvToRgb(current / (total * 3.0f), 1.0f, 1.0f); + builder.append(Component.literal("[").withColor(0xAAAAAA)); + builder.append(Component.literal("~" + Math.round(100.0 * current / total) + "%").withColor(color)); + builder.append(Component.literal("] ").withColor(0xAAAAAA)); + int filledWidth = (int) Math.round((double) width * current / total); + int unfilledWidth = width - filledWidth; + builder.append(Component.literal("|".repeat(filledWidth)).withColor(color)); + builder.append(Component.literal("|".repeat(unfilledWidth)).withColor(0xAAAAAA)); + + addOverlayMessage(builder, time); + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index f4271d9ba..9871074ee 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -3,10 +3,10 @@ import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; import com.mojang.brigadier.exceptions.CommandSyntaxException; +import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import com.mojang.logging.LogUtils; +import com.mojang.datafixers.util.Pair; import net.earthcomputer.clientcommands.Configs; -import net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument; import net.earthcomputer.clientcommands.command.arguments.WithStringArgument; import net.earthcomputer.clientcommands.features.FishingCracker; import net.earthcomputer.clientcommands.features.VillagerCracker; @@ -16,33 +16,33 @@ import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.commands.CommandBuildContext; import net.minecraft.core.BlockPos; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.ai.village.poi.PoiTypes; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.VillagerProfession; import net.minecraft.world.entity.npc.VillagerTrades; -import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; +import java.util.stream.Collectors; +import static com.mojang.brigadier.arguments.IntegerArgumentType.*; import static dev.xpple.clientarguments.arguments.CBlockPosArgument.*; import static dev.xpple.clientarguments.arguments.CEntityArgument.*; import static dev.xpple.clientarguments.arguments.CItemPredicateArgument.*; import static net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument.*; -import static net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument.Ints.*; import static net.earthcomputer.clientcommands.command.arguments.WithStringArgument.*; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; public class VillagerCommand { private static final SimpleCommandExceptionType NOT_A_VILLAGER_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notAVillager")); - private static final SimpleCommandExceptionType SELECTED_ITEM_NOT_WORKSTATION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.selected_item_not_workstation")); private static final SimpleCommandExceptionType NO_CRACKED_VILLAGER_PRESENT = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.no_cracked_villager_present")); + private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); public static final List goals = new ArrayList<>(); public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { @@ -63,6 +63,9 @@ public static void register(CommandDispatcher dispatc .executes(ctx -> addGoal(getWithString(ctx, "first-item", CItemStackPredicateArgument.class), getWithString(ctx, "first-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "second-item", CItemStackPredicateArgument.class), getWithString(ctx, "second-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "result-item", CItemStackPredicateArgument.class), getWithString(ctx, "result-item-quantity", MinMaxBounds.Ints.class)))))))))) .then(literal("list-goals") .executes(ctx -> listGoals(ctx.getSource()))) + .then(literal("remove-goal") + .then(argument("index", integer(0)) + .executes(ctx -> removeGoal(ctx.getSource(), getInteger(ctx, "index"))))) .then(literal("clock") .then(argument("pos", blockPos()) .executes(ctx -> setClockBlockPos(getBlockPos(ctx, "pos"))))) @@ -70,27 +73,21 @@ public static void register(CommandDispatcher dispatc .executes(ctx -> setVillagerTarget(null)) .then(argument("entity", entity()) .executes(ctx -> setVillagerTarget(getEntity(ctx, "entity"))))) - .then(literal("crack") - .executes(ctx -> crack(ctx.getSource())))); + .then(literal("brute-force") + .executes(ctx -> bruteForce()))); } - private static int setClockBlockPos(BlockPos pos) { - VillagerCracker.clockBlockPos = pos; - ClientCommandHelper.sendFeedback("commands.cvillager.clockSet", pos.getX(), pos.getY(), pos.getZ()); - return Command.SINGLE_SUCCESS; - } + private static int addGoal(WithStringArgument.Result firstPredicate, WithStringArgument.Result firstItemQuantityRange, @Nullable WithStringArgument.Result secondPredicate, @Nullable WithStringArgument.Result secondItemQuantityRange, WithStringArgument.Result resultPredicate, WithStringArgument.Result resultItemQuantityRange) { + goals.add(new Goal( + String.format("%s %s", firstItemQuantityRange.string(), firstPredicate.string()), + item -> firstPredicate.value().test(item) && firstItemQuantityRange.value().matches(item.getCount()), - private static int setVillagerTarget(@Nullable Entity target) throws CommandSyntaxException { - if (!(target instanceof Villager) && target != null) { - throw NOT_A_VILLAGER_EXCEPTION.create(); - } + secondPredicate == null ? null : String.format("%s %s", secondItemQuantityRange.string(), secondPredicate.string()), + secondPredicate == null ? null : item -> secondPredicate.value().test(item) && secondItemQuantityRange.value().matches(item.getCount()), - VillagerCracker.setTargetVillager((Villager) target); - if (target == null) { - ClientCommandHelper.sendFeedback("commands.cvillager.targetCleared"); - } else { - ClientCommandHelper.sendFeedback("commands.cvillager.targetSet"); - } + String.format("%s %s", resultItemQuantityRange.string(), resultPredicate.string()), + item -> resultPredicate.value().test(item) && resultItemQuantityRange.value().matches(item.getCount()))); + ClientCommandHelper.sendFeedback("commands.cvillager.goalAdded"); return Command.SINGLE_SUCCESS; } @@ -102,53 +99,61 @@ private static int listGoals(FabricClientCommandSource source) { source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", FishingCracker.goals.size())); for (int i = 0; i < goals.size(); i++) { Goal goal = goals.get(i); - if (goal.secondPredicate != null) { - source.sendFeedback(Component.literal(String.format("%d: %s + %s = %s", i + 1, goal.firstString, goal.secondString, goal.resultString))); - } else { - source.sendFeedback(Component.literal(String.format("%d: %s = %s", i + 1, goal.firstString, goal.resultString))); - } + source.sendFeedback(Component.literal((i + 1) + ": " + goal.toString())); } } return Command.SINGLE_SUCCESS; } - private static int crack(FabricClientCommandSource source) throws CommandSyntaxException { - Villager targetVillager = VillagerCracker.getVillager(); + private static int removeGoal(FabricClientCommandSource source, int index) throws CommandSyntaxException { + if (index < goals.size()) { + Goal goal = goals.remove(index); + source.sendFeedback(Component.translatable("commands.cvillager.removeGoal.success", goal.toString())); + } else { + throw INVALID_GOAL_INDEX.create(index, goals.size()); + } + return Command.SINGLE_SUCCESS; + } - if (!(targetVillager instanceof IVillager iVillager) || iVillager.clientcommands_getCrackedRandom() == null) { - throw NO_CRACKED_VILLAGER_PRESENT.create(); + private static int setClockBlockPos(BlockPos pos) { + VillagerCracker.clockBlockPos = pos; + ClientCommandHelper.sendFeedback("commands.cvillager.clockSet", pos.getX(), pos.getY(), pos.getZ()); + return Command.SINGLE_SUCCESS; + } + + private static int setVillagerTarget(@Nullable Entity target) throws CommandSyntaxException { + if (!(target instanceof Villager) && target != null) { + throw NOT_A_VILLAGER_EXCEPTION.create(); } - ItemStack selectedItem = source.getPlayer().getInventory().getSelected(); - if (selectedItem.getItem() instanceof BlockItem blockItem) { - VillagerProfession profession = PoiTypes.forState(blockItem.getBlock().defaultBlockState()) - .flatMap(poi -> BuiltInRegistries.VILLAGER_PROFESSION.stream().filter(p -> p.heldJobSite().test(poi)).findAny()) - .orElseThrow(SELECTED_ITEM_NOT_WORKSTATION::create); - VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(1, new VillagerTrades.ItemListing[0]); - int i = iVillager.clientcommands_bruteForceOffers(listings, profession, Configs.maxVillagerSimulationTicks, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))); - if (i == -1) { - LogUtils.getLogger().info("Could not find any matches"); - } else { - LogUtils.getLogger().info("Found a match at {} ticks in", i); - } + VillagerCracker.setTargetVillager((Villager) target); + if (target == null) { + ClientCommandHelper.sendFeedback("commands.cvillager.targetCleared"); } else { - throw SELECTED_ITEM_NOT_WORKSTATION.create(); + ClientCommandHelper.sendFeedback("commands.cvillager.targetSet"); } return Command.SINGLE_SUCCESS; } - private static int addGoal(WithStringArgument.Result firstPredicate, WithStringArgument.Result firstItemQuantityRange, @Nullable WithStringArgument.Result secondPredicate, @Nullable WithStringArgument.Result secondItemQuantityRange, WithStringArgument.Result resultPredicate, WithStringArgument.Result resultItemQuantityRange) { - goals.add(new Goal( - String.format("[%s] %s", firstItemQuantityRange.string(), firstPredicate.string()), - item -> firstPredicate.value().test(item) && firstItemQuantityRange.value().matches(item.getCount()), - - secondPredicate == null ? null : String.format("[%s] %s", secondItemQuantityRange.string(), secondPredicate.string()), - secondPredicate == null ? null : item -> secondPredicate.value().test(item) && secondItemQuantityRange.value().matches(item.getCount()), + private static int bruteForce() throws CommandSyntaxException { + Villager targetVillager = VillagerCracker.getVillager(); - String.format("[%s] %s", resultItemQuantityRange.string(), resultPredicate.string()), - item -> resultPredicate.value().test(item) && resultItemQuantityRange.value().matches(item.getCount()))); - ClientCommandHelper.sendFeedback("commands.cvillager.goalAdded"); + if (!(targetVillager instanceof IVillager iVillager) || iVillager.clientcommands_getCrackedRandom() == null) { + throw NO_CRACKED_VILLAGER_PRESENT.create(); + } + VillagerProfession profession = targetVillager.getVillagerData().getProfession(); + + VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(1, new VillagerTrades.ItemListing[0]); + // todo, ping + int adjustment = 1; + Pair pair = iVillager.clientcommands_bruteForceOffers(listings, profession, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))).mapFirst(x -> x + adjustment); + if (pair.getFirst() < 0) { + ClientCommandHelper.sendFeedback("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationCalls); + } else { + ClientCommandHelper.sendFeedback("commands.cvillager.bruteForce.success", VillagerCommand.displayText(pair.getSecond().result), pair.getSecond().second() == null ? VillagerCommand.displayText(pair.getSecond().first()) : VillagerCommand.displayText(pair.getSecond().first()) + " + " + VillagerCommand.displayText(pair.getSecond().second()), pair.getFirst()); + iVillager.clientcommands_getCrackedRandom().setCallsUntilOpenGui(pair.getFirst()); + } return Command.SINGLE_SUCCESS; } @@ -159,7 +164,36 @@ public boolean matches(ItemStack firstItem, @Nullable ItemStack secondItem, Item && ((secondPredicate == null && secondItem == null) || secondItem != null && secondPredicate != null && secondPredicate.test(secondItem)) && resultPredicate.test(result); } + + @Override + public String toString() { + if (secondString == null) { + return String.format("%s = %s", firstString, resultString); + } else { + return String.format("%s + %s = %s", firstString, secondString, resultString); + } + } } public record Offer(ItemStack first, @Nullable ItemStack second, ItemStack result) {} + + public static String displayText(ItemStack stack) { + String quantityPrefix; + if (stack.getCount() == 1) { + quantityPrefix = ""; + } else if (stack.getCount() < 64) { + quantityPrefix = stack.getCount() + " "; + } else if (stack.getCount() % 64 == 0) { + quantityPrefix = stack.getCount() / 64 + " stx "; + } else { + quantityPrefix = stack.getCount() / 64 + " stx & " + stack.getCount() % 64 + " "; + } + List lines = stack.getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL); + String itemDescription = lines.stream().skip(1).map(Component::getString).collect(Collectors.joining(", ")); + if (lines.size() == 1) { + return quantityPrefix + lines.getFirst().getString(); + } else { + return quantityPrefix + lines.getFirst().getString() + " (" + itemDescription + ")"; + } + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/EnchantmentCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/EnchantmentCracker.java index c22145eac..4405f9885 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/EnchantmentCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/EnchantmentCracker.java @@ -6,6 +6,7 @@ import com.seedfinding.mcseed.lcg.LCG; import com.seedfinding.mcseed.rand.Rand; import net.earthcomputer.clientcommands.Configs; +import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.util.MultiVersionCompat; import net.earthcomputer.clientcommands.task.ItemThrowTask; import net.earthcomputer.clientcommands.task.LongTask; @@ -23,7 +24,6 @@ import net.minecraft.core.BlockPos; import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; -import net.minecraft.network.chat.MutableComponent; import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; @@ -103,7 +103,6 @@ public class EnchantmentCracker { */ public static final Logger LOGGER = LogUtils.getLogger(); - private static final int PROGRESS_BAR_WIDTH = 50; // RENDERING /* @@ -463,17 +462,7 @@ public void onCompleted() { @Override protected void onItemThrown(int current, int total) { - MutableComponent builder = Component.empty(); - int color = Mth.hsvToRgb(current / (total * 3.0f), 1.0f, 1.0f); - builder.append(Component.literal("[").withColor(0xAAAAAA)); - builder.append(Component.literal("~" + Math.round(100.0 * current / total) + "%").withColor(color)); - builder.append(Component.literal("] ").withColor(0xAAAAAA)); - int filledWidth = (int) Math.round((double) PROGRESS_BAR_WIDTH * current / total); - int unfilledWidth = PROGRESS_BAR_WIDTH - filledWidth; - builder.append(Component.literal("|".repeat(filledWidth)).withColor(color)); - builder.append(Component.literal("|".repeat(unfilledWidth)).withColor(0xAAAAAA)); - - Minecraft.getInstance().gui.setOverlayMessage(builder, false); + ClientCommandHelper.updateOverlayProgressBar(current, total, 50, 60); } }); } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 912b44d9b..c0faf0df3 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -2,7 +2,12 @@ import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; +import net.minecraft.client.Minecraft; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.levelgen.LegacyRandomSource; @@ -19,17 +24,25 @@ public class VillagerRngSimulator { private int waitingTicks = 0; private boolean madeSound = false; private boolean firstAmbientNoise = true; + private int callsAtStartOfBruteForce = 0; + private int callsInBruteForce = 0; + private int totalCalls = 0; + private Villager parent; - public VillagerRngSimulator(@Nullable LegacyRandomSource random, int ambientSoundTime) { + public VillagerRngSimulator(@Nullable LegacyRandomSource random, int ambientSoundTime, Villager parent) { this.random = random; this.ambientSoundTime = ambientSoundTime; + this.parent = parent; } public VillagerRngSimulator copy() { - VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : new LegacyRandomSource(random.seed.get() ^ 0x5deece66dL), ambientSoundTime); + VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : new LegacyRandomSource(random.seed.get() ^ 0x5deece66dL), ambientSoundTime, parent); that.waitingTicks = this.waitingTicks; that.madeSound = this.madeSound; that.firstAmbientNoise = this.firstAmbientNoise; + that.callsAtStartOfBruteForce = this.callsAtStartOfBruteForce; + that.callsInBruteForce = this.callsInBruteForce; + that.totalCalls = this.totalCalls; return that; } @@ -40,6 +53,18 @@ public void simulateTick() { simulateBaseTick(); simulateServerAiStep(); + + if (callsInBruteForce > 0) { + updateProgressBar(); + } + } + + public boolean shouldInteractWithVillager() { + boolean shouldInteractWithVillager = totalCalls - callsAtStartOfBruteForce >= callsInBruteForce; + if (shouldInteractWithVillager) { + reset(); + } + return shouldInteractWithVillager; } public void simulateBaseTick() { @@ -53,9 +78,11 @@ public void simulateBaseTick() { } // we have the server receiving ambient noise tell us if we have to do this to increment the random, this is so that our ambient sound time is synced up. + totalCalls += 1; if (random.nextInt(1000) < ambientSoundTime++ && !firstAmbientNoise) { random.nextFloat(); random.nextFloat(); + totalCalls += 2; ambientSoundTime = -80; madeSound = true; } else { @@ -69,11 +96,17 @@ public void simulateServerAiStep() { } random.nextInt(100); + totalCalls += 1; } - public boolean anyOffersMatch(VillagerTrades.ItemListing[] listings, Entity trader, Predicate predicate) { + public void updateProgressBar() { + ClientCommandHelper.updateOverlayProgressBar(Math.min(callsInBruteForce, totalCalls - callsAtStartOfBruteForce), callsInBruteForce, 50, 60); + } + + @Nullable + public VillagerCommand.Offer anyOffersMatch(VillagerTrades.ItemListing[] listings, Entity trader, Predicate predicate) { if (!isCracked()) { - return false; + return null; } ArrayList newListings = new ArrayList<>(List.of(listings)); @@ -82,14 +115,15 @@ public boolean anyOffersMatch(VillagerTrades.ItemListing[] listings, Entity trad VillagerTrades.ItemListing listing = newListings.remove(random.nextInt(newListings.size())); MerchantOffer offer = listing.getOffer(trader, random); if (offer != null) { - if (predicate.test(new VillagerCommand.Offer(offer.getBaseCostA(), offer.getCostB(), offer.getResult()))) { - return true; + VillagerCommand.Offer x = new VillagerCommand.Offer(offer.getBaseCostA(), offer.getCostB(), offer.getResult()); + if (predicate.test(x)) { + return x; } else { i++; } } } - return false; + return null; } @Nullable @@ -97,6 +131,15 @@ public LegacyRandomSource getRandom() { return random; } + public void setCallsUntilOpenGui(int calls) { + callsAtStartOfBruteForce = totalCalls; + callsInBruteForce = calls; + } + + public int getTotalCalls() { + return totalCalls; + } + public boolean isCracked() { return random != null && !firstAmbientNoise; } @@ -105,11 +148,18 @@ public void setRandom(@Nullable LegacyRandomSource random) { this.random = random; } + public void reset() { + random = null; + firstAmbientNoise = true; + totalCalls = 0; + callsAtStartOfBruteForce = 0; + callsInBruteForce = 0; + } + @Override public String toString() { return "VillagerRngSimulator[" + - "seed=" + (random == null ? "null" : random.seed.get()) + ", " + - "ambientSoundTime=" + ambientSoundTime + ']'; + "seed=" + (random == null ? "null" : random.seed.get()) + ']'; } public void onAmbientSoundPlayed() { @@ -125,32 +175,11 @@ public void onAmbientSoundPlayed() { madeSound = true; } - // is in sync if (madeSound) { - ClientCommandHelper.sendFeedback("commands.cvillager.perfectlyInSync"); - return; - } - - // is not in sync, needs to be re-synced - VillagerRngSimulator copy = copy(); - int i = 0; - while (!copy.madeSound) { - i++; - copy.simulateTick(); - } - if (0 < i && i < 30) { - // in this case, it's a believable jump that we're less than 30 ticks behind, so we'll advance by the amount we calculated to be what this tick should've been - ClientCommandHelper.sendFeedback("commands.cvillager.tooManyTicksBehind", i); - this.random = copy.random; - this.ambientSoundTime = copy.ambientSoundTime; - this.waitingTicks = copy.waitingTicks; - this.madeSound = copy.madeSound; - } else if (i > 30) { - // in this case, it took so many ticks to advance to rsync, that it's safe to assume we are ahead of the server, so we'll let the server catch up by 30 ticks - ClientCommandHelper.sendFeedback("commands.cvillager.tooManyTicksAhead"); - waitingTicks += 30; + ClientCommandHelper.sendFeedback("commands.cvillager.inSync"); } else { - ClientCommandHelper.sendFeedback("commands.cvillager.perfectlyInSync"); + ClientCommandHelper.sendFeedback("commands.cvillager.outOfSync"); + reset(); } } } diff --git a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java index ac97f03c1..6b1d8eb51 100644 --- a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java +++ b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java @@ -1,5 +1,6 @@ package net.earthcomputer.clientcommands.interfaces; +import com.mojang.datafixers.util.Pair; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.minecraft.util.RandomSource; @@ -18,5 +19,5 @@ public interface IVillager { void clientcommands_onServerTick(); - int clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int maxTicks, Predicate predicate); + Pair clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int maxCalls, Predicate predicate); } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index 25383b166..471e7bd51 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -1,11 +1,20 @@ package net.earthcomputer.clientcommands.mixin.commands.villager; +import com.mojang.datafixers.util.Pair; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; +import net.minecraft.client.Minecraft; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; import net.minecraft.util.RandomSource; +import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.npc.*; +import net.minecraft.world.entity.npc.AbstractVillager; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.VillagerData; +import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.level.Level; import net.minecraft.world.level.levelgen.LegacyRandomSource; import org.jetbrains.annotations.Nullable; @@ -26,80 +35,58 @@ public VillagerMixin(EntityType entityType, Level le } @Unique - VillagerRngSimulator rng = new VillagerRngSimulator(null, -80); + VillagerRngSimulator rng = new VillagerRngSimulator(null, -80, (Villager) (Object) this); @Override public void clientcommands_setCrackedRandom(@Nullable RandomSource random) { rng.setRandom((LegacyRandomSource) random); } - @Override - public VillagerRngSimulator clientcommands_getCrackedRandom() { - return rng; - } - @Override public void clientcommands_onAmbientSoundPlayed() { rng.onAmbientSoundPlayed(); } -// public void clientcommands_onProfessionUpdate(VillagerProfession newProfession) { -// Villager targetVillager = VillagerCracker.getVillager(); -// if (targetVillager instanceof IVillager iVillager && iVillager.clientcommands_getCrackedRandom().isCracked()) { -// -// if (offers == null) { -// return; -// } -// for (MerchantOffer offer : offers) { -// if (offer.getItemCostB().isPresent()) { -// LOGGER.info("[x{}] {} + [x{}] {} = [x{}] {} ({})", -// offer.getItemCostA().count(), -// Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostA().item().value()).getPath()).getString(), -// offer.getItemCostB().get().count(), -// Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostB().get().item().value()).getPath()).getString(), -// offer.getResult().getCount(), -// I18n.get(BuiltInRegistries.ITEM.getKey(offer.getResult().getItem()).getPath()), -// offer.getResult().getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL).stream().map(Component::getString).skip(1).collect(Collectors.joining(", "))); -// } else { -// LOGGER.info("[x{}] {} = [x{}] {} ({})", -// offer.getItemCostA().count(), -// Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getItemCostA().item().value()).getPath()).getString(), -// offer.getResult().getCount(), -// Component.translatable(BuiltInRegistries.ITEM.getKey(offer.getResult().getItem()).getPath()).getString(), -// offer.getResult().getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL).stream().map(Component::getString).skip(1).collect(Collectors.joining(", "))); -// } -// } -// } -// } - @Override public void clientcommands_onServerTick() { rng.simulateTick(); + + if (rng.shouldInteractWithVillager()) { + Minecraft minecraft = Minecraft.getInstance(); + minecraft.gameMode.interact(minecraft.player, this, InteractionHand.MAIN_HAND); + minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); + } } @Override - public int clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int maxTicks, Predicate predicate) { + public Pair clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int maxCalls, Predicate predicate) { if (this instanceof IVillager iVillager && iVillager.clientcommands_getCrackedRandom().isCracked()) { VillagerProfession oldProfession = getVillagerData().getProfession(); setVillagerData(getVillagerData().setProfession(profession)); VillagerRngSimulator rng = this.rng.copy(); - int i = 0; - while (i < maxTicks) { + int startingCalls = rng.getTotalCalls(); + while (rng.getTotalCalls() < maxCalls + startingCalls) { VillagerRngSimulator randomBranch = rng.copy(); randomBranch.simulateBaseTick(); - if (randomBranch.anyOffersMatch(listings, (Villager) (Object) this, predicate)) { + randomBranch.simulateServerAiStep(); + VillagerCommand.Offer offer = randomBranch.anyOffersMatch(listings, (Villager) (Object) this, predicate); + if (offer != null) { setVillagerData(getVillagerData().setProfession(oldProfession)); - return i; + // we do the calls before this ticks processing so that since with 0ms ping, the server reads it next tick + return Pair.of(rng.getTotalCalls() - startingCalls, offer); } - randomBranch.simulateServerAiStep(); rng.simulateTick(); - i++; } setVillagerData(getVillagerData().setProfession(oldProfession)); } - return -1; + return Pair.of(-1_000_000, null); + } + + @Override + public VillagerRngSimulator clientcommands_getCrackedRandom() { + return rng; } } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 10f63c68d..316f7a0eb 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -45,20 +45,22 @@ "commands.ccrackrng.starting": "Cracking player seed", "commands.ccrackrng.success": "Player RNG cracked: %d", - "commands.cvillager.notAVillager": "Target was not a villager", - "commands.cvillager.selected_item_not_workstation": "Your selected item was not a valid workstation block", - "commands.cvillager.no_cracked_villager_present": "There was no cracked villager available to use", - "commands.cvillager.listGoals.noGoals": "There are no villager goals.", - "commands.cvillager.listGoals.success": "There are %d villager goals:", - "commands.cvillager.targetSet": "Target entity set", - "commands.cvillager.targetCleared": "Target entity cleared", + "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %d calls.", + "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls.", "commands.cvillager.clockSet": "Clock set to %d %d %d", "commands.cvillager.crackFailed": "Failed to crack villager seed", "commands.cvillager.crackSuccess": "Villager RNG cracked: %d", "commands.cvillager.goalAdded": "Added goal successfully.", - "commands.cvillager.tooManyTicksAhead": "Was too many ticks ahead of villager cracking, awaiting the next 30 ticks of processing. Will likely need another ambient sound to resync", - "commands.cvillager.tooManyTicksBehind": "Was too many ticks behind of villager cracking, simulating by %d ticks, should be in sync.", - "commands.cvillager.perfectlyInSync": "Your villager's random is perfectly in sync", + "commands.cvillager.inSync": "Your villager's RNG is in sync", + "commands.cvillager.listGoals.noGoals": "There are no villager goals.", + "commands.cvillager.listGoals.success": "There are %d villager goals:", + "commands.cvillager.no_cracked_villager_present": "There was no cracked villager available to use", + "commands.cvillager.notAVillager": "Target was not a villager", + "commands.cvillager.outOfSync": "Your Villager's RNG was out of sync, please re-crack.", + "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals.", + "commands.cvillager.removeGoal.success": "Successfully removed goal %s", + "commands.cvillager.targetCleared": "Target entity cleared", + "commands.cvillager.targetSet": "Target entity set", "commands.ccreativetab.addStack.success": "Successfully added %s to \"%s\"", "commands.ccreativetab.addTab.alreadyExists": "Creative tab \"%s\" already exists", From b5fe87c027580e41d3dd203e8784829334d6ada7 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sun, 2 Jun 2024 15:27:31 -0400 Subject: [PATCH 06/78] whoopsie --- .../clientcommands/features/VillagerRngSimulator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index c0faf0df3..61ca94d84 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -60,7 +60,7 @@ public void simulateTick() { } public boolean shouldInteractWithVillager() { - boolean shouldInteractWithVillager = totalCalls - callsAtStartOfBruteForce >= callsInBruteForce; + boolean shouldInteractWithVillager = totalCalls - callsAtStartOfBruteForce >= callsInBruteForce && callsInBruteForce > 0; if (shouldInteractWithVillager) { reset(); } From fa0fde5ad1b235ea2e0fa1d8c8b63874a70f0c46 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sun, 2 Jun 2024 18:29:52 -0400 Subject: [PATCH 07/78] need to check the ping checking - i can probably remove the clock requirement and use the day/night packets --- .../command/VillagerCommand.java | 25 +++++++++---- .../features/FishingCracker.java | 4 +++ .../features/VillagerRngSimulator.java | 32 ++++++++++------- .../commands/villager/VillagerMixin.java | 6 +++- .../assets/clientcommands/lang/en_us.json | 36 ++++++++++--------- 5 files changed, 65 insertions(+), 38 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 9871074ee..86dbd8e2c 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -41,7 +41,8 @@ public class VillagerCommand { private static final SimpleCommandExceptionType NOT_A_VILLAGER_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notAVillager")); - private static final SimpleCommandExceptionType NO_CRACKED_VILLAGER_PRESENT = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.no_cracked_villager_present")); + private static final SimpleCommandExceptionType NO_CRACKED_VILLAGER_PRESENT = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noCrackedVillagerPresent")); + private static final SimpleCommandExceptionType NO_PROFESSION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noProfession")); private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); public static final List goals = new ArrayList<>(); @@ -143,16 +144,26 @@ private static int bruteForce() throws CommandSyntaxException { throw NO_CRACKED_VILLAGER_PRESENT.create(); } VillagerProfession profession = targetVillager.getVillagerData().getProfession(); + if (profession == VillagerProfession.NONE) { + throw NO_PROFESSION.create(); + } VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(1, new VillagerTrades.ItemListing[0]); - // todo, ping - int adjustment = 1; + int adjustment = 1 + (iVillager.clientcommands_getCrackedRandom().currentCorrectionMs() - 25) / 50; Pair pair = iVillager.clientcommands_bruteForceOffers(listings, profession, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))).mapFirst(x -> x + adjustment); - if (pair.getFirst() < 0) { - ClientCommandHelper.sendFeedback("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationCalls); + int ticks = pair.getFirst(); + Offer offer = pair.getSecond(); + if (ticks < 0) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationCalls).withStyle(ChatFormatting.RED), 100); } else { - ClientCommandHelper.sendFeedback("commands.cvillager.bruteForce.success", VillagerCommand.displayText(pair.getSecond().result), pair.getSecond().second() == null ? VillagerCommand.displayText(pair.getSecond().first()) : VillagerCommand.displayText(pair.getSecond().first()) + " + " + VillagerCommand.displayText(pair.getSecond().second()), pair.getFirst()); - iVillager.clientcommands_getCrackedRandom().setCallsUntilOpenGui(pair.getFirst()); + String price; + if (offer.second() == null) { + price = VillagerCommand.displayText(offer.first()); + } else { + price = VillagerCommand.displayText(offer.first()) + " + " + VillagerCommand.displayText(offer.second()); + } + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", VillagerCommand.displayText(offer.result()), price, ticks).withStyle(ChatFormatting.GREEN)); + iVillager.clientcommands_getCrackedRandom().setCallsUntilOpenGui(ticks, offer.result()); } return Command.SINGLE_SUCCESS; diff --git a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java index 9d06b8233..2eada8d5e 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java @@ -629,6 +629,10 @@ private static void onTimeSync() { } } + public static int getMagicMillisecondsCorrection() { + return magicMillisecondsCorrection; + } + public static void onThrownFishingRod(ItemStack stack) { if (expectedFishingRodUses > 0) { expectedFishingRodUses--; diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 61ca94d84..fd2781b1b 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -1,14 +1,14 @@ package net.earthcomputer.clientcommands.features; import net.earthcomputer.clientcommands.command.ClientCommandHelper; +import net.earthcomputer.clientcommands.command.PingCommand; import net.earthcomputer.clientcommands.command.VillagerCommand; +import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.world.InteractionHand; +import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; -import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.VillagerTrades; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.levelgen.LegacyRandomSource; import org.jetbrains.annotations.Nullable; @@ -27,22 +27,23 @@ public class VillagerRngSimulator { private int callsAtStartOfBruteForce = 0; private int callsInBruteForce = 0; private int totalCalls = 0; - private Villager parent; + @Nullable + private ItemStack activeGoalResult = null; - public VillagerRngSimulator(@Nullable LegacyRandomSource random, int ambientSoundTime, Villager parent) { + public VillagerRngSimulator(@Nullable LegacyRandomSource random, int ambientSoundTime) { this.random = random; this.ambientSoundTime = ambientSoundTime; - this.parent = parent; } public VillagerRngSimulator copy() { - VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : new LegacyRandomSource(random.seed.get() ^ 0x5deece66dL), ambientSoundTime, parent); + VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : new LegacyRandomSource(random.seed.get() ^ 0x5deece66dL), ambientSoundTime); that.waitingTicks = this.waitingTicks; that.madeSound = this.madeSound; that.firstAmbientNoise = this.firstAmbientNoise; that.callsAtStartOfBruteForce = this.callsAtStartOfBruteForce; that.callsInBruteForce = this.callsInBruteForce; that.totalCalls = this.totalCalls; + that.activeGoalResult = this.activeGoalResult; return that; } @@ -99,6 +100,10 @@ public void simulateServerAiStep() { totalCalls += 1; } + public int currentCorrectionMs() { + return -PingCommand.getLocalPing() / 2; + } + public void updateProgressBar() { ClientCommandHelper.updateOverlayProgressBar(Math.min(callsInBruteForce, totalCalls - callsAtStartOfBruteForce), callsInBruteForce, 50, 60); } @@ -131,9 +136,10 @@ public LegacyRandomSource getRandom() { return random; } - public void setCallsUntilOpenGui(int calls) { + public void setCallsUntilOpenGui(int calls, ItemStack resultStack) { callsAtStartOfBruteForce = totalCalls; callsInBruteForce = calls; + activeGoalResult = resultStack; } public int getTotalCalls() { @@ -154,6 +160,7 @@ public void reset() { totalCalls = 0; callsAtStartOfBruteForce = 0; callsInBruteForce = 0; + activeGoalResult = null; } @Override @@ -173,12 +180,11 @@ public void onAmbientSoundPlayed() { random.nextFloat(); random.nextFloat(); madeSound = true; + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync").withStyle(ChatFormatting.GREEN), 100); } - if (madeSound) { - ClientCommandHelper.sendFeedback("commands.cvillager.inSync"); - } else { - ClientCommandHelper.sendFeedback("commands.cvillager.outOfSync"); + if (!madeSound) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); reset(); } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index 471e7bd51..2e2d63364 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -1,10 +1,13 @@ package net.earthcomputer.clientcommands.mixin.commands.villager; import com.mojang.datafixers.util.Pair; +import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; +import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; +import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; import net.minecraft.util.RandomSource; @@ -35,7 +38,7 @@ public VillagerMixin(EntityType entityType, Level le } @Unique - VillagerRngSimulator rng = new VillagerRngSimulator(null, -80, (Villager) (Object) this); + VillagerRngSimulator rng = new VillagerRngSimulator(null, -80); @Override public void clientcommands_setCrackedRandom(@Nullable RandomSource random) { @@ -55,6 +58,7 @@ public void clientcommands_onServerTick() { Minecraft minecraft = Minecraft.getInstance(); minecraft.gameMode.interact(minecraft.player, this, InteractionHand.MAIN_HAND); minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.success", rng.currentCorrectionMs()).withStyle(ChatFormatting.GREEN), 100); } } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 316f7a0eb..609e35b2f 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -45,23 +45,6 @@ "commands.ccrackrng.starting": "Cracking player seed", "commands.ccrackrng.success": "Player RNG cracked: %d", - "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %d calls.", - "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls.", - "commands.cvillager.clockSet": "Clock set to %d %d %d", - "commands.cvillager.crackFailed": "Failed to crack villager seed", - "commands.cvillager.crackSuccess": "Villager RNG cracked: %d", - "commands.cvillager.goalAdded": "Added goal successfully.", - "commands.cvillager.inSync": "Your villager's RNG is in sync", - "commands.cvillager.listGoals.noGoals": "There are no villager goals.", - "commands.cvillager.listGoals.success": "There are %d villager goals:", - "commands.cvillager.no_cracked_villager_present": "There was no cracked villager available to use", - "commands.cvillager.notAVillager": "Target was not a villager", - "commands.cvillager.outOfSync": "Your Villager's RNG was out of sync, please re-crack.", - "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals.", - "commands.cvillager.removeGoal.success": "Successfully removed goal %s", - "commands.cvillager.targetCleared": "Target entity cleared", - "commands.cvillager.targetSet": "Target entity set", - "commands.ccreativetab.addStack.success": "Successfully added %s to \"%s\"", "commands.ccreativetab.addTab.alreadyExists": "Creative tab \"%s\" already exists", "commands.ccreativetab.addTab.illegalCharacter": "Creative tab can only contain [a-z0-9/._-] characters", @@ -259,6 +242,25 @@ "commands.cvar.list.empty": "No available variables", "commands.cvar.list": "Available variables: %s", + "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %d calls.", + "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls.", + "commands.cvillager.clockSet": "Clock set to %d %d %d", + "commands.cvillager.crackFailed": "Failed to crack villager seed", + "commands.cvillager.crackSuccess": "Villager RNG cracked: %d", + "commands.cvillager.goalAdded": "Added goal successfully.", + "commands.cvillager.inSync": "Your villager's RNG is now in sync", + "commands.cvillager.listGoals.noGoals": "There are no villager goals.", + "commands.cvillager.listGoals.success": "There are %d villager goals:", + "commands.cvillager.noCrackedVillagerPresent": "There was no cracked villager available to use", + "commands.cvillager.noProfession": "The targeted villager has no profession.", + "commands.cvillager.notAVillager": "Target was not a villager", + "commands.cvillager.outOfSync": "Your Villager's RNG was out of sync, please re-crack.", + "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals.", + "commands.cvillager.removeGoal.success": "Successfully removed goal %s", + "commands.cvillager.success": "Got the correct trade with correction of %dms", + "commands.cvillager.targetCleared": "Target entity cleared", + "commands.cvillager.targetSet": "Target entity set", + "commands.cwe.playerNotFound": "Player not found", "commands.cweather.reset": "Stopped overriding weather", From 406d55aa0e6dcc51ccec124866e41df1f011989a Mon Sep 17 00:00:00 2001 From: RTTV Date: Tue, 11 Jun 2024 11:59:45 -0400 Subject: [PATCH 08/78] ping checking might work, idk --- .../earthcomputer/clientcommands/Configs.java | 4 +- .../command/VillagerCommand.java | 28 +++---- .../event/MoreClientEvents.java | 13 ++++ .../features/VillagerCracker.java | 18 ++--- .../features/VillagerRngSimulator.java | 76 +++++++++++++++---- .../commands/villager/VillagerMixin.java | 8 +- .../events/ClientPacketListenerMixin.java | 4 +- .../rngevents/ClientPacketListenerMixin.java | 18 ----- .../util/EstimatedServerTick.java | 48 ++++++++++++ .../assets/clientcommands/lang/en_us.json | 4 +- 10 files changed, 157 insertions(+), 64 deletions(-) create mode 100644 src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java diff --git a/src/main/java/net/earthcomputer/clientcommands/Configs.java b/src/main/java/net/earthcomputer/clientcommands/Configs.java index 60b03797d..b61237cb9 100644 --- a/src/main/java/net/earthcomputer/clientcommands/Configs.java +++ b/src/main/java/net/earthcomputer/clientcommands/Configs.java @@ -171,11 +171,11 @@ public enum PacketDumpMethod { public static int maximumPacketFieldDepth = 10; @Config(temporary = true, setter = @Config.Setter("setMaxVillagerBruteForceSimulationCalls")) - public static int maxVillagerBruteForceSimulationCalls = 16384; + public static int maxVillagerBruteForceSimulationCalls = 12000; public static void setMaxVillagerBruteForceSimulationCalls(int maxVillagerBruteForceSimulationCalls) { Configs.maxVillagerBruteForceSimulationCalls = Mth.clamp(maxVillagerBruteForceSimulationCalls, 0, 65536); } @Config(temporary = true) - public static int villagerAdjustment = 1; + public static int villagerAdjustment = 0; } diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 86dbd8e2c..a0a41a072 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -10,12 +10,12 @@ import net.earthcomputer.clientcommands.command.arguments.WithStringArgument; import net.earthcomputer.clientcommands.features.FishingCracker; import net.earthcomputer.clientcommands.features.VillagerCracker; +import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.ChatFormatting; import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.commands.CommandBuildContext; -import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; @@ -32,7 +32,6 @@ import java.util.stream.Collectors; import static com.mojang.brigadier.arguments.IntegerArgumentType.*; -import static dev.xpple.clientarguments.arguments.CBlockPosArgument.*; import static dev.xpple.clientarguments.arguments.CEntityArgument.*; import static dev.xpple.clientarguments.arguments.CItemPredicateArgument.*; import static net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument.*; @@ -65,11 +64,8 @@ public static void register(CommandDispatcher dispatc .then(literal("list-goals") .executes(ctx -> listGoals(ctx.getSource()))) .then(literal("remove-goal") - .then(argument("index", integer(0)) + .then(argument("index", integer(1)) .executes(ctx -> removeGoal(ctx.getSource(), getInteger(ctx, "index"))))) - .then(literal("clock") - .then(argument("pos", blockPos()) - .executes(ctx -> setClockBlockPos(getBlockPos(ctx, "pos"))))) .then(literal("target") .executes(ctx -> setVillagerTarget(null)) .then(argument("entity", entity()) @@ -97,7 +93,7 @@ private static int listGoals(FabricClientCommandSource source) { if (goals.isEmpty()) { source.sendFeedback(Component.translatable("commands.cvillager.listGoals.noGoals").withStyle(style -> style.withColor(ChatFormatting.RED))); } else { - source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", FishingCracker.goals.size())); + source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", FishingCracker.goals.size() + 1)); for (int i = 0; i < goals.size(); i++) { Goal goal = goals.get(i); source.sendFeedback(Component.literal((i + 1) + ": " + goal.toString())); @@ -107,21 +103,16 @@ private static int listGoals(FabricClientCommandSource source) { } private static int removeGoal(FabricClientCommandSource source, int index) throws CommandSyntaxException { + index = index - 1; if (index < goals.size()) { Goal goal = goals.remove(index); source.sendFeedback(Component.translatable("commands.cvillager.removeGoal.success", goal.toString())); } else { - throw INVALID_GOAL_INDEX.create(index, goals.size()); + throw INVALID_GOAL_INDEX.create(index + 1, goals.size()); } return Command.SINGLE_SUCCESS; } - private static int setClockBlockPos(BlockPos pos) { - VillagerCracker.clockBlockPos = pos; - ClientCommandHelper.sendFeedback("commands.cvillager.clockSet", pos.getX(), pos.getY(), pos.getZ()); - return Command.SINGLE_SUCCESS; - } - private static int setVillagerTarget(@Nullable Entity target) throws CommandSyntaxException { if (!(target instanceof Villager) && target != null) { throw NOT_A_VILLAGER_EXCEPTION.create(); @@ -149,12 +140,17 @@ private static int bruteForce() throws CommandSyntaxException { } VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(1, new VillagerTrades.ItemListing[0]); - int adjustment = 1 + (iVillager.clientcommands_getCrackedRandom().currentCorrectionMs() - 25) / 50; + int adjustment = 3 + Configs.villagerAdjustment - (iVillager.clientcommands_getCrackedRandom().currentCorrectionMs() + 40) / 50; Pair pair = iVillager.clientcommands_bruteForceOffers(listings, profession, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))).mapFirst(x -> x + adjustment); int ticks = pair.getFirst(); Offer offer = pair.getSecond(); if (ticks < 0) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationCalls).withStyle(ChatFormatting.RED), 100); + VillagerRngSimulator.CrackedState state = iVillager.clientcommands_getCrackedRandom().getCrackedState(); + Component message = state.getMessage(true); + if (state.isCracked()) { + message = Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationCalls).withStyle(ChatFormatting.RED); + } + ClientCommandHelper.addOverlayMessage(message, 100); } else { String price; if (offer.second() == null) { diff --git a/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java b/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java index 803c21b31..7b901bc3d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java +++ b/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java @@ -2,6 +2,7 @@ import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; +import net.minecraft.client.Minecraft; import net.minecraft.network.protocol.game.ClientboundSetTimePacket; public final class MoreClientEvents { @@ -15,9 +16,21 @@ public final class MoreClientEvents { listener.onTimeSync(packet); } }); + public static final Event ESTIMATED_SERVER_TICK = EventFactory.createArrayBacked(EstimatedServerTickEvent.class, listeners -> () -> { + Minecraft.getInstance().tell(() -> { + for (EstimatedServerTickEvent listener : listeners) { + listener.onEstimatedServerTick(); + } + }); + }); @FunctionalInterface public interface TimeSync { void onTimeSync(ClientboundSetTimePacket packet); } + + @FunctionalInterface + public interface EstimatedServerTickEvent { + void onEstimatedServerTick(); + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index f5527531a..f28ac3528 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -1,9 +1,9 @@ package net.earthcomputer.clientcommands.features; +import com.mojang.logging.LogUtils; import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.interfaces.IVillager; import net.minecraft.client.Minecraft; -import net.minecraft.core.BlockPos; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundSoundPacket; import net.minecraft.util.RandomSource; @@ -20,9 +20,6 @@ public class VillagerCracker { @Nullable private static WeakReference cachedVillager = null; - @Nullable - public static BlockPos clockBlockPos = null; - @Nullable public static Villager getVillager() { if (villagerUuid == null) { @@ -35,10 +32,12 @@ public static Villager getVillager() { return villager; } } - for (Entity entity : Minecraft.getInstance().level.entitiesForRendering()) { - if (entity.getUUID() == villagerUuid && entity instanceof Villager villager) { - cachedVillager = new WeakReference<>(villager); - return villager; + if (Minecraft.getInstance().level != null) { + for (Entity entity : Minecraft.getInstance().level.entitiesForRendering()) { + if (entity.getUUID() == villagerUuid && entity instanceof Villager villager) { + cachedVillager = new WeakReference<>(villager); + return villager; + } } } return null; @@ -67,6 +66,8 @@ public static void onSoundEventPlayed(ClientboundSoundPacket packet) { ClientCommandHelper.sendError(Component.translatable("commands.cvillager.crackFailed")); } else { ((IVillager) targetVillager).clientcommands_setCrackedRandom(RandomSource.create(possible[0] ^ 0x5deece66dL)); + // simulate a tick to advance it by one + ((IVillager) targetVillager).clientcommands_getCrackedRandom().simulateTick(); ClientCommandHelper.sendFeedback("commands.cvillager.crackSuccess", Long.toHexString(possible[0])); } } @@ -84,5 +85,4 @@ public static void onServerTick() { ((IVillager) targetVillager).clientcommands_onServerTick(); } - } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index fd2781b1b..c1ea4d383 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -4,7 +4,6 @@ import net.earthcomputer.clientcommands.command.PingCommand; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.VillagerTrades; @@ -23,7 +22,7 @@ public class VillagerRngSimulator { private int ambientSoundTime; private int waitingTicks = 0; private boolean madeSound = false; - private boolean firstAmbientNoise = true; + private int totalAmbientSounds = 0; private int callsAtStartOfBruteForce = 0; private int callsInBruteForce = 0; private int totalCalls = 0; @@ -39,7 +38,7 @@ public VillagerRngSimulator copy() { VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : new LegacyRandomSource(random.seed.get() ^ 0x5deece66dL), ambientSoundTime); that.waitingTicks = this.waitingTicks; that.madeSound = this.madeSound; - that.firstAmbientNoise = this.firstAmbientNoise; + that.totalAmbientSounds = this.totalAmbientSounds; that.callsAtStartOfBruteForce = this.callsAtStartOfBruteForce; that.callsInBruteForce = this.callsInBruteForce; that.totalCalls = this.totalCalls; @@ -80,7 +79,7 @@ public void simulateBaseTick() { // we have the server receiving ambient noise tell us if we have to do this to increment the random, this is so that our ambient sound time is synced up. totalCalls += 1; - if (random.nextInt(1000) < ambientSoundTime++ && !firstAmbientNoise) { + if (random.nextInt(1000) < ambientSoundTime++ && totalAmbientSounds > 0) { random.nextFloat(); random.nextFloat(); totalCalls += 2; @@ -101,7 +100,7 @@ public void simulateServerAiStep() { } public int currentCorrectionMs() { - return -PingCommand.getLocalPing() / 2; + return PingCommand.getLocalPing() / 2; } public void updateProgressBar() { @@ -110,7 +109,7 @@ public void updateProgressBar() { @Nullable public VillagerCommand.Offer anyOffersMatch(VillagerTrades.ItemListing[] listings, Entity trader, Predicate predicate) { - if (!isCracked()) { + if (!getCrackedState().isCracked()) { return null; } @@ -146,8 +145,20 @@ public int getTotalCalls() { return totalCalls; } - public boolean isCracked() { - return random != null && !firstAmbientNoise; + public CrackedState getCrackedState() { + if (random == null) { + return CrackedState.UNCRACKED; + } + + if (totalAmbientSounds == 0) { + return CrackedState.PENDING_FIRST_AMBIENT_SOUND; + } + + if (totalAmbientSounds == 1) { + return CrackedState.PENDING_SECOND_AMBIENT_SOUND; + } + + return CrackedState.CRACKED; } public void setRandom(@Nullable LegacyRandomSource random) { @@ -156,7 +167,7 @@ public void setRandom(@Nullable LegacyRandomSource random) { public void reset() { random = null; - firstAmbientNoise = true; + totalAmbientSounds = 0; totalCalls = 0; callsAtStartOfBruteForce = 0; callsInBruteForce = 0; @@ -170,22 +181,59 @@ public String toString() { } public void onAmbientSoundPlayed() { - if (firstAmbientNoise) { + if (totalAmbientSounds == 0) { if (random == null) { return; } - firstAmbientNoise = false; + totalAmbientSounds++; ambientSoundTime = -80; random.nextFloat(); random.nextFloat(); madeSound = true; - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync").withStyle(ChatFormatting.GREEN), 100); + ClientCommandHelper.addOverlayMessage(getCrackedState().getMessage(true), 100); + return; } if (!madeSound) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); - reset(); + int i = 0; + VillagerRngSimulator rng = this.copy(); + do { + rng.simulateTick(); + i++; + } while (!rng.madeSound); + + if (i <= PingCommand.getLocalPing() / 50 + 5) { + for (int j = 0; j < i; j++) { + simulateTick(); + } + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.resynced", i).withStyle(ChatFormatting.GREEN), 100); + } else { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); + reset(); + } + } else if (totalAmbientSounds++ == 1) { + ClientCommandHelper.addOverlayMessage(getCrackedState().getMessage(true), 100); + } + } + + public enum CrackedState { + UNCRACKED, + PENDING_FIRST_AMBIENT_SOUND, + PENDING_SECOND_AMBIENT_SOUND, + CRACKED; + + public boolean isCracked() { + return this == CRACKED; + } + + public Component getMessage(boolean addColor) { + return switch (this) { + case UNCRACKED -> Component.translatable("commands.cvillager.noCrackedVillagerPresent").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); + case PENDING_FIRST_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 0).withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); + case PENDING_SECOND_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 50).withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); + case CRACKED -> Component.translatable("commands.cvillager.inSync", 100).withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); + }; } } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index 2e2d63364..d2ffdace7 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -12,6 +12,7 @@ import net.minecraft.sounds.SoundSource; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; +import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.npc.AbstractVillager; import net.minecraft.world.entity.npc.Villager; @@ -56,7 +57,10 @@ public void clientcommands_onServerTick() { if (rng.shouldInteractWithVillager()) { Minecraft minecraft = Minecraft.getInstance(); - minecraft.gameMode.interact(minecraft.player, this, InteractionHand.MAIN_HAND); + InteractionResult result = minecraft.gameMode.interact(minecraft.player, this, InteractionHand.MAIN_HAND); + if (result.consumesAction() && result.shouldSwing()) { + minecraft.player.swing(InteractionHand.MAIN_HAND); + } minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.success", rng.currentCorrectionMs()).withStyle(ChatFormatting.GREEN), 100); } @@ -64,7 +68,7 @@ public void clientcommands_onServerTick() { @Override public Pair clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int maxCalls, Predicate predicate) { - if (this instanceof IVillager iVillager && iVillager.clientcommands_getCrackedRandom().isCracked()) { + if (this instanceof IVillager iVillager && iVillager.clientcommands_getCrackedRandom().getCrackedState().isCracked()) { VillagerProfession oldProfession = getVillagerData().getProfession(); setVillagerData(getVillagerData().setProfession(profession)); diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java index b948c017a..d9021af03 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java @@ -2,19 +2,20 @@ import net.earthcomputer.clientcommands.event.MoreClientEntityEvents; import net.earthcomputer.clientcommands.event.MoreClientEvents; +import net.earthcomputer.clientcommands.util.EstimatedServerTick; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundSetTimePacket; 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; @Mixin(ClientPacketListener.class) public class ClientPacketListenerMixin { - @Inject(method = "handleAddEntity", at = @At("HEAD")) public void onHandleAddEntityPre(ClientboundAddEntityPacket packet, CallbackInfo ci) { MoreClientEntityEvents.PRE_ADD_MAYBE_ON_NETWORK_THREAD.invoker().onAddEntity(packet); @@ -33,6 +34,7 @@ public void onHandleAddExperienceOrb(ClientboundAddExperienceOrbPacket packet, C @Inject(method = "handleSetTime", at = @At("HEAD")) private void onHandleSetTime(ClientboundSetTimePacket packet, CallbackInfo ci) { if (Minecraft.getInstance().isSameThread()) { + EstimatedServerTick.onSetTime(packet.getGameTime()); MoreClientEvents.TIME_SYNC.invoker().onTimeSync(packet); } else { MoreClientEvents.TIME_SYNC_ON_NETWORK_THREAD.invoker().onTimeSync(packet); diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java index ae7ee2a02..4f8425d09 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java @@ -5,8 +5,6 @@ import net.earthcomputer.clientcommands.features.VillagerCracker; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; -import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.phys.Vec3; @@ -37,20 +35,4 @@ private void onHandleSoundEvent(ClientboundSoundPacket packet, CallbackInfo ci) VillagerCracker.onSoundEventPlayed(packet); } } - - @Inject(method = "handleBlockUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) - private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackInfo ci) { - if (packet.getPos().equals(VillagerCracker.clockBlockPos)) { - VillagerCracker.onServerTick(); - } - } - - @Inject(method = "handleChunkBlocksUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) - private void onHandleChunkBlocksUpdate(ClientboundSectionBlocksUpdatePacket packet, CallbackInfo ci) { - packet.runUpdates((pos, state) -> { - if (pos.equals(VillagerCracker.clockBlockPos)) { - VillagerCracker.onServerTick(); - } - }); - } } diff --git a/src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java b/src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java new file mode 100644 index 000000000..a91506eb4 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java @@ -0,0 +1,48 @@ +package net.earthcomputer.clientcommands.util; + +import net.earthcomputer.clientcommands.event.MoreClientEvents; +import net.earthcomputer.clientcommands.features.VillagerCracker; + +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicLong; + +public class EstimatedServerTick { + private static long lastServerSetTime = 0; + private static long lastGameTime = 0; + private static final AtomicLong estimatedNsPerTick = new AtomicLong(50_000_000L); + private static final AtomicInteger ticksRemaining = new AtomicInteger(0); + + public static void onSetTime(long gameTime) { + long ns = System.nanoTime(); + long estimatedNsPerTick; + if (lastServerSetTime == 0) { + // assuming 20 tps + estimatedNsPerTick = 50_000_000L; + } else { + estimatedNsPerTick = (ns - lastServerSetTime) / Math.max(1, gameTime - lastGameTime); + } + lastGameTime = gameTime; + lastServerSetTime = ns; + EstimatedServerTick.estimatedNsPerTick.set(0); + // spin loop + while (ticksRemaining.get() > 0); + EstimatedServerTick.estimatedNsPerTick.set(estimatedNsPerTick); + ticksRemaining.set(20); + } + + static { + new Thread(() -> { + long lastTickTimestamp = 0; + + while (true) { + long ns = System.nanoTime(); + if (ns >= lastTickTimestamp + estimatedNsPerTick.get() && EstimatedServerTick.ticksRemaining.getAndDecrement() > 0) { + lastTickTimestamp = ns; + MoreClientEvents.ESTIMATED_SERVER_TICK.invoker().onEstimatedServerTick(); + } + } + }, "Estimated Server Tick Thread").start(); + + MoreClientEvents.ESTIMATED_SERVER_TICK.register(VillagerCracker::onServerTick); + } +} diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 609e35b2f..3a50a7ff6 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -244,17 +244,17 @@ "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %d calls.", "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls.", - "commands.cvillager.clockSet": "Clock set to %d %d %d", "commands.cvillager.crackFailed": "Failed to crack villager seed", "commands.cvillager.crackSuccess": "Villager RNG cracked: %d", "commands.cvillager.goalAdded": "Added goal successfully.", - "commands.cvillager.inSync": "Your villager's RNG is now in sync", + "commands.cvillager.inSync": "Your villager's RNG is %d%% synced", "commands.cvillager.listGoals.noGoals": "There are no villager goals.", "commands.cvillager.listGoals.success": "There are %d villager goals:", "commands.cvillager.noCrackedVillagerPresent": "There was no cracked villager available to use", "commands.cvillager.noProfession": "The targeted villager has no profession.", "commands.cvillager.notAVillager": "Target was not a villager", "commands.cvillager.outOfSync": "Your Villager's RNG was out of sync, please re-crack.", + "commands.cvillager.resynced": "Your Villager's RNG was resynced, skipped %d ticks.", "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals.", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", "commands.cvillager.success": "Got the correct trade with correction of %dms", From 70aaf2ad3b0c395aaa45559f726b14bb21d111bb Mon Sep 17 00:00:00 2001 From: RTTV Date: Wed, 19 Jun 2024 14:49:48 -0400 Subject: [PATCH 09/78] yo, check out this broken code --- .../clientcommands/ClientCommands.java | 36 + .../features/VillagerCracker.java | 21 +- .../features/VillagerRngSimulator.java | 216 +++- .../clientcommands/interfaces/IVillager.java | 2 +- .../commands/villager/VillagerMixin.java | 4 +- .../mixin/rngevents/LivingEntityMixin.java | 11 + .../assets/clientcommands/lang/en_us.json | 5 +- src/main/resources/villager_lattice_data.csv | 1002 +++++++++++++++++ src/main/resources/villager_lattice_data.nbt | Bin 0 -> 172231 bytes 9 files changed, 1239 insertions(+), 58 deletions(-) create mode 100644 src/main/resources/villager_lattice_data.csv create mode 100644 src/main/resources/villager_lattice_data.nbt diff --git a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java index beeb377d4..0ed2df87d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java +++ b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java @@ -23,6 +23,10 @@ import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.commands.CommandBuildContext; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.LongArrayTag; +import net.minecraft.nbt.NbtIo; import org.slf4j.Logger; import java.io.IOException; @@ -64,6 +68,38 @@ public class ClientCommands implements ClientModInitializer { @Override public void onInitializeClient() { + try { + String file = new String(ClientCommands.class.getResourceAsStream("/villager_lattice_data.csv").readAllBytes()); + file = file.substring(file.indexOf('\n') + 1); + CompoundTag root = new CompoundTag(); + ListTag lattice = new ListTag(); + ListTag lattice_inverse = new ListTag(); + ListTag offset = new ListTag(); + for (String line : file.split("\n")) { + String[] values = line.split(","); + long[] longs = new long[9]; + for (int i = 0; i < 9; i++) { + longs[i] = Long.parseLong(values[i]); + } + lattice.add(new LongArrayTag(longs)); + long[] inverse = new long[9]; + for (int i = 0; i < 9; i++) { + inverse[i] = Long.parseLong(values[i + 9]); + } + lattice_inverse.add(new LongArrayTag(inverse)); + long[] offsets = new long[2]; + for (int i = 0; i < 2; i++) { + offsets[i] = Long.parseLong(values[i + 11]); + } + offset.add(new LongArrayTag(offsets)); + } + root.put("lattices", lattice); + root.put("lattice_inverses", lattice_inverse); + root.put("offsets", offset); + NbtIo.write(root, Path.of("villager_lattice_data.nbt")); + } catch (IOException e) { + throw new RuntimeException(e); + } // Config configDir = FabricLoader.getInstance().getConfigDir().resolve("clientcommands"); try { diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index f28ac3528..0579a935b 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -1,6 +1,5 @@ package net.earthcomputer.clientcommands.features; -import com.mojang.logging.LogUtils; import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.interfaces.IVillager; import net.minecraft.client.Minecraft; @@ -15,6 +14,9 @@ import java.util.UUID; public class VillagerCracker { + // This value was computed by brute forcing all seeds + public static final float MAX_ERROR = 0x1.4p-24f; + @Nullable private static UUID villagerUuid = null; @Nullable @@ -59,21 +61,8 @@ public static void onSoundEventPlayed(ClientboundSoundPacket packet) { return; } - if (packet.getSound().value().getLocation().getPath().startsWith("item.armor.equip_")) { - long seed = packet.getSeed(); - long[] possible = CrackVillagerRngGen.getSeeds(seed).toArray(); - if (possible.length == 0) { - ClientCommandHelper.sendError(Component.translatable("commands.cvillager.crackFailed")); - } else { - ((IVillager) targetVillager).clientcommands_setCrackedRandom(RandomSource.create(possible[0] ^ 0x5deece66dL)); - // simulate a tick to advance it by one - ((IVillager) targetVillager).clientcommands_getCrackedRandom().simulateTick(); - ClientCommandHelper.sendFeedback("commands.cvillager.crackSuccess", Long.toHexString(possible[0])); - } - } - - if (packet.getSound().value().getLocation().getPath().equals("entity.villager.ambient")) { - ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(); + if (packet.getSound().value().getLocation().toString().equals("minecraft:entity.villager.ambient")) { + ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(packet.getPitch()); } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index c1ea4d383..37d57a129 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -1,10 +1,20 @@ package net.earthcomputer.clientcommands.features; +import com.seedfinding.latticg.math.component.BigFraction; +import com.seedfinding.latticg.math.component.BigMatrix; +import com.seedfinding.latticg.math.component.BigVector; +import com.seedfinding.latticg.math.lattice.enumerate.EnumerateRt; +import com.seedfinding.latticg.math.optimize.Optimize; +import com.seedfinding.mcseed.lcg.LCG; +import com.seedfinding.mcseed.rand.JRand; +import com.seedfinding.mcseed.rand.Rand; import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.PingCommand; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.minecraft.ChatFormatting; +import net.minecraft.nbt.*; import net.minecraft.network.chat.Component; +import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.item.ItemStack; @@ -12,23 +22,82 @@ import net.minecraft.world.level.levelgen.LegacyRandomSource; import org.jetbrains.annotations.Nullable; +import java.io.DataInputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.nio.file.Path; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.OptionalLong; import java.util.function.Predicate; +import java.util.stream.LongStream; public class VillagerRngSimulator { + private static final BigMatrix[] LATTICES; + private static final BigMatrix[] INVERSE_LATTICES; + private static final BigVector[] OFFSETS; + @Nullable private LegacyRandomSource random; private int ambientSoundTime; - private int waitingTicks = 0; private boolean madeSound = false; private int totalAmbientSounds = 0; private int callsAtStartOfBruteForce = 0; private int callsInBruteForce = 0; private int totalCalls = 0; + private float firstPitch = Float.NaN; + private int ticksBetweenSounds = 0; + private float secondPitch = Float.NaN; @Nullable private ItemStack activeGoalResult = null; + static { + try { + CompoundTag root = NbtIo.read(new DataInputStream(Objects.requireNonNull(VillagerRngSimulator.class.getResourceAsStream("/villager_lattice_data.nbt")))); + ListTag lattices = root.getList("lattices", Tag.TAG_LONG_ARRAY); + LATTICES = new BigMatrix[lattices.size()]; + ListTag lattice_inverses = root.getList("lattice_inverses", Tag.TAG_LONG_ARRAY); + INVERSE_LATTICES = new BigMatrix[lattices.size()]; + ListTag offsets = root.getList("offsets", Tag.TAG_LONG_ARRAY); + OFFSETS = new BigVector[offsets.size()]; + for (int i = 0; i < lattices.size(); i++) { + long[] lattice = lattices.getLongArray(i); + BigMatrix matrix = new BigMatrix(3, 3); + matrix.set(0, 0, new BigFraction(lattice[0])); + matrix.set(0, 1, new BigFraction(lattice[1])); + matrix.set(0, 2, new BigFraction(lattice[2])); + matrix.set(1, 0, new BigFraction(lattice[3])); + matrix.set(1, 1, new BigFraction(lattice[4])); + matrix.set(1, 2, new BigFraction(lattice[5])); + matrix.set(2, 0, new BigFraction(lattice[6])); + matrix.set(2, 1, new BigFraction(lattice[7])); + matrix.set(2, 2, new BigFraction(lattice[8])); + LATTICES[i] = matrix; + } + for (int i = 0; i < lattice_inverses.size(); i++) { + long[] lattice_inverse = lattice_inverses.getLongArray(i); + BigMatrix matrix = new BigMatrix(3, 3); + matrix.set(0, 0, new BigFraction(lattice_inverse[0], 1L << 48)); + matrix.set(0, 1, new BigFraction(lattice_inverse[1], 1L << 48)); + matrix.set(0, 2, new BigFraction(lattice_inverse[2], 1L << 48)); + matrix.set(1, 0, new BigFraction(lattice_inverse[3], 1L << 48)); + matrix.set(1, 1, new BigFraction(lattice_inverse[4], 1L << 48)); + matrix.set(1, 2, new BigFraction(lattice_inverse[5], 1L << 48)); + matrix.set(2, 0, new BigFraction(lattice_inverse[6], 1L << 48)); + matrix.set(2, 1, new BigFraction(lattice_inverse[7], 1L << 48)); + matrix.set(2, 2, new BigFraction(lattice_inverse[8], 1L << 48)); + INVERSE_LATTICES[i] = matrix; + } + for (int i = 0; i < offsets.size(); i++) { + long[] offset = offsets.getLongArray(i); + OFFSETS[i] = new BigVector(0, offset[0], offset[1]); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + } + public VillagerRngSimulator(@Nullable LegacyRandomSource random, int ambientSoundTime) { this.random = random; this.ambientSoundTime = ambientSoundTime; @@ -36,18 +105,21 @@ public VillagerRngSimulator(@Nullable LegacyRandomSource random, int ambientSoun public VillagerRngSimulator copy() { VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : new LegacyRandomSource(random.seed.get() ^ 0x5deece66dL), ambientSoundTime); - that.waitingTicks = this.waitingTicks; that.madeSound = this.madeSound; that.totalAmbientSounds = this.totalAmbientSounds; that.callsAtStartOfBruteForce = this.callsAtStartOfBruteForce; that.callsInBruteForce = this.callsInBruteForce; that.totalCalls = this.totalCalls; + that.firstPitch = this.firstPitch; + that.ticksBetweenSounds = this.ticksBetweenSounds; + that.secondPitch = this.secondPitch; that.activeGoalResult = this.activeGoalResult; return that; } public void simulateTick() { if (random == null) { + ambientSoundTime++; return; } @@ -68,11 +140,6 @@ public boolean shouldInteractWithVillager() { } public void simulateBaseTick() { - if (waitingTicks > 0) { - waitingTicks--; - return; - } - if (random == null) { return; } @@ -146,10 +213,6 @@ public int getTotalCalls() { } public CrackedState getCrackedState() { - if (random == null) { - return CrackedState.UNCRACKED; - } - if (totalAmbientSounds == 0) { return CrackedState.PENDING_FIRST_AMBIENT_SOUND; } @@ -158,6 +221,10 @@ public CrackedState getCrackedState() { return CrackedState.PENDING_SECOND_AMBIENT_SOUND; } + if (random == null) { + return CrackedState.UNCRACKED; + } + return CrackedState.CRACKED; } @@ -171,6 +238,9 @@ public void reset() { totalCalls = 0; callsAtStartOfBruteForce = 0; callsInBruteForce = 0; + firstPitch = Float.NaN; + ticksBetweenSounds = 0; + secondPitch = Float.NaN; activeGoalResult = null; } @@ -180,41 +250,115 @@ public String toString() { "seed=" + (random == null ? "null" : random.seed.get()) + ']'; } - public void onAmbientSoundPlayed() { + public void onAmbientSoundPlayed(float pitch) { if (totalAmbientSounds == 0) { - if (random == null) { - return; - } - totalAmbientSounds++; + firstPitch = pitch; ambientSoundTime = -80; - random.nextFloat(); - random.nextFloat(); madeSound = true; ClientCommandHelper.addOverlayMessage(getCrackedState().getMessage(true), 100); return; } - if (!madeSound) { - int i = 0; - VillagerRngSimulator rng = this.copy(); - do { - rng.simulateTick(); - i++; - } while (!rng.madeSound); - - if (i <= PingCommand.getLocalPing() / 50 + 5) { - for (int j = 0; j < i; j++) { - simulateTick(); - } - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.resynced", i).withStyle(ChatFormatting.GREEN), 100); + if (totalAmbientSounds == 1) { + totalAmbientSounds++; + ticksBetweenSounds = ambientSoundTime - (-80); + secondPitch = pitch; + ambientSoundTime = -80; + madeSound = true; + OptionalLong seed = crackSeed(); + if (seed.isPresent()) { + random = new LegacyRandomSource(seed.getAsLong() ^ 0x5deece66dL); + // simulate a tick to advance it by one + simulateTick(); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.crackSuccess", Long.toHexString(seed.getAsLong())).withStyle(ChatFormatting.GREEN), 100); } else { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); reset(); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.crackFailed").withStyle(ChatFormatting.RED), 100); } - } else if (totalAmbientSounds++ == 1) { - ClientCommandHelper.addOverlayMessage(getCrackedState().getMessage(true), 100); + return; } + + if (!madeSound) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); + reset(); + } + } + + public OptionalLong crackSeed() { + float first = (firstPitch - 1.0f) / 0.2f; + float second = (secondPitch - 1.0f) / 0.2f; + float firstMin = Math.max(-1.0f + 0x1.0p-24f, first - VillagerCracker.MAX_ERROR); + float firstMax = Math.min(1.0f - 0x1.0p-24f, first + VillagerCracker.MAX_ERROR); + float secondMin = Math.max(-1.0f + 0x1.0p-24f, second - VillagerCracker.MAX_ERROR); + float secondMax = Math.min(1.0f - 0x1.0p-24f, second + VillagerCracker.MAX_ERROR); + int callsBetweenSounds2m = (ticksBetweenSounds - 1) * 2; + int callsBetweenSounds = ticksBetweenSounds * 2; + int callsBetweenSounds2p = (ticksBetweenSounds + 1) * 2; + OptionalLong seed2m = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, callsBetweenSounds2m); + OptionalLong seed = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, callsBetweenSounds); + OptionalLong seed2p = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, callsBetweenSounds2p); + System.out.println("Seed 2M: " + seed2m); + System.out.println("Seed: " + seed); + System.out.println("Seed 2P: " + seed2p); + return seed; + } + + private OptionalLong crackSeed0(float firstPitch, float secondPitch, float firstMin, float firstMax, float secondMin, float secondMax, int callsBetweenSounds) { + System.out.printf("%f, %f, %f, %f, %f, %f, %d%n", firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, callsBetweenSounds); + + if (!(80 <= callsBetweenSounds && callsBetweenSounds - 80 < LATTICES.length)) { + return OptionalLong.empty(); + } + + BigMatrix lattice = LATTICES[callsBetweenSounds - 80]; + BigMatrix inverseLattice = INVERSE_LATTICES[callsBetweenSounds - 80]; + BigVector vector = OFFSETS[callsBetweenSounds - 80]; + + firstMax = Math.nextUp(firstMax); + secondMax = Math.nextUp(secondMax); + + long firstMinLong = (long) Math.ceil(firstMin * 0x1.0p24f); + long firstMaxLong = (long) Math.ceil(firstMax * 0x1.0p24f) - 1; + long secondMinLong = (long) Math.ceil(secondMin * 0x1.0p24f); + long secondMaxLong = (long) Math.ceil(secondMax * 0x1.0p24f) - 1; + + long firstMinSeedDiff = (firstMinLong << 24) - 0xFFFFFF; + long firstMaxSeedDiff = (firstMaxLong << 24) + 0xFFFFFF; + long secondMinSeedDiff = (secondMinLong << 24) - 0xFFFFFF; + long secondMaxSeedDiff = (secondMaxLong << 24) + 0xFFFFFF; + + long firstCombinationModMin = firstMinSeedDiff & 0xFFFFFFFFFFFFL; + long firstCombinationModMax = firstMaxSeedDiff & 0xFFFFFFFFFFFFL; + long secondCombinationModMin = secondMinSeedDiff & 0xFFFFFFFFFFFFL; + long secondCombinationModMax = secondMaxSeedDiff & 0xFFFFFFFFFFFFL; + + firstCombinationModMax = firstCombinationModMax < firstCombinationModMin ? firstCombinationModMax + (1L << 48) : firstCombinationModMax; + secondCombinationModMax = secondCombinationModMax < secondCombinationModMin ? secondCombinationModMax + (1L << 48) : secondCombinationModMax; + + Optimize optimize = Optimize.Builder.ofSize(3) + .withLowerBound(0, 0) + .withUpperBound(0, 0xFFFFFFFFFFFFL) + .withLowerBound(1, firstCombinationModMin) + .withUpperBound(1, firstCombinationModMax) + .withLowerBound(2, secondCombinationModMin) + .withUpperBound(2, secondCombinationModMax) + .build(); + + System.out.printf("%s, %s, %d, %d, %d, %d, %s, %s%n", lattice, vector, firstCombinationModMin, firstCombinationModMax, secondCombinationModMin, secondCombinationModMax, inverseLattice, inverseLattice.multiply(vector)); + + return EnumerateRt.enumerate(lattice, vector, optimize, inverseLattice, inverseLattice.multiply(vector)).mapToLong(vec -> vec.get(0).getNumerator().longValue() & ((1L << 48) - 1)).flatMap(seed -> { + System.out.println(seed); + JRand rand = JRand.ofInternalSeed(seed); + float simulatedFirstPitch = (rand.nextFloat() - rand.nextFloat()) * 0.2f + 1.0f; + rand.advance(callsBetweenSounds); + float simulatedSecondPitch = (rand.nextFloat() - rand.nextFloat()) * 0.2f + 1.0f; + if (simulatedFirstPitch == firstPitch && simulatedSecondPitch == secondPitch) { + return LongStream.of(rand.getSeed()); + } else { + return LongStream.empty(); + } + }).findAny(); } public enum CrackedState { @@ -230,8 +374,8 @@ public boolean isCracked() { public Component getMessage(boolean addColor) { return switch (this) { case UNCRACKED -> Component.translatable("commands.cvillager.noCrackedVillagerPresent").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); - case PENDING_FIRST_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 0).withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); - case PENDING_SECOND_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 50).withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); + case PENDING_FIRST_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 0).withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); + case PENDING_SECOND_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 50).withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); case CRACKED -> Component.translatable("commands.cvillager.inSync", 100).withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); }; } diff --git a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java index 6b1d8eb51..61c5ca551 100644 --- a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java +++ b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java @@ -15,7 +15,7 @@ public interface IVillager { VillagerRngSimulator clientcommands_getCrackedRandom(); - void clientcommands_onAmbientSoundPlayed(); + void clientcommands_onAmbientSoundPlayed(float pitch); void clientcommands_onServerTick(); diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index d2ffdace7..8cd483aa7 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -47,8 +47,8 @@ public void clientcommands_setCrackedRandom(@Nullable RandomSource random) { } @Override - public void clientcommands_onAmbientSoundPlayed() { - rng.onAmbientSoundPlayed(); + public void clientcommands_onAmbientSoundPlayed(float pitch) { + rng.onAmbientSoundPlayed(pitch); } @Override diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java index 2dc030fbe..ab420840a 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java @@ -2,14 +2,17 @@ import com.google.common.base.Objects; import net.earthcomputer.clientcommands.features.PlayerRandCracker; +import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.util.CUtil; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; +import net.minecraft.sounds.SoundEvent; import net.minecraft.tags.BlockTags; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; +import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.Enchantments; @@ -127,4 +130,12 @@ private void testSoulSpeed(CallbackInfo ci) { private boolean isThePlayer() { return (Object) this instanceof LocalPlayer; } + + @Inject(method = "makeSound", at = @At("TAIL")) + private void onMakeSound(SoundEvent sound, CallbackInfo ci) { + Villager targetVillager = VillagerCracker.getVillager(); + if (!level().isClientSide && targetVillager != null && targetVillager.getUUID().equals(uuid)) { + System.out.println("(Server) Post-call seed: 0x" + Long.toHexString(((LegacyRandomSource) random).seed.get())); + } + } } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 3a50a7ff6..db2c114a3 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -244,7 +244,7 @@ "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %d calls.", "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls.", - "commands.cvillager.crackFailed": "Failed to crack villager seed", + "commands.cvillager.crackFailed": "Failed to crack villager seed, re-cracking.", "commands.cvillager.crackSuccess": "Villager RNG cracked: %d", "commands.cvillager.goalAdded": "Added goal successfully.", "commands.cvillager.inSync": "Your villager's RNG is %d%% synced", @@ -253,8 +253,7 @@ "commands.cvillager.noCrackedVillagerPresent": "There was no cracked villager available to use", "commands.cvillager.noProfession": "The targeted villager has no profession.", "commands.cvillager.notAVillager": "Target was not a villager", - "commands.cvillager.outOfSync": "Your Villager's RNG was out of sync, please re-crack.", - "commands.cvillager.resynced": "Your Villager's RNG was resynced, skipped %d ticks.", + "commands.cvillager.outOfSync": "Your Villager's RNG was out of sync, re-cracking.", "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals.", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", "commands.cvillager.success": "Got the correct trade with correction of %dms", diff --git a/src/main/resources/villager_lattice_data.csv b/src/main/resources/villager_lattice_data.csv new file mode 100644 index 000000000..fb2b4bd6b --- /dev/null +++ b/src/main/resources/villager_lattice_data.csv @@ -0,0 +1,1002 @@ +l00,l01,l02,l10,l11,l12,l20,l21,l22,li00,li01,li02,li10,li11,li12,li20,li21,li22,o1,o2 +-3476554084835,28255265391812,-42113478785852,15148148,25330448,25330448,-27574892,28215696,28215696,0,7053924,-6332612,4,4474174,1953561,-4,2419549,1833476,281197612767569,172263588355769 +12408218695821,-33144088090201,11237077975074,-7074252,-21222756,81737864,5975924,17927772,90107144,12,-11325962,8777495,-4,-3733608,3885657,0,1493981,1768563,281197612767569,201206084637665 +1602613649463,-12026233802062,70368744177664,-22952740,-11156792,0,8610812,-44867448,0,0,-11216862,2789198,0,-2152703,-5738185,4,-112445,-1044196,281197612767569,161003732889929 +-12329864442980,16801320061067,-70368744177664,25640560,20354604,0,17921136,-29684308,0,0,7421077,5088651,0,4480284,-6410140,-4,-230588,-2422115,281197612767569,249134577176817 +32622245201238,37746498976426,7745155264947,-590504,590504,42179276,26476568,-26476568,15473964,4,-2803635,5640098,4,1064856,-4904721,0,6619142,147626,281197612767569,836491779289 +23509883930646,-16485223278971,-46858860247018,18483288,26453524,18483288,19502296,-33002540,19502296,4,6636331,3321364,0,4875574,-4620822,-4,1614304,3292017,281197612767569,70648974266113 +6895670548764,-35890391433844,-2246799087477,-2263952,-11319760,-197781972,4560624,22803120,-98893748,20,-12791792,25128483,-4,-2386329,4863402,0,-1140156,-565988,281197612767569,230155805389161 +19872089964001,50496654213663,-12819105457601,-22195324,22195324,-15102724,2233988,-2233988,-49206788,4,-8929447,1698598,4,3372250,-2077083,0,-558497,-5548831,281197612767569,84128279961105 +17174215164515,-53194529013149,-7169935869527,2825612,2825612,51192484,-21444756,-21444756,9941060,4,2424967,-9602632,-4,60298,-3195489,0,5361189,706403,281197612767569,272644608294649 +20352156869675,21101248121487,28915339186502,-18119508,-18936260,37055768,-24931220,36082428,-11151208,4,-4542642,-4723231,4,-1754840,4540711,4,4477965,10834,281197612767569,269324635098657 +8728276822537,-61640467355127,-18950317931798,-10001372,-10001372,43590568,-20691452,-20691452,-22391704,4,-3510527,-10219282,-4,-2087399,-678360,0,5172863,-2500343,281197612767569,87559348770185 +14749827991492,-55618916186172,-18090665508531,-18575600,-18575600,-25808588,10136848,10136848,-46527820,4,-9845313,3905856,-4,-1786642,2546291,0,-2534212,-4643900,281197612767569,47732792454961 +-18192233826070,-15513661186801,-52176510351594,22477736,18765884,-22477736,18664168,-34507492,-18664168,-4,5367905,4717472,0,4666042,-5619434,-4,-3258968,26001,281197612767569,166573851575577 +-18548560215540,30996920595025,39371823582639,-34383824,5072196,-5072196,10831152,31147268,-31147268,0,-7786817,1268049,4,-537507,5143746,4,-3245295,-3452210,281197612767569,28772858958145 +6635313999154,-34403094847883,-35965649329781,-28201784,19596756,-19596756,-18696824,-26931020,26931020,0,-6732755,-4899189,-4,1754144,-4065463,-4,-2920062,2984983,281197612767569,84219543494057 +679467483691,-70368744177664,-26173736256862,17628332,0,16327304,3186860,0,-60917112,0,15229278,4081826,-4,-149288,1678633,0,796715,-4407083,281197612767569,54989266732113 +-17723997367094,52644746810570,-17284716852249,-15668440,-15668440,-18041956,-6751384,-6751384,64083708,-4,-11571099,-4336580,4,-4449828,-173909,0,-1687846,3917110,281197612767569,11537315573561 +22094520762725,48274223414939,29636162462236,-5385836,5385836,39753840,-27544876,27544876,-5734544,4,-3883667,-6250894,4,-2450031,3687566,0,6886219,-1346459,281197612767569,64617847461985 +-33507228868266,-36861515309398,-15627295282179,-3642024,3642024,44047348,25676440,-25676440,-1394604,-4,-1242903,5566168,-4,-1591554,-5445669,0,6419110,910506,281197612767569,24474283264457 +-5503785216671,-28825883512764,-70368744177664,-3886716,-42323696,0,26397188,-2231536,0,0,-557884,10580924,0,-6599297,-971679,-4,2746973,-429532,281197612767569,126472728714609 +16928453150971,16724763738115,36715527288578,29022188,-32599028,3576840,-15795892,-21051796,36847688,4,4935418,-4464739,4,-4276504,-3570529,4,-327531,3685018,281197612767569,232501607923033 +-25573063045165,44795681132499,15083705793408,10654540,10654540,-36311552,20919692,20919692,34377216,-4,4349958,6349803,4,4244346,2728085,0,-5229923,2663635,281197612767569,253370774610817 +24744389011837,20879966153990,-8270689147546,-15396364,30792728,-17351272,-6032172,12064344,66329560,8,-5274854,-382332,4,5653768,1977743,0,-1508043,3849091,281197612767569,223942364092905 +-19050704186021,51318039991643,5496886509440,-11826836,-11826836,40959488,-16408468,-16408468,-38371840,-4,-6675450,-7698629,4,-2917510,-2541243,0,4102117,-2956709,281197612767569,215005482154641 +-12852700529477,-18957942059756,8424651188627,-2382100,9528400,175897164,5242316,-20969264,85551148,-16,-5134435,12132239,-4,4063338,-7960513,0,1310579,595525,281197612767569,245876592668537 +-19801117297829,-50567626879835,-16090944486380,-22675092,22675092,22167632,9941804,-9941804,39934288,-4,-7742625,2686210,-4,2240947,-2855698,0,2485451,5668773,281197612767569,3981803975329 +-23853307764859,46515436412805,8135371541155,18074132,18074132,-16695668,-11756940,-11756940,-51433172,-4,8159835,-3281450,4,4698458,-892467,0,-2939235,-4518533,281197612767569,270412568055305 +-33873695926765,-36495048250899,7503894385005,15248460,-15248460,-26480204,19822796,-19822796,39413044,-4,4581696,3839841,-4,-5271565,-2780210,0,-4955699,3812115,281197612767569,169123345062833 +19681637176475,-20773331307312,50687107001189,7439980,-33516736,-7439980,-30447924,-14164672,30447924,4,303620,-6584669,0,-7611981,-1859995,4,-3237548,1794515,281197612767569,105858529625497 +32090285076227,-38278459101437,4250048274206,20336652,20336652,-39959432,-13582004,-13582004,-28675848,4,4104775,-5127112,-4,3064187,-4862746,0,-3395501,-5084163,281197612767569,30325612234177 +32873540801129,-37495203376535,16903558321289,-14580316,-14580316,-34795996,11024900,11024900,-50909564,4,-6119565,5510764,-4,-6607826,3188235,0,-2756225,-3645079,281197612767569,40235896284713 +19179198791735,-51189545385929,-13622850413044,-23706404,-23706404,-4274128,-6908196,-6908196,46247984,4,-8745085,370044,-4,-2816911,-1438576,0,-1727049,5926601,281197612767569,277256898035921 +-2745204197029,28056858011329,42311886166335,23009644,17987332,-17987332,-18170036,34727588,-34727588,0,8681897,-4496833,4,3070052,3283427,4,-1472457,-2468984,281197612767569,236533133459385 +-21462494033268,48906250144396,-53992773633,21723696,21723696,15844348,-6597328,-6597328,47016380,-4,8167826,-2757121,4,3586269,-1203966,0,1649332,5430924,281197612767569,185701192228065 +-27783654384506,42585089793158,19328056851003,23370264,23370264,-14115604,15359320,15359320,38899596,-4,4830543,3740354,4,4894356,-211453,0,-3839830,5842566,281197612767569,214329415918153 +-8140355554195,62228388623469,4706998051577,11042228,11042228,50563044,8988212,8988212,-60805532,-4,13593172,10993805,4,1608211,1646956,0,2247053,-2760557,281197612767569,216453714946545 +-3179689164013,22396351671217,-6345024530712,-15769524,-5256508,47430560,-3925332,-1308444,-202385248,-4,-16132849,-3655454,12,-2197765,-891278,0,327111,-1314127,281197612767569,100794912120281 +17741298711947,-596450670124,-9117733830418,2255404,-9021616,248482744,-2581396,10325584,214803000,16,-120698,818774,4,-13455362,15734865,0,645349,563851,281197612767569,54581474703361 +-8111320699039,62257423478625,18390756168318,20257156,20257156,-20934152,-9436188,-9436188,-45828808,-4,9520011,-5953818,4,1937191,720280,0,-2359047,-5064289,281197612767569,145930115875433 +-32988701444515,-37380042733149,17238095250666,4244852,-4244852,-44160088,-23719820,23719820,-18476632,-4,1001058,-6124449,-4,-3618100,4915573,0,-5929955,-1061213,281197612767569,88765010876177 +-23503147051142,9327188155085,46865597126522,16266728,-32073932,16266728,25817640,18308948,25817640,-4,2192926,5879339,0,-6454410,4066682,4,2384311,2139144,281197612767569,238248515936249 +12826417145930,28771163515867,841208670912,20855080,-10427540,-8148224,-3044952,1522476,-106784000,4,10919552,-801713,8,-4856896,433630,0,-380619,-2606885,281197612767569,237039169427233 +-17348149709099,-53020594468565,-7653614457209,23521108,-23521108,-17973732,-7288908,7288908,-42297796,-4,8165702,-2746093,-4,-2408747,1747340,0,-1822227,-5880277,281197612767569,19700769916553 +-21178028960358,19026795343725,30163919873581,-30036376,-35624524,5588148,20416872,-13269196,33686068,-4,-3699046,4195399,4,-4722471,-2798362,4,381747,4710732,281197612767569,175053049989169 +13374320705058,-28261601907977,56994423472606,25637000,520156,-25637000,-3848504,43838908,3848504,4,9263126,2468769,0,962126,6409250,4,-1696601,2598808,281197612767569,239427853338137 +-8404370651775,32454674210874,-37914069966790,-13962748,-38184728,-38184728,-24172092,14531176,14531176,0,-3632794,-9546182,4,-3689805,740620,-4,-2353218,2750067,281197612767569,10574924298817 +-15056862021332,40255020135000,15230839426201,9155760,18311520,60272228,10246448,20492896,-55519548,-8,9048991,7628955,4,2415448,3719551,0,2561612,-2288940,281197612767569,2014714097321 +-5785566913775,64583177263889,-8462600387277,15337540,15337540,36890828,-9332668,-9332668,50960588,-4,11412091,-8925562,4,1328056,-297145,0,2333167,3834385,281197612767569,276792004377937 +21455739128394,16596470215339,32316534833931,-31080152,31964844,-884692,10905960,25009292,-35915252,4,-4989005,3722092,4,3989808,3500919,4,1263318,-4269119,281197612767569,134145913458745 +-12362671005334,14624424335071,-70368744177664,20618664,34865020,0,-25726936,11103036,0,0,2775759,-8716255,0,6431734,5154666,-4,849022,2602579,281197612767569,38206713487713 +-3621173379697,-9761231300379,-70368744177664,-31991236,-4509804,0,11229276,-33611020,0,0,-8402755,1127451,0,-2807319,-7997809,-4,821824,1051401,281197612767569,210403630463689 +20435175485779,4355960904628,49933568691885,-12052148,37822160,12052148,30156492,-1218352,-30156492,4,-250551,6523126,0,7539123,3013037,4,-555139,-2932414,281197612767569,133260978091633 +-8472462464277,-30201394404272,40167349773392,32481196,6967616,6967616,-947444,-34866368,-34866368,0,8716592,1741904,-4,-1184689,-4844894,4,947828,-3275405,281197612767569,32902074564185 +26173939142337,44194805035327,-11790061081703,10163972,-10163972,42412644,-25675836,25675836,3632420,4,1645808,-6233537,4,737703,4369624,0,6418959,2540993,281197612767569,4324181822593 +-7832741307919,-14748511539107,-70368744177664,-16153660,37858676,0,18523684,26286164,0,0,-6571541,9464669,0,4630921,4038415,-4,-239112,-1899919,281197612767569,167945336417001 +-10156086704332,-16974261408117,-70368744177664,31313104,12201516,0,-10493744,31867180,0,0,7966795,-3050379,0,2623436,7828276,-4,-1782643,-1448076,281197612767569,238788538725265 +23851175764897,46517568412767,-11109912840107,18475652,-18475652,37940564,9943332,-9943332,-40520588,4,7089045,5540954,4,-3041102,-3944187,0,2485833,-4618913,281197612767569,241295234535545 +5659191690264,64709552487400,15231484533969,1421408,-1421408,-67760316,16526944,-16526944,4241540,4,1869431,15500808,4,809046,-1439271,0,-4131736,355352,281197612767569,25287740160929 +30793090984886,39575653192778,16247530820149,-15198504,15198504,30921940,-10177000,10177000,-53374156,4,-8091903,-3470354,4,5251636,4260131,0,2544250,-3799626,281197612767569,7070136893193 +-6192811350418,-35404546597997,-34964197579667,15081912,-26951092,26951092,-30204232,-20677940,20677940,0,5169485,-6737773,-4,-4206844,-1280483,-4,3344214,2489995,281197612767569,257153099199665 +34843136834195,-13292841254721,-35525607343469,-1622452,-37411076,-1622452,-29511252,13468636,-29511252,4,-3093596,-4645117,0,-7377813,405613,-4,-273563,-4707652,281197612767569,224597960541849 +19985804772941,20639039344121,-50382939404723,-5028556,-40029212,-5028556,28079092,-381020,28079092,4,1990687,7533792,0,-7019773,-1257139,-4,-2085942,2473511,281197612767569,186890417499841 +30273884605767,40094859571897,19575823284985,-3524324,3524324,-53286940,20771516,-20771516,-5405116,4,674668,7835595,4,2025947,-5486140,0,-5192879,-881081,281197612767569,32475994847017 +34229814023149,-1460733208451,36138930154515,22739892,24628724,-22739892,18494900,-29480972,-18494900,4,3881080,3044103,0,4623725,-5684973,4,-3489163,-3113078,281197612767569,270972026288593 +-3162183131148,-5517780108997,-70368744177664,-5230640,36149484,0,28927056,15333068,0,0,-3833267,9037371,0,7231764,1307660,-4,-394803,-508652,281197612767569,280712319508665 +9582106252206,32040319168840,713163497639,3790520,-15162080,-137296228,5432888,-21731552,100246108,16,11466083,15590025,4,-3398861,-4683508,0,-1358222,947630,281197612767569,56171242137057 +26905955367752,43462788809912,-7898174980133,16239904,-16239904,33305452,-18910176,18910176,30547468,4,5247479,-4687032,4,-2389388,3639331,0,4727544,4059976,281197612767569,47812984263497 +24333353040089,-21702038097486,-15336517126085,16473956,32947912,-551700,-902684,-1805368,-68314004,8,5168719,-1837745,-4,5954891,849910,0,-225671,-4118489,281197612767569,165426748982001 +613321008509,70368744177664,28060760903125,-21822988,0,-14859436,8490388,0,-45811212,0,-11452803,3714859,4,946243,2143196,0,-2122597,-5455747,281197612767569,96329145163481 +18899295738082,-51469448439582,14674183751909,3578760,3578760,48951188,-20805368,-20805368,30025044,4,4405616,-9137601,-4,3100645,-3100196,0,5201342,894690,281197612767569,227274668351745 +6481089188274,27444005862565,-70368744177664,27279048,3915412,0,1152392,41438836,0,0,10359709,-978853,0,-288098,6819762,-4,841789,2569572,281197612767569,177352443368297 +-9636296503703,-60732447673961,-7679793694213,-22055516,22055516,9935852,1661092,-1661092,50300140,-4,-10898331,1542044,-4,1676704,-941919,0,415273,5513879,281197612767569,275293441167377 +24582872340535,-45785871837129,10245774104137,6399196,6399196,-50719452,22084412,22084412,904900,4,951074,8017301,-4,-724849,4662562,0,-5521103,1599799,281197612767569,104996193714425 +9403758898333,20321661759777,5097394581485,564852,-188284,-262247500,12853428,-4284476,12251636,4,962122,18930085,12,-176543,-8771620,0,-1071119,47071,281197612767569,45666356715553 +-3488607244915,5769032448000,70368744177664,-25632204,10805248,0,-10590316,-39460864,0,0,-9865216,-2701312,0,2647579,-6408051,4,-706135,391430,281197612767569,209045990455177 +-18121940115266,-16002923831866,-15960046498823,-2831624,8494872,-119919644,-8332296,24996888,44742500,-12,-1126421,-7299560,-4,3353068,7560117,0,-2083074,707906,281197612767569,215306691060017 +-20436497345775,-27710341425286,49932246831889,387140,-39176728,387140,28800868,-6260952,28800868,-4,1724695,6911642,0,-7200217,96785,4,-3289933,2882540,281197612767569,263920618309401 +-33910613674001,36458130503663,26272721740064,24200124,24200124,-17562496,11439100,11439100,38222976,-4,3883123,4533614,4,5672621,-142990,0,-2859775,6050031,281197612767569,11338940015425 +26932125592071,-43436618585593,-9441637397437,1027100,1027100,-43530996,-25855044,-25855044,-393428,4,-806554,-6752063,-4,904911,-4130686,0,-6463761,-256775,281197612767569,230327819878313 +3153761480983,22404994232227,-7944188926622,1607772,-535924,-260321912,-12766116,4255372,-33835640,4,2573166,-20736367,12,-739412,2871377,0,-1063843,-133981,281197612767569,150924661962321 +-127382841341,30128239667705,-40240504509959,30864396,-11164700,-11164700,-1667860,37082244,37082244,0,9270561,2791175,4,255224,4417519,-4,161741,3298580,281197612767569,147308842479929 +-19795357393026,-50573386784638,25439182260535,-16988680,16988680,-38836004,-14727816,14727816,32605852,-4,-7189456,-5442367,-4,962007,4266634,0,-3681954,4247170,281197612767569,227951711136353 +-916585133688,34726079521988,-16082008913045,10749472,5374736,-73588308,-4492000,-2246000,-178728884,-4,22178432,-8771639,8,325357,-853799,0,-561500,-1343684,281197612767569,130622231260105 +-5010434819705,25456794242480,70368744177664,25422364,-21399872,0,9534876,36261568,0,0,9065392,5349968,0,-2383719,6355591,4,1507820,-1918285,281197612767569,94716040662897 +-21378440761279,48990303416385,17732767507628,-24404732,-24404732,-3186000,-2092252,-2092252,-46407632,-4,-7945369,-982966,4,-3656539,1779466,0,523063,-6101183,281197612767569,59410052808537 +-16742815739213,34807977361034,35560766816630,10428108,28807720,-28807720,-32227060,18940328,-18940328,0,4735082,-7201930,4,5198094,-396095,4,-2858671,-3003122,281197612767569,128590283879809 +-10801064657545,-15860174167770,70368744177664,-9881124,34876568,0,-31458692,-2907432,0,0,-726858,-8719142,0,7864673,-2470281,4,1661025,-1895090,281197612767569,233935437429737 +-18909385936075,-4462150324542,51459358241589,1071316,-37981432,1071316,30144980,-17781496,30144980,-4,-2772939,6926796,0,-7536245,267829,4,-1672435,2568562,281197612767569,220998906113169 +-3927991906303,-26956744032864,-43412000144800,-32695292,14251648,-14251648,15444644,27703936,-27703936,0,-6925984,3562912,-4,2768643,4843726,-4,-1092518,-3330097,281197612767569,118351926735225 +34291562109338,36077182068326,-16423940447453,12303976,-12303976,46833804,-15528216,15528216,32400460,4,5058893,-5284846,4,-3041222,6423605,0,3882054,3075994,281197612767569,30410301506721 +20313468230605,18367437957077,50055275947059,-12870860,36481876,12870860,-27397484,-9819724,27397484,4,-3534064,-5647769,0,6849371,-3217715,4,-1079133,3472700,281197612767569,197887976288265 +-6909306135499,9687492742302,70368744177664,4586708,42007160,0,25494612,-11978888,0,0,2994722,10501790,0,6373653,-1146677,4,-583402,1189001,281197612767569,249056884166065 +6530893668537,-22977527047370,70368744177664,-22118684,26268888,0,12426500,36144536,0,0,-9036134,6567222,0,3106625,5529671,4,1853047,1196104,281197612767569,270688257214361 +17221772683051,18703426128511,-7098089974594,-4222804,12668412,-130770184,5210092,-15630276,-105279624,12,-7389768,8369941,4,6310046,-8107535,0,-1302523,-1055701,281197612767569,145716686985153 +-15965891122865,-38436961931934,1769367289713,-6256324,12512648,73013700,-13153828,26307656,-26451676,-8,-3446751,-10049079,-4,1583084,4102173,0,3288457,-1564081,281197612767569,45654725412905 +11629984837236,58738759340428,-5620070242189,-19830320,19830320,8222156,6431184,-6431184,54110156,4,-11163407,2111758,4,2364132,56219,0,1607796,4957580,281197612767569,45336814138065 +-7276301136861,582292548137,-70368744177664,-13548404,-33299292,0,20068204,-33778364,0,0,-8444591,8324823,0,-5017051,-3387101,-4,831676,-888835,281197612767569,107494392234425 +-3002018962971,7281994748398,-70368744177664,4477844,-43528264,0,23803604,20047672,0,0,5011918,10882066,0,-5950901,1119461,-4,-829634,-348397,281197612767569,172400695471841 +15338740654831,16151424388080,38878579134753,-8785988,36270016,-27484028,-33940516,11964864,21975652,4,391647,-6586848,4,5885560,284159,4,-2599569,2480656,281197612767569,170300705096777 +-5189742925446,12005744571521,70368744177664,-29721112,-12931580,0,12234472,-32558972,0,0,-8139743,3232895,0,-3058618,-7430278,4,-78475,1506122,281197612767569,130471013833713 +-13558329224802,-56810414952862,6449762708569,-17494408,17494408,-32821916,13869624,-13869624,-38336380,-4,-8055286,6223615,-4,1528809,-1981864,0,-3467406,-4373602,281197612767569,54346476658649 +-8103459437403,21679181535842,48689562641822,32562836,-1269368,1269368,-12396460,35059464,-35059464,0,8764866,317342,4,3153677,5669266,4,54562,-2471443,281197612767569,265587983321601 +2551656855136,-67817087322528,-17442845956859,-6203008,-6203008,-83894252,9633152,9633152,-51222540,4,-12938248,19828639,-4,132613,1144924,0,-2408288,-1550752,281197612767569,10830599365737 +-22545202520337,47823541657327,3230998561840,-14491716,-14491716,32460992,-20586308,-20586308,-31579968,-4,-5129236,-5681579,4,-2765756,-2433669,0,5146577,-3622929,281197612767569,162340229744913 +-8368577286671,-62000166890993,29514214468310,-470076,470076,65770328,17119844,-17119844,-165608,-4,1831589,14536444,-4,1790187,-1906138,0,4279961,117519,281197612767569,81430600770041 +34678198748601,-35690545429063,3306315941498,-650524,-650524,-43060760,25895972,25895972,-16601496,4,-1800857,5467672,-4,-2349517,5297518,0,-6473993,-162631,281197612767569,217616373508385 +-28833908404664,9204579231161,-32330256541839,19732768,-11889948,-31622716,-26359776,-41174332,-14814556,-4,5213744,-2399783,4,-1510105,-5505896,-4,-5079839,572704,281197612767569,246083854133385 +1894984646831,-17945029583154,70368744177664,30828220,-5471432,0,-8232132,-35060680,0,0,8765170,-1367858,0,-2058033,-7707055,4,-760868,-1928573,281197612767569,205300125776433 +28611080061252,-41757664116412,-15144640134557,22312208,22312208,-6546036,-13213296,-13213296,-46584596,4,6200030,-2171623,-4,5446119,535114,0,-3303324,-5578052,281197612767569,199921331030041 +8013518681087,27818012730386,42550731447278,31454204,-18282424,18282424,13014076,28230600,-28230600,0,7057650,4570606,4,-2771063,4234454,4,482456,-3629097,281197612767569,148485973314625 +-18940644319977,-14153219098715,-51428099857687,1194076,-39146860,-1194076,28654076,3502964,-28654076,-4,2080818,7092455,0,-7163519,298519,-4,1205077,-2694260,281197612767569,238732027170985 +-18334773394543,33699197388578,9965763298867,12429892,24859784,-27792180,5046852,10093704,79295692,-8,9136193,4207553,4,5343865,1370246,0,-1261713,3107473,281197612767569,44236653358929 +-18187009074278,10363264225349,52181735103386,1295976,-42824428,1295976,26337448,-1532620,26337448,-4,-1253812,7986797,0,-6584362,323994,4,870657,2719310,281197612767569,247673076109881 +26250867388639,44117876789025,697578968510,7628668,-7628668,-43999496,-23360708,23360708,-12851592,4,2072230,-6877495,4,-1140668,4122379,0,-5840177,-1907167,281197612767569,134233672938337 +11014323535679,-15142677172470,59354420641985,19669244,38884392,-19669244,15425820,-26746136,-15425820,4,6469810,7141365,0,3856455,-4917311,4,-216724,-2579733,281197612767569,63716713635017 +-11037611103791,-37255910866291,-11115135388759,-5422268,16266804,-100136284,5849028,-17547084,-99626204,-12,-12493568,13896355,-4,4137661,-3712572,0,-1462257,-1355567,281197612767569,18766040180849 +-34647143250174,-35721600927490,-15088564029461,-25963512,25963512,9622444,-4581304,4581304,-41666804,-4,-5533459,170612,-4,4883242,2576223,0,1145326,-6490878,281197612767569,153930229186649 +26425024646605,43943719531059,-8908844100082,-20159692,20159692,11034680,11908340,-11908340,49330872,4,-7324603,2360794,4,5008115,-397876,0,2977085,5039923,281197612767569,212801983422081 +-19498632669487,-1855852383534,50870111508177,-6555836,-36420792,-6555836,28013988,-16109048,28013988,-4,-2726634,6625443,0,-7003497,-1638959,4,-1300628,2479755,281197612767569,34260210060521 +15563643317021,39241457543622,-16231529704848,-6121356,12242712,-86472256,10556788,-21113576,-34801216,8,-6069300,11349426,4,1315502,-5134319,0,-2639197,-1530339,281197612767569,186556135564689 +-9684218735441,-17341141447714,-70368744177664,30324412,-11733128,0,12202524,32407096,0,0,8101774,2933282,0,-3050631,7581103,-4,-363200,-2271911,281197612767569,246584330015353 +1946992827933,31719723055679,-38649021121985,25716,30346492,30346492,-37092172,10989500,10989500,0,2747375,-7586623,4,5017070,213441,-4,4255973,-207012,281197612767569,61824986516897 +-28097010510215,-42271733667449,-2341499741517,19486180,-19486180,13319884,-14166076,14166076,48096108,-4,7105200,-2162471,-4,-4918827,1167500,0,3541519,4871545,281197612767569,148257148363017 +-12996253123391,-57372491054273,18663609502235,9293572,-9293572,45440108,19524740,-19524740,-25683732,-4,6529681,8645744,-4,108748,-2714283,0,4881185,-2323393,281197612767569,97015221954225 +-17212474599654,-6988206356573,53156269578010,22393960,-25611636,22393960,23127464,23826412,23127464,-4,5073782,4280755,0,-5781866,5598490,4,882821,2122154,281197612767569,137463118317721 +-31514471044075,38854273133589,-6784842001105,16104532,16104532,25475260,22786324,22786324,-33867012,-4,4125683,3904750,4,4341070,2464065,0,5696581,-4026133,281197612767569,36390982762689 +-15155716319936,55213027857728,12938621629695,-18262784,-18262784,-20449284,1740032,1740032,-59701604,-4,-11790817,3171762,4,-3134584,1940559,0,-435008,-4565696,281197612767569,163716703689001 +-33677059438116,-36691684739548,21547621216353,18888560,-18888560,-19194492,-11645072,11645072,-47773820,-4,5336099,-3948066,-4,-6607356,850557,0,-2911268,-4722140,281197612767569,208648704453585 +31374462036366,38994282141298,26541701022777,437816,-437816,41028836,27513080,-27513080,6691716,4,-3521388,5725235,4,-1848459,-4531974,0,6878270,-109454,281197612767569,202201814491833 +-11558385489269,20851365910376,-37958992778019,29040172,33930656,4890484,16581356,-19396704,-35978060,-4,5281006,4938083,4,3713509,-3715462,-4,431830,-3544581,281197612767569,83838238636001 +5707736998723,18425414336068,-46235592842873,8200460,30238992,38439452,30738092,-23951216,6786876,4,3490000,7483367,4,5186719,-2126496,-4,2497804,76381,281197612767569,177395654473033 +23106289029288,-14017125600561,47262455148376,29991584,-5066948,-29991584,-6494560,38637756,6494560,4,6811086,2344337,0,1623640,7497896,4,-2848353,1077600,281197612767569,267023137551601 +-20502566712469,30348282291305,40020461886359,8462764,-32649820,32649820,-31495412,-11530556,11530556,0,2882639,-8162455,4,-3638174,-3581451,4,4235679,-1465760,281197612767569,269323034534105 +-457456490393,69453831196878,16992872996538,-1301092,-2602184,314725096,-3016484,-6032968,-135683480,-8,-33115626,-77815380,4,-402622,-432947,0,754121,-325273,281197612767569,20245418832641 +3959692111895,27984831261968,38424220803801,34767964,-13732800,-21035164,-4371716,34110016,-29738300,4,7613011,-216692,4,178436,5042099,4,-914493,-3649892,281197612767569,218467666244969 +12557638946155,3092440796188,-70368744177664,-8705620,34553968,0,28310188,16962672,0,0,-4240668,8638492,0,7077547,2176405,-4,-445736,1637225,281197612767569,41699163243025 +-5952056782895,-70368744177664,10187012820698,16243524,0,-31812760,12448228,0,44934056,0,11233514,7953190,-4,-1400694,-84833,0,-3112057,4060881,281197612767569,188185582076665 +-30765710257262,39603033920402,-12786557659369,12371528,12371528,42147932,11163848,11163848,-52973796,-4,6946180,6492141,4,6297269,4044842,0,2790962,-3092882,281197612767569,115593801921057 +-14984380832522,13164159986365,-55384363345142,25295832,23598836,-25295832,5099288,-39752108,-5099288,-4,8060301,3460372,0,1274822,-6323958,-4,-1877726,-2439337,281197612767569,264088286665097 +23875023721538,-23494071681127,-46493720456126,-4454136,35879524,-4454136,29100040,18365924,29100040,4,-604749,6298316,0,7275010,1113534,-4,-3986732,2671565,281197612767569,204177889153841 +-29090378285311,10281238806779,30997127085574,-16197628,-42682388,26484760,-29254364,-7578036,-21676328,-4,42767,-5667742,4,-5461849,-953448,4,1851742,-5002855,281197612767569,147181965904153 +5994606855410,-46390316756024,3415011087261,4066248,16264992,-137479564,-3926200,-15704800,-144144588,16,23947227,-22460879,-4,3022230,-2977253,0,-981550,-1016562,281197612767569,91252959098177 +-24246920219841,-46121823957823,24016113850491,20574460,-20574460,17503724,5019036,-5019036,-50453236,-4,8695384,1112657,-4,-3917925,-3263274,0,1254759,-5143615,281197612767569,228839023206825 +-25138770148434,20091203880796,15227267400007,7706296,15412592,-60684004,12050104,24100208,51211548,-8,2351617,5165313,4,5225635,5002844,0,-3012526,1926574,281197612767569,21697026107473 +18849518295874,32669707585916,1331602908257,14886152,-29772304,-30478972,6502472,-13004944,62320420,8,7294813,3396729,4,-4142646,-2111507,0,-1625618,3721538,281197612767569,13242793472825 +-14244029078115,-41880686021434,11693006515525,164468,-328936,-106757868,-10518092,21036184,-18306476,-8,1849939,-15898177,-4,-1363340,5395645,0,-2629523,-41117,281197612767569,17750016998497 +-18971114194357,-51397629983307,-92347342630,-16425684,16425684,18930536,-9041972,9041972,-58124248,-4,-10616516,-3451347,-4,3914546,1281287,0,2260493,-4106421,281197612767569,193616921333193 +17240737168121,53128007009543,-3890641350062,-18290716,18290716,-26754744,10198116,-10198116,-46638520,4,-8943917,4797100,4,2715713,-1891586,0,-2549529,-4572679,281197612767569,136063219466609 +-4179837079501,-2442900823718,-70368744177664,-25258804,-17834648,0,-3400404,42173608,0,0,-10543402,-4458662,0,-850101,6314701,-4,655780,45621,281197612767569,87418725466457 +-23047547573756,47321196603908,2242397494013,-20965360,-20965360,-3745804,7637776,7637776,-52338252,-4,-8859884,462717,4,-4224679,473734,0,-1909444,-5241340,281197612767569,198326416967553 +4347991891375,-15399798970430,70368744177664,21158588,-15575288,0,22595676,36579272,0,0,9144818,3893822,0,-5648919,5289647,4,-1801280,917015,281197612767569,199453619265001 +32046395118346,26452076711767,38322349059318,13755432,-28442276,-13755432,-29354456,-21154724,29354456,4,5638814,-2579679,0,-7338614,-3438858,4,350133,4530890,281197612767569,208418987531921 +-3729724723103,-32962069570599,-70368744177664,15998340,-36705436,0,20820004,22608132,0,0,5652033,9176359,0,-5205001,3999585,-4,2138550,-2359853,281197612767569,104483304993657 +9493097807769,27376260737895,33499385632000,3635812,30421404,-34057216,-35092060,16048732,19043328,4,57865,-6932970,4,4818697,1581334,4,-3954318,672381,281197612767569,45188478211745 +-35132535449109,35236208728555,-5285312401967,-23372884,-23372884,-44220,8305996,8305996,48186916,-4,-6188202,-444413,4,-5858527,433358,0,2076499,5843221,281197612767569,278649599463945 +-32126091059090,38242653118574,12222015487923,-16053832,-16053832,-30223668,-7115080,-7115080,56737612,-4,-8017613,-3409266,4,-6166790,-4146651,0,-1778770,4013458,281197612767569,193910933831601 +25862675360776,-44506068816888,2687558283037,25595936,25595936,-13850508,-4044512,-4044512,46176020,4,7262611,1945612,-4,4281394,1517015,0,1011128,6398984,281197612767569,157755950959001 +5754292307040,32307225935312,-15643489869667,7639424,-3819712,-96309644,-20465280,10232640,-36756172,4,3650114,-11266547,8,-1888815,1544317,0,-2558160,-954928,281197612767569,37844746168769 +34799580946387,-35569163231277,2516443706468,-10366132,-10366132,-56311408,10965356,10965356,-49046768,4,-6099863,7208582,-4,-6161829,6869270,0,-2741339,-2591533,281197612767569,244420682672681 +-8947514713782,30710614731941,-1992364270397,-9110232,-4555116,-105707764,-17004248,-8502124,49869068,-4,-5380835,-11565596,8,-1705597,-3295749,0,-2125531,1138779,281197612767569,95906250630353 +26647243932989,43721500244675,-9642440949615,15040756,-15040756,45522500,-23694828,23694828,3141604,4,1299695,-6555760,4,514294,4824865,0,5923707,3760189,281197612767569,45035917624249 +33641372022092,-36727372155572,-3136702677419,-25483984,-25483984,14353748,-13897680,-13897680,-36352876,4,-4588517,-2156892,-4,-4499702,-1431545,0,3474420,-6370996,281197612767569,52420387799265 +-10671032688601,18184453277996,59697711489063,-25033572,7664816,-25033572,-5402180,-43321552,-5402180,-4,-8839016,-3242895,0,1350545,-6258393,4,-1991372,1326691,281197612767569,177524298557001 +-20314782880453,29739178416758,-2781618836317,-8951572,-17903144,-52181364,-9513876,-19027752,70317580,-8,-7241351,-5690135,4,-5169022,-3677603,0,-2378469,2237893,281197612767569,280892506869233 +11843681931986,11150334517734,1933236471219,-2768056,13840280,172485324,-1553016,7765080,-309974740,20,-12332655,-6737766,4,13032206,7276713,0,388254,-692014,281197612767569,173687765770713 +7531788635196,-20429180249835,-70368744177664,28033264,-1478572,0,-10701328,-39598572,0,0,9899643,-369643,0,-2675332,-7008316,-4,1836282,1995063,281197612767569,229418591640577 +20246606749315,50122137428349,-4119001477284,18025996,-18025996,544112,-1285844,1285844,62420976,4,11134095,166896,4,-4471149,302924,0,321461,4506499,281197612767569,60138253338217 +-23223716462308,-3537285540509,-47145027715356,29955184,-1218164,-29955184,-4089744,37752460,4089744,-4,6271869,-172412,0,1022436,7488796,-4,-3166246,-476953,281197612767569,161394016582417 +-24452186651741,-15131593776943,-45916557525923,-5561716,40443716,5561716,-29355924,11033060,29355924,-4,221683,-6298530,0,7338981,-1390429,-4,-2536582,3812399,281197612767569,47979147535353 +14014458447588,-42339827282488,7353700045445,14748560,29497120,-27421164,3633296,7266592,69584468,8,10656829,3354097,-4,3369644,1750597,0,-908324,3687140,281197612767569,98739931708193 +27846943438999,-7376757690027,-42521800738665,-18504100,30069076,-18504100,-24142724,-21614156,-24142724,4,-2632482,-5027415,0,6035681,-4626025,-4,-2771057,-2489854,281197612767569,183753807448713 +3210735649755,-4043206625799,-70368744177664,1852268,33149924,0,34525676,10054500,0,0,-2513625,8287481,0,8631419,-463067,-4,-610629,404742,281197612767569,74619827186737 +857849085767,18913385764266,-51455358413398,-27393764,-14324056,-14324056,-20526852,30367208,30367208,0,-7591802,-3581014,4,-3659885,5051404,-4,-1471828,1797037,281197612767569,170514938382873 +-3602011416763,22255577586967,154637391375,-11949804,-3983268,144063548,11116500,3705500,148639868,-4,-11750576,11392961,12,-1908239,1837004,0,926375,995817,281197612767569,126119467277889 +20078804032884,-50289940144780,5970072733253,-5429808,-5429808,56714516,17472848,17472848,24850932,4,-4810609,10017776,-4,-1402124,4160853,0,4368212,1357452,281197612767569,132643923210921 +6205205790719,64163538386945,18257595396804,13378556,-13378556,29637392,-5307396,5307396,72399632,4,16159576,-7623769,4,-1940332,-214421,0,1326849,3344639,281197612767569,225725972996433 +29688296420325,-40680447757339,18642214997870,-12084332,-12084332,47433144,19478452,19478452,16713848,4,-3705652,6054971,-4,-472810,5803315,0,4869613,3021083,281197612767569,234066239591481 +-10694314849102,-59674429328562,-12751272409221,-18404664,18404664,-9317908,1986376,-1986376,-60169044,-4,-12666222,2809215,-4,2376039,479738,0,-496594,-4601166,281197612767569,29801049425249 +23746218478732,-22876307220200,-5165981490581,229936,459872,69238188,-16224080,-32448160,11194444,8,1505335,-5618753,-4,646638,-5845397,0,4056020,57484,281197612767569,206075146469065 +-1241136011615,-33649579971560,-36719164206104,6026884,33116256,-33116256,35644164,9043040,-9043040,0,-2260760,8279064,-4,4689751,-932246,-4,-4221290,574475,281197612767569,188599917238897 +-26825066949073,43543677228591,-12714494859268,23837884,23837884,23080944,-7067492,-7067492,40388464,-4,5928778,-4647361,4,4168338,-1122875,0,1766873,5959471,281197612767569,18379447435865 +32561059306115,-37807684871549,-31709959717611,-1376756,-1376756,-42991532,26067020,26067020,-3805164,4,-3447726,5619517,-4,2496435,5128366,0,-6516755,-344189,281197612767569,109685582852225 +12912336443611,57456407734053,-21001773950633,563052,-563052,-46126756,24187276,-24187276,18149884,4,1900174,9457689,4,-2637297,-2074000,0,-6046819,140763,281197612767569,39574819745513 +19066327970361,51302416207303,-6704477920215,19383524,-19383524,23448740,16180708,-16180708,-38511196,4,7404568,3812135,4,-2223231,-2050050,0,4045177,-4845881,281197612767569,12860757301137 +-13433286676509,32270410532082,-38098333645582,-30682228,17107912,17107912,-14708884,-28494072,-28494072,0,-7123518,-4276978,4,631015,-4969384,-4,3046206,-2701173,281197612767569,180548516582521 +-32609284964797,37759459212867,-17159837934220,12750092,12750092,43132368,-14140212,-14140212,40470224,-4,4566978,-6563441,4,5550578,-4219651,0,3535053,3187523,281197612767569,115893597577121 +-1308760766909,70368744177664,33685362521442,19115276,0,-4387448,67500,0,-58916024,0,14729006,-1096862,4,265861,2267210,0,16875,-4778819,281197612767569,102616276681481 +-27207912053231,43160832124433,6952125787358,4666436,4666436,-51741832,-21835324,-21835324,835704,-4,-667454,-8049249,4,458528,-4886209,0,-5458831,-1166609,281197612767569,169363907926193 +-21494282162570,-48874462015094,29483033593499,-12639784,12639784,-43299220,-19004776,19004776,23972556,-4,-6153173,-6194394,-4,-160034,4630411,0,-4751194,3159946,281197612767569,225390080084633 +692005726349,-22994910908322,-3243721864728,-340428,-226952,-690714720,4865268,3243512,-50487904,8,-4161954,56424864,-12,-68057,1702044,0,-405439,-28369,281197612767569,177143669920449 +10753961578458,-26378541039165,-33236241560041,1349480,-35546356,36895836,-30911704,-20082900,-10828804,4,1356540,-7654981,-4,-4063741,-1568978,-4,3664185,-1231608,281197612767569,184321854946089 +-32204152700209,38164591477455,-8928338330552,21622588,21622588,-9383648,3874108,3874108,50389280,-4,6955061,586444,4,5642259,1759468,0,-968527,5405647,281197612767569,259202953502161 +27529472523334,42839271654330,7316139393581,-3335912,3335912,-49695564,22890200,-22890200,3489748,4,1126090,7650157,4,253653,-4773734,0,-5722550,-833978,281197612767569,82501250065593 +-16954100840038,18905172407187,-53414643337626,30834280,926284,-30834280,6869224,36720908,-6869224,-4,6507045,1895196,0,-1717306,7708570,-4,-2673182,2126767,281197612767569,42120302971361 +-16370143349147,-31440279849086,38928464328578,-5659244,-34433528,-34433528,33407732,4319688,4319688,0,1079922,8608382,-4,-4871572,-2785283,4,-3480361,1370472,281197612767569,247678237873993 +25833861416465,-44534882761199,184680264964,17478724,17478724,-17546224,-11646268,-11646268,-52724208,4,8349649,-2764690,-4,4831403,-1621866,0,-2911567,-4369681,281197612767569,264989615941361 +20004867996943,-30359008183778,-450315241873,-2041796,-4083592,-67748420,16457244,32914488,-5361764,8,-630961,7300599,-4,-354740,4818253,0,-4114311,-510449,281197612767569,62956180382425 +18534084246313,19576670877625,51834659931351,-28628828,1891044,28628828,-808604,39380900,808604,4,-7195900,-1642901,0,-202151,7157207,4,2649325,-2115662,281197612767569,136085038646529 +30016947667912,-40351796509752,-32173179717881,-6099168,-6099168,-44900324,-23746016,-23746016,9787580,4,-4117351,-5739690,-4,1670456,-5485391,0,-5936504,1524792,281197612767569,70639357089641 +1010796699473,-70368744177664,-29197669054979,-1304252,0,129795060,-8485820,0,-18771212,0,-4692803,-32448765,-4,-947651,-330812,0,2121455,-326063,281197612767569,190216390243345 +7775794177202,70368744177664,12949250585773,-22181176,0,-3309900,-7163384,0,49690324,0,-12422581,-827475,4,1702255,-929008,0,-1790846,5545294,281197612767569,82981634622713 +24588767035010,45779977142654,-11520336149753,-21646840,21646840,-12513252,-5726072,5726072,48702172,4,-8155434,-1149223,4,4020109,1979090,0,-1431518,5411710,281197612767569,19600365093921 +11061103359915,-21738014520158,70368744177664,15127212,-34968952,0,24018508,18906184,0,0,4726546,8742238,0,-6004627,3781803,4,-2597879,-205914,281197612767569,83730948127625 +-24600920736559,32883507024672,-37485237152992,-33648828,-734080,-734080,-983356,33438848,33438848,0,-8359712,-183520,4,-3053514,4417001,-4,2807675,3995206,281197612767569,108463213053233 +-6590631926677,-70368744177664,-27085951441546,11961772,0,-39125544,20423180,0,27323032,0,6830758,9781386,-4,1325536,-2067175,0,-5105795,2990443,281197612767569,124970756147993 +-5296638338783,-29614466333464,40754277844200,27771012,1799072,1799072,3769412,-40298080,-40298080,0,10074520,449768,-4,-212540,-4054771,4,1154893,-2887982,281197612767569,251909633115969 +7602870855522,-62765873322142,-4271625836139,-15018616,-15018616,-12471724,880712,880712,-74235596,4,-16567100,2553139,-4,-1991799,564792,0,-220178,-3754654,281197612767569,18245061051305 +14263000773333,11691508407506,56105743404331,-24389804,-26285240,24389804,-11474092,33796936,11474092,4,-6260069,-6252444,0,-2868523,6097451,4,2189165,318866,281197612767569,129626436803153 +-11146151631975,6047926081286,70368744177664,27331172,164888,0,454404,-41191976,0,0,10297994,41222,0,113601,-6832793,4,1621401,593782,281197612767569,239322958263609 +-13645814726305,32579998555667,37788745621997,23046524,20106316,-20106316,-27672260,24711436,-24711436,0,6177859,-5026579,4,4913075,2119308,4,-2004990,-3642323,281197612767569,187001196891745 +-18742919499936,-23231667450191,28394157227537,33176960,-12101948,21075012,-2240128,-33119068,-35359196,-4,6259317,518636,-4,-2580482,-4750117,4,2020450,-3544123,281197612767569,11045268975561 +22632454493236,-25103835191192,-4272619033673,-9371440,-18742880,-18681124,-1303856,-2607712,117542492,8,-10522815,-1381603,-4,-9431404,-1644339,0,-325964,2342860,281197612767569,125699428496241 +-16722062336939,26165206855080,-53646681840725,-25330348,-24308064,25330348,14048756,-30966880,-14048756,-4,-7207955,2278260,0,-3512189,-6332587,-4,533765,-3798756,281197612767569,106935503553369 +-30392913892746,589131771647,39975830284918,-22212136,13426684,-22212136,18793048,39328572,18793048,-4,-5546215,1953384,0,4698262,5553034,4,-4285928,1403287,281197612767569,64451945879937 +34033292496265,-36335451681399,-4362996204068,13300260,13300260,35522416,7397764,7397764,-64894480,4,8491862,4379409,-4,7731758,4501195,0,1849441,-3325065,281197612767569,272096504463337 +6389007819914,-19873379378331,44106356979419,-16176600,-35178092,-19001492,-34624472,-5694828,28929644,4,-1150197,-6853900,-4,-6082214,2103527,4,-2573904,1940623,281197612767569,273594460885137 +10016735021547,25147768409961,45220975767703,-3859540,-35620444,35620444,32331916,6678852,-6678852,0,1669713,8905111,4,-5432032,-1887673,4,2650947,-922788,281197612767569,215169341175161 +-5899940850176,-32234401663744,3467280836353,-10201088,5100544,87848964,-19933184,9966592,-49082044,-4,-5498085,-10123258,-8,1274341,1715725,0,2491648,-1275136,281197612767569,101199326881953 +-16875495033223,10886669713060,-53493249144441,7329252,-36181360,-7329252,-28539964,-12727792,28539964,-4,1315022,-7159605,0,-7134991,-1832313,-4,-1866926,1885735,281197612767569,145434918319113 +4705816388864,-11505789881583,-70368744177664,-2452480,-48535484,0,22680576,-10229308,0,0,-2557327,12133871,0,-5670144,-613120,-4,756091,911686,281197612767569,219040657207729 +-10190206113997,20059512687889,8156064458377,1929420,643140,-279554524,-11758548,-3919516,-46928316,-4,3230807,-19941286,12,2039658,-10064773,0,-979879,-160785,281197612767569,42568864730009 +16845775815088,-53522968362576,-32430454330883,10634944,10634944,-40233996,23231168,23231168,17980084,4,742340,8875883,-4,3752681,1182616,0,-5807792,2658736,281197612767569,128277070232513 +-10095768229756,-19889903028884,-5333290111749,4854288,-24271440,-25663508,472976,-2364880,229438732,-20,16257668,1353577,-4,-8220403,-1012460,0,-118244,1213572,281197612767569,183754154970153 +12010944087795,27046761897668,-43321982279996,1437644,-30741744,-30741744,35901900,15450896,15450896,0,3862724,7685436,4,-6184995,-1090526,-4,-2790480,1449937,281197612767569,173046494172881 +-16635069128162,26866837524751,-12062693905378,3035256,1517628,133855352,-16227016,-8113508,26266936,-4,2159477,-12841556,8,2247780,-7780726,0,2028377,379407,281197612767569,39655228704185 +-33147994587071,-37220749590593,-14397905398626,16702724,-16702724,33167992,-19849404,19849404,27991544,-4,2686123,-5240330,-4,-4311763,3051668,0,4962351,4175681,281197612767569,115871485629153 +5239748488647,-21337860860999,-70368744177664,9354012,-39367964,0,-27358148,-5223996,0,0,1305999,-9841991,0,-6839537,-2338503,-4,2171194,-23745,281197612767569,170630928271433 +-8870701429245,21412459629475,-70368744177664,-5846004,39273100,0,28787596,-800244,0,0,200061,9818275,0,7196899,1461501,-4,2164720,-792975,281197612767569,128679531528177 +22709046866928,24950650443808,12593155521767,-7204928,14409856,82409372,7507392,-15014784,70399100,8,-6912113,6660279,4,5343831,-6971032,0,1876848,1801232,281197612767569,6114328290265 +5502030547670,30653987251001,39714756926663,-22670504,-24737564,24737564,-17016872,31095204,-31095204,0,-7773801,-6184391,4,-1793176,3682247,4,2461042,-1985379,281197612767569,171936100298241 +-23561529201083,23111091787297,-23696123189284,-30472940,-21318524,9154416,9884916,-30032156,-39917072,-4,-5805748,1043069,4,-4173520,-3331673,-4,1702291,-4286562,281197612767569,143241593841769 +-1651810875235,70368744177664,-25832823155506,-2355596,0,-74753224,14717300,0,-10924744,0,-2731186,18688306,4,-1414815,222494,0,-3679325,-588899,281197612767569,89638431091985 +22960764460602,-14374075467355,47407979717062,8933608,35631764,-8933608,30192936,-5604940,-30192936,4,2485885,5545138,0,7548234,-2233402,4,1084650,-3362803,281197612767569,178909080643065 +1145478611384,70368744177664,-12352198068769,-8640800,0,-54756484,-15631136,0,31246396,0,-7811599,-13689121,4,-558795,602026,0,-3907784,2160200,281197612767569,254367411997985 +31737701553363,6893341070938,4884878348242,-88244,176488,87144264,-12914196,25828392,-5686520,8,-587504,-2131106,4,417063,9827480,0,3228549,-22061,281197612767569,8211717729417 +5337530678692,-32515606749486,-14314892190133,-14424432,-7212216,46853420,-5733232,-2866616,-137487444,4,-15736576,-5779233,-8,-2898709,-154889,0,716654,-1803054,281197612767569,244949979766321 +18110398675216,-52258345502448,19051499905691,21931072,21931072,-16073108,-928192,-928192,52018380,4,9594853,1499722,-4,3409742,2518555,0,232048,5482768,281197612767569,43965623716889 +-19347897769305,-31672948639054,20645196007189,13635228,-27270456,31336532,5960924,-11921848,-68873452,-8,8624405,1525949,-4,-4296979,-3154092,0,1490231,-3408807,281197612767569,119319017697345 +-9982581363679,60386162813985,17417764464535,-15004540,-15004540,-29269412,4577252,4577252,-66108420,-4,-14465795,5350820,4,-2061310,1966533,0,-1144313,-3751135,281197612767569,214088803177641 +15635233652303,-39098276873058,18370351256413,15785276,31570552,-7653004,-723652,-1447304,-70975116,8,9953255,997399,-4,3895262,-1455325,0,-180913,-3946319,281197612767569,42815528719185 +-12061619593679,24857342349310,45511401828354,25793732,-18577416,18577416,-19671964,-29481800,29481800,0,7370450,-4644354,4,-1917401,-4966632,4,3000590,1481801,281197612767569,9485629019705 +-10604755028821,28643597616958,41725146560706,-14235988,-33987336,33987336,-26870420,14937208,-14937208,0,-3734302,-8496834,4,-4545973,829812,4,2171632,-2729185,281197612767569,64515262486369 +-24951006144325,45417738033339,6662322803428,18224876,18224876,24460176,-3377268,-3377268,57245456,-4,9316848,-3515431,4,4994516,-2599613,0,844317,4556219,281197612767569,183586919342281 +8396378205541,-24111140963853,37861225008270,30310804,28883916,-1426888,21211156,-16932532,-38143688,4,5544984,3762951,-4,3990938,-4119673,4,1311851,-3458028,281197612767569,237056911477873 +-1640495753641,-17096308140975,53272436036689,-14934692,21163332,21163332,-33630660,-27731612,-27731612,0,-6932903,-5290833,-4,6526622,-2703221,4,1881043,-1030452,281197612767569,128900623598681 +112175643173,-33464421834166,36904322343498,-674668,-33021656,-33021656,34363476,13101224,13101224,0,3275306,8255414,-4,-4500191,-75296,4,-4090678,-93371,281197612767569,1669065261697 +-33432843800487,36935900377177,10948920506594,-14992028,-14992028,25959304,-4366652,-4366652,-67538872,-4,-8692776,-3989615,4,-8191942,-2500211,0,1091663,-3748007,281197612767569,120293718937833 +-12378070273755,-27297274395648,-43071469782016,9080980,34607104,-34607104,31778196,-2879488,2879488,0,719872,8651776,-4,4736091,-2911450,-4,-3208458,-641205,281197612767569,246723323677073 +22181219557243,-30207698474771,-40161045702893,-30723604,-12890188,12890188,11760844,-31711788,31711788,0,-7927947,3222547,-4,-4177046,-3367873,-4,-1236835,4313028,281197612767569,257255540938361 +-9899991951506,29797564171773,-40571180005891,-28908104,23757812,23757812,20772664,21875764,21875764,0,-5468941,5939453,4,2224715,5002356,-4,2968451,2224670,281197612767569,128260739838369 +20449816887807,-49918927289857,-32387581003517,-25940996,-25940996,-6850548,7095068,7095068,-41528660,4,-8181396,-1769941,-4,-2200769,3482578,0,-1773767,-6485249,281197612767569,203583147123977 +34692604819488,35676139358176,-19064377626033,4677760,-4677760,43822396,23924864,-23924864,-16558148,4,3719135,5237536,4,-420402,-5718063,0,5981216,-1169440,281197612767569,182164063783601 +5090218684159,5256579171218,-70368744177664,9166844,34375240,0,-25940772,25546376,0,0,6386594,-8593810,0,6485193,2291711,-4,946430,-450453,281197612767569,211690744401049 +-29702792217459,40665951960205,-8008870540657,-22995404,-22995404,-21098948,-6834956,-6834956,42690684,-4,-5973238,-3702553,4,-4699433,-1572184,0,-1708739,5748851,281197612767569,136847165777089 +-26823818592491,-43544925585173,19820999674482,-17102764,17102764,-35249720,21964084,-21964084,-20562296,-4,-4727716,4248877,-4,412858,-4563553,0,-5491021,-4275691,281197612767569,167387631246633 +-35230527734777,24509360100914,-35138216442887,-15928292,37376200,15928292,25692700,10396872,-25692700,-4,939281,6052848,0,6423175,3982073,-4,3538499,-3291202,281197612767569,161802617507793 +32809121956893,-37559622220771,-3907913854323,10615924,10615924,-53971404,-16288364,-16288364,-23247532,4,2875975,-7349256,-4,2935908,-6143595,0,-4072091,-2653981,281197612767569,47107557353145 +-64073958941,70368744177664,-9976002306225,7797644,0,-70229700,5600844,0,93945596,0,23486399,17557425,4,-177119,292350,0,-1400211,1949411,281197612767569,269541522922465 +-16242783940787,-21640392355303,6485679647520,-3512012,10536036,118893696,-7495276,22485828,-66844544,-12,-4621037,-9383568,-4,4030033,6779952,0,1873819,-878003,281197612767569,16579332012361 +23103101143600,21034086818327,-47265643034064,-7509824,-34124708,-7509824,30187712,-12750372,30187712,4,114811,6291460,0,-7546928,-1877456,-4,-3302404,2239717,281197612767569,153035265022193 +23551699569749,-46817044607915,12308421270116,-19645100,-19645100,44915088,13122548,13122548,27309584,4,-5116163,6611570,-4,-1711233,4617202,0,3280637,4911275,281197612767569,163377659749593 +24404070547213,-45964673630451,13412598165567,18753588,18753588,-24976132,17744884,17744884,36403772,4,6790275,3184956,-4,2310668,3059077,0,-4436221,4688397,281197612767569,137685176620801 +-6396772145155,70368744177664,-30548990309022,23464948,0,-12882552,1508564,0,-48810424,0,12202606,-3220638,4,1272988,-2839461,0,377141,-5866237,281197612767569,146515223017833 +5014414819989,-65354329357675,-12026257235043,-10742188,-10742188,21854836,2954580,2954580,98799988,4,-22813660,5533339,-4,-1886337,-69630,0,738645,2685547,281197612767569,141300623074833 +19244574782765,51124169394899,-17482996653208,8093876,-8093876,-48960096,-18583340,18583340,-26693984,4,3694166,-9395327,4,-2979330,2844697,0,-4645835,-2023469,281197612767569,37966455244537 +-18593910428163,-51774833749501,-19374464751889,-13818892,13818892,-36831300,-15690188,15690188,39656572,-4,-6214490,-7725973,-4,3699653,1481852,0,-3922547,3454723,281197612767569,199847694865953 +13611102482445,29535436730329,-15794887502384,1961012,-5883036,-119793856,-8857196,26571588,-33075904,12,1979629,-12900208,4,-2096449,5682752,0,-2214299,-490253,281197612767569,55990044515721 +12921007845213,-25581689383342,-31866046949109,-35346060,-16920248,-18425812,-2483468,30664776,-33148244,4,-6484247,-240938,-4,-1802814,4847391,-4,-1181947,-3989124,281197612767569,133398882957105 +-5894856295667,-19526343862110,2240804252136,9967668,-6645112,54593440,-1643820,1095880,329862304,-8,22891770,-3734328,-12,-6895133,1222688,0,136985,830639,281197612767569,245934070336793 +5951050967602,27645105631539,42723638546125,-4677432,-33974068,33974068,31489096,-11991028,11991028,0,-2997757,8493517,4,-4526049,-1428256,4,3346225,-258898,281197612767569,96341375244609 +16305530632121,54063213545543,11714289262596,-8332572,8332572,48689168,23612228,-23612228,-2851440,4,-435003,9005002,4,-1147863,-3167290,0,5903057,2083143,281197612767569,25839479006633 +-26774824252194,43593919925470,-14439429827941,-18285704,-18285704,-26640788,7299960,7299960,-50937236,-4,-7514510,5064079,4,-5219799,1596118,0,-1824990,-4571426,281197612767569,82781156379729 +1975382975924,34196680600870,-8272542555479,-19446064,9723032,-60963164,13245264,-6622632,-74273468,4,-9218198,7120717,8,131971,-999357,0,-1655658,-2430758,281197612767569,36682090395449 +-8592486751327,30316423863060,-40052320314604,3074692,32021584,32021584,-34153788,10486096,10486096,0,2621524,-8005396,4,5179999,-540000,-4,3358448,1308673,281197612767569,178144541827169 +-21023217123497,49345527054167,-28572623148249,24428892,24428892,-13422436,10259068,10259068,40452028,-4,8133068,-126691,4,1979939,3482300,0,-2564767,6107223,281197612767569,152969827668425 +-20793440002421,26830041949428,49575304175243,30928428,-5487664,30928428,2624428,35937744,2624428,-4,6079443,3914606,0,-656107,7732107,4,2904993,-2542690,281197612767569,159880387782001 +-13976015954881,-21126263320545,-70368744177664,14456060,-31464324,0,27137756,18817628,0,0,4704407,7866081,0,-6784439,3614015,-4,1102492,-2647299,281197612767569,215750484165977 +5715628903488,-18831040695919,70368744177664,-22662912,32334404,0,21127424,19536644,0,0,-4884161,8083601,0,5281856,5665728,4,1810163,859596,281197612767569,254697152686977 +-11663682253118,-13039239609985,58705061924546,20574984,-20829700,20574984,-17005624,-37505636,-17005624,-4,8610041,-3391160,0,-4251406,-5143746,4,766368,-1816265,281197612767569,41132209758697 +16278498394866,-30983640708807,39385103468857,-27982904,25239780,25239780,18537928,23514596,23514596,0,-5878649,6309945,-4,1233985,5375168,4,3400497,1620558,281197612767569,190765873185425 +23462466609393,46906277568271,-11682424024806,-15818812,15818812,33201256,-7406492,7406492,-55629656,4,-8962979,-6189358,4,4944435,2110956,0,1851623,-3954703,281197612767569,32018077841273 +14723541002871,-40921662171922,11627926741291,4976092,9952184,-87394132,-11509092,-23018184,-24129940,8,4458979,-12294485,-4,786753,-4777024,0,-2877273,-1244023,281197612767569,106259024919201 +9591203252665,-23301531957064,-47067212220600,-7068956,33178336,-33178336,-32280380,-7765024,7765024,0,-1941256,-8294584,-4,5133215,-2312590,-4,-2936880,-545351,281197612767569,137486353913353 +-19488643012963,18610676620005,50880101164701,-25721228,-26462316,-25721228,19423732,-23789804,19423732,-4,-5584569,3082746,0,-4855933,-6430307,4,-362882,3532833,281197612767569,26398006748081 +3072535387157,-32835852569741,37532891607923,-31228844,13279692,13279692,21111284,27075884,27075884,0,-6768971,3319923,-4,2519499,4309126,4,2758322,3498085,281197612767569,230939541638553 +-14437019636553,4598716287515,70368744177664,13367004,31087724,0,-29060324,16644012,0,0,4161003,-7771931,0,7265081,3341751,4,378896,-1812897,281197612767569,255908496379329 +4415938098983,-23005229227308,70368744177664,23683228,13482832,0,4125244,-45191472,0,0,11297868,3370708,0,1031311,-5920807,4,-371829,-2147180,281197612767569,49210748612137 +-16194254855161,-54174489322503,-28682363364516,26121244,-26121244,-8290960,2565660,-2565660,42288496,-4,8400558,-1066029,-4,-2171566,-3138769,0,-641415,6530311,281197612767569,230914271807697 +-29256115695649,41112628482015,13289295865979,17752956,17752956,35083756,-17311780,-17311780,29208524,-4,5083580,-4286211,4,2218551,-4484728,0,4327945,4438239,281197612767569,79169784956857 +21966396277824,48402347899840,-18408817182101,-22802176,22802176,11460012,3907840,-3907840,47412844,4,-7897520,3461951,4,3955691,596948,0,976960,5700544,281197612767569,265905831879905 +21299441801273,-49069302376391,-18895410871656,-22848284,-22848284,-11031968,8491972,8491972,-45176992,4,-8445734,389389,-4,-2848514,2368603,0,-2122993,-5712071,281197612767569,161835615447625 +-3384776143419,-70368744177664,-19094948041882,17597204,0,11687320,6776724,0,-59480936,0,14870234,2921830,-4,-1174992,1053233,0,1694181,-4399301,281197612767569,138716260921841 +-25526051494862,-44842692682802,-3009847778941,-8025912,8025912,-53536244,16015112,-16015112,-33455508,-4,-5158654,8614855,-4,3205223,-4769206,0,-4003778,-2006478,281197612767569,259524955645401 +27439336091691,42929408085973,14054725908239,24032428,-24032428,-28524484,6815468,-6815468,38759804,4,6251799,3150440,4,-3438152,-3980681,0,-1703867,6008107,281197612767569,198125750353921 +-30978089097090,39390655080574,5787192200715,12052984,12052984,37334060,15732024,15732024,-44682676,-4,6576514,4976855,4,4594155,4356660,0,3933006,-3013246,281197612767569,259681193593449 +-7797641318479,32166336889297,38202407288367,37214916,3253060,-3253060,8688068,31013444,-31013444,0,7753361,-813265,4,-320005,4960772,4,1852012,-4342957,281197612767569,130074647781137 +-10499343303207,-59869400874457,-25255897358981,-11570332,11570332,-42980884,-20634876,20634876,20655820,-4,-2541964,-10180155,-4,2621991,565066,0,-5158719,2892583,281197612767569,94740846356473 +-32031904728823,-38336839448841,-26345095177257,28942372,-28942372,5780316,-4256412,4256412,38051356,-4,4784202,-3496185,-4,-4728637,-2051106,0,1064103,7235593,281197612767569,148129474027297 +5934863189659,-34759565039710,-10772849956371,1527404,9164424,-250653772,3846156,23076936,105961748,24,12202079,31304179,-4,2381393,5226544,0,-961539,381851,281197612767569,188047241121417 +28422233133362,12690515718029,-41946511044302,-24167224,28502580,-24167224,-15668280,-28108876,-15668280,4,-4895312,-3157969,0,3917070,-6041806,-4,-2131907,-3967676,281197612767569,40302593790001 +32262894155741,38105850021923,20309330007668,-12596364,12596364,39193040,26311700,-26311700,7515216,4,-2915878,4397053,4,-1037074,-5401207,0,6577925,3149091,281197612767569,33606694325785 +-24894119899263,-20580504379138,10721681156430,-13821436,27642872,35892536,5894596,-11789192,66152888,-8,-4387814,3677288,-4,6075204,-2647923,0,1473649,3455359,281197612767569,81895606747713 +-28021718366075,-42347025811589,-5140457775964,-20484588,20484588,27878032,4072180,-4072180,49421328,-4,-7509652,3820061,-4,4845680,-3149447,0,1018045,5121147,281197612767569,112424008545961 +33153301854962,37215442322702,-18376930313867,2024392,-2024392,62878164,17515464,-17515464,-12131884,4,2747576,8181319,4,-285395,-7538222,0,4378866,-506098,281197612767569,272938558735697 +-13251499882974,-18630152825105,-70368744177664,-32026488,-19349572,0,-7227448,30788636,0,0,-7697159,-4837393,0,-1806862,8006622,-4,1927859,-1208802,281197612767569,59157456361529 +-11482894064728,-58885850112936,-20516083732365,20639392,-20639392,-92724,-1394528,1394528,-54544756,-4,11512656,1484961,-4,-2123533,1508142,0,-348632,-5159848,281197612767569,270188195359073 +22321190711675,3405172042639,3003398504151,6060524,-18181572,-74072228,2661004,-7983012,153252988,12,1939174,702095,4,-12124691,-5938654,0,-665251,1515131,281197612767569,50952869954249 +15777661864085,-11272729740961,54591082313579,26553940,17598844,-26553940,11572436,-34730756,-11572436,4,7199370,2349781,0,2893109,-6638485,4,-1483319,-2049930,281197612767569,137831556169329 +5992602434972,-32188070871346,2974923636921,17041008,8520504,64749284,9622000,4811000,-95580156,4,10879221,7494458,-8,2136597,1198405,0,1202750,-2130126,281197612767569,187219150603865 +-11523567296329,11461614522128,-47383562359207,10929884,-24445888,-35375772,33595420,27871296,-5724124,-4,4458775,5555722,4,-5889806,3288221,-4,-2509049,-555750,281197612767569,153733793420417 +-11346539999915,-24982584178004,4346598731105,-48812,195248,-202370684,5564724,-22258896,4857316,-16,87389,17958591,-4,-281735,-8158520,0,-1391181,-12203,281197612767569,231032122438377 +31711974953271,38656769224393,-4730109772269,14780636,-14780636,28265548,-7583780,7583780,61671244,4,8597152,-3633505,4,-6820659,3432882,0,1895945,3695159,281197612767569,127506334530449 +24003045862433,46365698315231,64657780451,986244,-986244,-49492084,22891300,-22891300,-7136404,4,-1170279,8152310,4,613822,-4220711,0,-5722825,246561,281197612767569,279074764658809 +1428364862713,3555813611500,70368744177664,-22376476,-22663248,0,22358820,-27670864,0,0,-6917716,5665812,0,-5589705,-5594119,4,422872,167671,281197612767569,52956438807457 +21176482584443,49192261593221,8861832549779,22352364,-22352364,7645772,-5362292,5362292,48536300,4,8313672,-2039953,4,-3820403,-128510,0,1340573,5588091,281197612767569,101315627779849 +-24368383131189,11341189471136,46000361046475,-12158164,42266240,-12158164,-23902292,-9511296,-23902292,-4,-591323,-7397284,0,5975573,-3039541,4,-1786501,-3169276,281197612767569,51257013320881 +-15059074734856,25191519973096,-2004739683997,3257312,9771936,151337356,-5473568,-16420704,91346668,-12,8058415,-13614028,4,4926084,-8073437,0,1368392,814328,281197612767569,149049461821081 +25829897639014,-7239521784371,-44538846538650,-20055656,16311092,-20055656,-22275048,-38022668,-22275048,4,-5443557,-3096796,0,5568762,-5013914,-4,-4062110,-980977,281197612767569,144757295134401 +27802045863288,-42566698314376,-9818289787787,-10979872,-10979872,-42123820,-22365472,-22365472,16737972,4,-3311381,-5987276,-4,-873112,-4543679,0,-5591368,2744968,281197612767569,278987667242793 +11961728836653,22521828831052,2703616278316,1522868,-6091472,162778288,-6449484,25797936,49947824,16,3748712,-13082988,4,-2184561,6902896,0,1612371,380717,281197612767569,24020655325649 +4612019606714,6849878514451,70368744177664,28388072,16105548,0,-8635096,34762028,0,0,8690507,-4026387,0,2158774,7097018,4,-779723,-426950,281197612767569,236429793929401 +-2265437113225,2392502107326,-70368744177664,-18999844,-32556296,0,24110492,-17944968,0,0,-4486242,8139074,0,-6027623,-4749961,-4,-60507,-423524,281197612767569,31571357036001 +1630326644623,-2210819460334,70368744177664,-25402820,21775432,0,12377692,33711624,0,0,-8427906,5443858,0,3094423,6350705,4,292480,73399,281197612767569,181618939845449 +79257724128,-17572371613384,-1490436804481,-4975744,-1243936,-447879684,5555072,1388768,-405084292,4,-25296606,27954365,-16,-84649,152461,0,-347192,-310984,281197612767569,242696745569009 +-27135863673426,16097016830812,-12247651961165,5914296,11828592,-81875252,-9577352,-19154704,-57784020,-8,4138025,-4167599,4,5153990,-8150607,0,-2394338,-1478574,281197612767569,183132164630233 +4593523981389,65775220196275,26043982479344,6561076,-6561076,75382720,9916660,-9916660,-57666624,4,12558010,18222549,4,-1858646,-623131,0,2479165,-1640269,281197612767569,188339549825281 +13946097456345,7438387209377,70368744177664,-28061852,-29626748,0,18881220,-20187932,0,0,-5046983,7406687,0,-4720305,-7015463,4,1499205,-726326,281197612767569,182062283725673 +26833380847621,-19332281195113,-43535363330043,-24572908,31349340,-24572908,-21445868,-18458788,-21445868,4,-1382050,-6536479,0,5361467,-6143227,-4,-3232647,-1300856,281197612767569,215976105269265 +-459796783441,70368744177664,15525489830962,16375484,0,25995464,12828700,0,-48390136,0,12097534,6498866,4,-628554,945697,0,3207175,-4093871,281197612767569,180294832441593 +-17103388103237,1955191764716,1827605036569,1272556,5090224,-301435804,-3225940,-12903760,-120612444,-16,754019,-2126895,4,7349773,-18308014,0,-806485,-318139,281197612767569,65025229236257 +13983886229202,-56384857948462,8192302449039,-14847160,-14847160,44493372,-12652792,-12652792,-37915300,4,-7963423,-8480754,-4,-1515402,-2642589,0,3163198,-3711790,281197612767569,35137469693833 +-14213101159212,-41942541859240,10501607889701,-2874544,5749088,100546708,10082640,-20165280,39005716,-8,-5059885,15196943,-4,2345772,-4969867,0,2520660,718636,281197612767569,67574931614001 +-12241935317250,-58126808860414,14468069727369,-15244296,15244296,-32362972,8014264,-8014264,-56843196,-4,-12150510,5899639,-4,2060289,-2191104,0,-2003566,-3811074,281197612767569,52462604652313 +-5252945858766,13428175083945,-70368744177664,242888,48603812,0,23158856,-1199004,0,0,299751,12150953,0,5789714,-60722,-4,1082451,-918642,281197612767569,8302573857601 +-2738648572556,30938978464237,39429765713427,796112,-36932684,36932684,-30495408,474004,-474004,0,-118501,-9233171,4,-4276490,-470863,4,3347362,-271835,281197612767569,77001925937065 +-12912005978612,28728369099526,-9084866983137,2353200,1176600,-143732612,15456304,7728152,12844156,-4,1560355,14631902,8,90329,6669349,0,-1932038,294150,281197612767569,77536887504465 +17018375881917,23822785616906,-53350368295747,-9601292,37947432,-9601292,24854036,19034216,24854036,4,-5711253,6379892,0,6213509,2400323,-4,952699,3106966,281197612767569,47536046438713 +13900307224569,42568129728526,-21846671812644,-12231708,24463416,6123376,-1922524,3845048,-91085200,8,-13476598,-2824780,4,4647351,-646968,0,480631,-3057927,281197612767569,128579411047009 +23463905233691,-46904838943973,-2252173449840,-12492692,-12492692,34166336,12204300,12204300,56747072,4,-9358651,5793418,-4,-4828117,2748166,0,3051075,3123173,281197612767569,26788323996617 +1621312160263,6285128049919,70368744177664,25365532,9156604,0,9748380,-40867972,0,0,10216993,2289151,0,2437095,-6341383,4,-453076,513651,281197612767569,28166792681329 +-1727525013158,70368744177664,34391170669261,7486824,0,70227764,-11119448,0,46081748,0,11520437,-17556941,4,-1075774,-1345771,0,2779862,1871706,281197612767569,9795425797977 +564985795673,-15632272085071,70368744177664,-12268188,28236484,0,-28539868,-26086524,0,0,-6521631,-7059121,0,7134967,-3067047,4,1637380,-624661,281197612767569,6034387926401 +-905481910254,34731631133705,-1232315800648,-15624120,-7812060,72789728,14382856,7191428,77116384,-4,-9546994,8947435,8,-185108,302562,0,1797857,1953015,281197612767569,257531606107113 +-9197368084301,-27702198367150,-70368744177664,3126988,44607816,0,-25182772,815944,0,0,203986,-11151954,0,6295693,781747,-4,-2505099,1149836,281197612767569,10219909493905 +8048354899397,15725111319824,-70368744177664,-12049644,40645696,0,28025908,-1098176,0,0,274544,10161424,0,7006477,3012411,-4,1597119,1835378,281197612767569,149906242025849 +-12442352525782,-57926391651882,23380703560019,-1994584,1994584,-72984244,-15575768,15575768,-5457652,-4,-170638,-14854177,-4,-1535051,3391884,0,-3893942,498646,281197612767569,139776283135137 +-18373020211923,14670577477512,51995723965741,19873972,-23757280,19873972,16706580,36680992,16706580,-4,5905177,5424424,0,-4176645,4968493,4,3265071,514896,281197612767569,209835732875273 +13136353659884,-28616195258890,6083037286551,1376176,688088,-118421924,18842032,9421016,14889180,4,1717311,12024512,-8,287673,5556457,0,-2355254,172022,281197612767569,247090979853745 +5459564793791,-70368744177664,17792879491655,-5610756,0,-51057380,-20661284,0,12652284,0,-3163071,-12764345,-4,-1551469,-635650,0,-5165321,1402689,281197612767569,249745255993241 +12203250283254,58165493894410,31694715066769,15414232,-15414232,-30211516,-7902632,7902632,-57553916,4,12783103,-4507392,4,-1605376,3045487,0,-1975658,-3853558,281197612767569,275095744077761 +6522771840242,18138997116293,70368744177664,20343752,21332500,0,-16297848,38253812,0,0,9563453,-5333125,0,4074462,5085938,4,-1936753,-816656,281197612767569,136915707973673 +6799104269635,-27314559517668,43054184659996,26282252,25165936,25165936,21068556,-22665104,-22665104,0,5666276,6291484,-4,3770111,-3412222,4,1497028,-3158341,281197612767569,187451146336977 +18299754118665,-52068990058999,-17731878456637,-23350236,-23350236,-41204,-1568572,-1568572,-48220692,4,-8821349,-1463356,-4,-3233824,1473657,0,392143,-5837559,281197612767569,183901358361017 +-30663375060645,-13489747322714,-39705369117019,-23185044,26413720,23185044,-17889748,-28180456,17889748,-4,-4832556,-2614819,0,4472437,-5796261,-4,2212558,3988611,281197612767569,53900268058337 +-7690523191760,-34749340052045,-35619404125619,-21718848,-29218100,29218100,-20450624,24327788,-24327788,0,-6081947,-7304525,-4,-1923246,3546727,-4,3189410,-1882985,281197612767569,276122042616905 +-2384734177011,-70368744177664,24364642067120,20189236,0,-26817856,-10383180,0,-41975104,0,10493776,-6704464,-4,-1254399,-1520384,0,-2595795,-5047309,281197612767569,126144215622641 +1733742962484,21745690921689,70368744177664,-22459184,-4610204,0,-8457392,48394884,0,0,-12098721,-1152551,0,-2114348,5614796,4,951474,-1706715,281197612767569,22856286840793 +10070815718890,50227112739884,-14552311464537,12586920,-25173840,31685276,-2720984,5441968,82600412,8,15020779,-4352509,4,-2814662,1784405,0,680246,3146730,281197612767569,45804618666497 +15879998863239,-38608746451186,-17255092767972,-11541988,-23083976,-58139536,8066748,16133496,-56914192,8,-8795704,6559654,-4,-2716422,3987615,0,-2016687,-2885497,281197612767569,31384100645993 +-15068369213179,55300374964485,22161387651626,-19992556,-19992556,-43900760,17881876,17881876,-17049944,-4,-4757636,7050949,4,495150,3924241,0,-4470469,-4998139,281197612767569,117227374629137 +16567665283713,53801078893951,-12649720314515,11150852,-11150852,-34750028,22185636,-22185636,31831508,4,5087228,7143243,4,-2870649,-1544264,0,-5546409,2787713,281197612767569,156584691722745 +-304498061465,70368744177664,-23006702099809,9552284,0,58404476,-10602404,0,53041980,0,13260495,-14601119,4,923981,717586,0,2650601,2388071,281197612767569,57364101476641 +20951272890235,-49417471287429,28963568450258,-16240148,-16240148,20603720,4091788,4091788,64136968,4,-11681321,1946216,-4,-4352921,3204714,0,1022947,4060037,281197612767569,112748090585225 +-16011104743279,54357639434385,-16730074611080,-21963196,-21963196,18950624,10379716,10379716,42307040,-4,-8787155,2354260,4,-1789605,2383396,0,2594929,5490799,281197612767569,215223026745905 +11389885792100,36199086801364,-21255462117145,-7541360,22624080,59180956,-4375024,13125072,-114963588,12,-13793757,-9319414,4,4982380,1825275,0,1093756,-1885340,281197612767569,145582235144217 +28863934654817,12640874868030,-12280809217028,-1769084,3538168,94838768,11675972,-23351944,10494192,8,547562,4413524,4,1585555,-9648084,0,2918993,442271,281197612767569,62286936069185 +429860259535,-70368744177664,28256098564156,-4587716,0,100823280,-8499748,0,-58619024,0,-14654756,-25205820,-4,763733,-614516,0,2124937,-1146929,281197612767569,280060053657769 +12035425936379,-14610497939151,58333318241285,22430700,21594308,-22430700,11496428,-39126844,-11496428,4,8705453,3310930,0,2874107,-5607675,4,-1076258,-2087647,281197612767569,188365602305873 +10243958148878,-30062393014393,-4564846228684,9061432,4530716,-118891312,10763000,5381500,107286864,4,11371292,12771435,-8,4079132,4179958,0,-1345375,1132679,281197612767569,65183408970297 +-351245440035,18992975755930,70368744177664,-31614092,-18922904,0,7403188,-31182616,0,0,-7795654,4730726,0,-1850797,-7903523,4,460630,2156825,281197612767569,124546590358369 +-14422816451141,-41523111275382,-14918015249032,-7795988,15591976,68384224,11107212,-22214424,46991072,-8,-8109462,9261656,-4,1819153,-3917200,0,2776803,1948997,281197612767569,125176078705865 +-15003426031154,25358466084202,-5530630390681,-3084488,-9253464,-130910820,6827576,20482728,-75246308,-12,-6376583,11975754,4,-4144998,6917317,0,-1706894,-771122,281197612767569,279202987733105 +31288891229054,7790961719556,-14011202466097,-1747464,3494928,82976572,13181368,-26362736,18401052,8,802955,2470683,4,2701609,-9136730,0,3295342,436866,281197612767569,255219198953561 +-15235090808366,27566826684649,-3279134093672,-4948152,-2474076,-148055456,-13415224,-6707612,53677152,-4,-5178839,-14528936,8,-3061610,-7955992,0,-1676903,618519,281197612767569,261382826387073 +-12431367869187,-16722879687053,-41214496621424,-17489932,33041868,-15551936,-29765932,-8140564,37906496,-4,-3444054,-5762065,-4,6032570,-1874081,-4,-1408913,2498402,281197612767569,98325301761257 +29590535860724,-2759678363719,-40778208316940,-18778160,-42542364,-18778160,24341456,-4811804,24341456,4,-935754,5979145,0,-6085364,-4694540,-4,-267197,4656446,281197612767569,173373032279441 +27255480386989,-43113263790675,-14747688781382,-26950988,-26950988,-28131608,-5449516,-5449516,36087592,4,-5813027,-2896814,-4,-3208871,-4136088,0,-1362379,6737747,281197612767569,234811489704569 +26428760303063,16364286507949,43939983874601,26434396,-19621196,-26434396,17071132,29921012,-17071132,4,5663330,1526157,0,-4267783,6608599,4,-1816923,-3379142,281197612767569,173932927800737 +-18675271311661,-33018201554342,-6689304970250,-12923060,25846120,41506776,5402604,-10805208,69771032,-8,-8441224,4254682,-4,4500767,-3061006,0,1350651,3230765,281197612767569,205253085194505 +-23676043334767,23016657508130,-12125542540115,-14661052,-29322104,-22995276,-7176252,-14352504,65539636,-8,-4740995,-3143515,4,-5821957,-1302652,0,-1794063,3665263,281197612767569,217019846258353 +20775218963448,-21204315948979,-28389209265237,28880864,-6484684,35365548,-15460640,-35512876,20052236,4,5092376,-3318225,-4,-79317,-5523162,-4,3785843,1697054,281197612767569,173232430272665 +-21582313632306,48786430545358,-4148932593579,16269112,16269112,4713812,5638072,5638072,-67571180,-4,11628617,1056824,4,5264178,121629,0,1409518,-4067278,281197612767569,40971486038209 +-1023521604773,12039215668947,-70368744177664,-30072468,-7155892,0,5312140,-36175508,0,0,-9043877,1788973,0,-1328035,-7518117,-4,-95666,-1312277,281197612767569,250407468278057 +14624762010218,11773408049089,55743982167446,27623848,-5391612,-27623848,8529320,39093508,-8529320,4,8098933,-87670,0,-2132330,6905962,4,-1674444,-1435573,281197612767569,75544535970769 +22462523381917,-47906220795747,-671315412870,-1356172,-1356172,53459432,-20846700,-20846700,-8440792,4,-1386879,-9101874,-4,-723319,-4262984,0,5211675,-339043,281197612767569,278023562488505 +176249602114,-70368744177664,14586524205523,-8472312,0,22371148,1480072,0,128983564,0,-32245891,5592787,-4,-4065,453058,0,370018,2118078,281197612767569,89083797110753 +-3532281699562,-27108159690951,-43260584486713,-23497640,16160996,-16160996,-21557864,-33088572,33088572,0,-8272143,-4040249,-4,3728516,-3408603,-4,-1660950,2465807,281197612767569,163303028145481 +-327420916375,4030305472476,-70368744177664,-21532252,27610992,0,-11461596,-37591696,0,0,-9397924,-6902748,0,2865399,-5383063,-4,207841,-276192,281197612767569,72622763506929 +9776644989096,30296049594284,-10440599644535,-4267360,2133680,-161802716,-12511328,6255664,53295940,4,-5968450,-17336199,8,1387085,5778281,0,-1563916,533420,281197612767569,103719257614553 +-29476246242959,-11416251691746,1478611164666,6947268,-13894536,-69578776,-12771196,25542392,-34156696,-8,1251174,-2895012,-4,-3644000,7249841,0,-3192799,-1736817,281197612767569,242503385529089 +27621018738683,15126706700298,-13430544217585,13251564,-26503128,9702460,2086924,-4173848,-83435556,8,4683053,-743175,4,-8087918,-1584395,0,521731,-3312891,281197612767569,116176173710697 +-10545007757996,59823736419668,-5664648168123,-16775856,-16775856,33898772,-11779760,-11779760,-43311084,-4,-9442257,-6867118,4,-1385514,-1607575,0,2944940,-4193964,281197612767569,263645311519249 +33043998052774,-37324746124890,8485417293107,16969368,16969368,-12703540,8842840,8842840,59729068,4,8186900,1172979,-4,6745367,2002906,0,-2210710,4242342,281197612767569,269403634699001 +-19698272183719,-50670471993945,14353508727723,4187492,-4187492,49472172,22962852,-22962852,2417260,-4,735816,8692329,-4,1340131,-3675714,0,5740713,-1046873,281197612767569,277334381345313 +-28193212076142,-10756979024337,42175532101522,2700872,33348796,2700872,-31626744,26356700,-31626744,-4,2740562,-5100121,0,7906686,675218,4,3848613,-3237078,281197612767569,221310243938697 +-21651901349687,-48716842827977,-1889659353570,-16072924,16072924,-37494664,-17036636,17036636,30306680,-4,-5131015,-6597368,-4,2445655,2776298,0,-4259159,4018231,281197612767569,162544506542897 +10779675560791,-48809393056082,9640687682548,4256092,8512184,82100176,12521276,25042552,-23002544,8,3131052,14528194,-4,1309792,2998425,0,3130319,-1064023,281197612767569,23249925804313 +19734744504191,-30899255169282,-9080059218120,-10255876,-20511752,-45941536,3718716,7437432,-93122848,8,-10462596,4381602,-4,-6409058,3551891,0,-929679,-2563969,281197612767569,61554057772353 +27433252932037,42935491245627,10808577428812,5272340,-5272340,44664112,21863412,-21863412,-28334672,4,3482550,7015409,4,-3601118,-4150619,0,5465853,-1318085,281197612767569,274807456197033 +-22593104924168,-25182534329328,18867965653303,9955296,-19910592,-51443492,13305824,-26611648,44338396,-8,2182949,5937117,-4,-4450825,-3461878,0,-3326456,2488824,281197612767569,89336215138385 +10883106298948,29742818939358,8932630770465,-13115120,6557560,52373636,-3874928,1937464,-156220892,4,-16568991,-5326098,8,5917241,2441213,0,484366,-1639390,281197612767569,128568344394553 +9409881713801,-23087236620508,-37871625843355,-36540892,-11768688,-24772204,3139684,31823248,-28683564,4,-6634417,448432,-4,-536474,5744619,-4,-1321395,-3390604,281197612767569,61424673981537 +11839915632399,58528828545265,24773339548357,-6193092,6193092,-43550956,-23797156,23797156,14453364,4,-910928,-9600889,4,2702413,1286850,0,-5949289,1548273,281197612767569,164217843422665 +28297943043851,-42070801133813,13902762479382,22065196,22065196,-35707816,13843884,13843884,28622680,4,4961888,4247231,-4,2193782,4679723,0,-3460971,5516299,281197612767569,93033616099697 +-35127142060045,-17764363566677,-35241602117619,30184396,10549932,-30184396,-1772500,-37920244,1772500,-4,4859606,3225875,0,-443125,-7546099,-4,-4620455,588392,281197612767569,25703003982169 +-5141221049968,-65227523127696,-546060966417,10069568,-10069568,54066108,12882496,-12882496,-42642692,-4,9856800,12548529,-4,-803873,-967998,0,3220624,-2517392,281197612767569,114612209799041 +-29120106516131,-41248637661533,-4785039864789,14463348,-14463348,-40819540,8353876,-8353876,54268108,-4,8094713,5736008,-4,-5472314,-4468877,0,-2088469,3615837,281197612767569,54402923668969 +-21271495277509,49097248900155,-22316278399512,3720428,3720428,-55552096,20237292,20237292,450464,-4,1683054,9394899,4,-1570438,4493125,0,-5059323,930107,281197612767569,93473765009041 +34054151847619,36314592330045,3468879485841,-15560948,15560948,21891652,12446444,-12446444,54844132,4,-7229124,2632587,4,6481909,-2840326,0,3111611,3890237,281197612767569,241838780349305 +2161471222057,22735757651869,8726886866738,9502884,-3167628,-81890104,-2284572,761524,-335752376,4,27143551,-6516352,12,-2507441,923470,0,-190381,-791907,281197612767569,206461741129377 +12607640904282,-5714068107277,-70368744177664,-23994008,10032076,0,-26802136,-35718036,0,0,-8929509,-2508019,0,6700534,-5998502,-4,-2143954,37739,281197612767569,249963636201993 +-12747391147869,57621353029795,-14947263804885,-11692404,-11692404,47914156,15420172,15420172,33103148,-4,-7595480,9187705,4,-680307,2790834,0,3855043,2923101,281197612767569,224768177276849 +-25672258623990,-44696485553674,4820840440041,-4444120,4444120,44154788,-26413208,26413208,9083844,-4,1894839,-7087622,-4,-376122,3951075,0,6603302,-1111030,281197612767569,8012292231577 +-8939989324756,706887867129,-70368744177664,7897264,-41064476,0,-26133072,-6680668,0,0,1670167,-10266119,0,-6533268,-1974316,-4,-277816,1284425,281197612767569,90841787150785 +1999965365977,70368744177664,24865068821274,16062308,0,27460712,-16886332,0,41226280,0,10306570,-6865178,4,-1784638,-1223803,0,4221583,4015577,281197612767569,44323357454889 +-4610593600175,-65758150577489,6519195808371,-7286460,7286460,61185484,13246276,-13246276,43288524,-4,-9806265,14462906,-4,1015866,-833465,0,3311569,1821615,281197612767569,241042865122513 +28771707681563,-41597036496101,-22757227462185,3743852,3743852,-44905636,24391244,24391244,8172220,4,-764320,6938951,-4,2807375,4287458,0,-6097811,935963,281197612767569,160385428769721 +-4965630575315,13272382667309,-70368744177664,-6774604,-29846348,0,32812532,-21634572,0,0,-5408643,7461587,0,-8203133,-1693651,-4,-1165543,-845976,281197612767569,122015889901793 +16683713175553,-26308497079798,53685031002111,20798468,-21323736,-20798468,-19228188,-34419992,19228188,4,4767648,-6010985,0,-4807047,-5199617,4,-3837350,-680051,281197612767569,223476972301897 +-23984194536591,46384549641073,16929992316738,-11793980,-11793980,46863624,-18822076,-18822076,-20674040,-4,-2274797,-8432082,4,-2893713,-3283824,0,4705519,-2948495,281197612767569,135971565884913 +26625957180241,-43742786997423,14112010714103,21391684,21391684,2569180,-3617948,-3617948,52198076,4,7930484,-1471757,-4,5119035,829462,0,904487,5347921,281197612767569,178966901074393 +-13321908555543,-7333704509564,-70368744177664,-917596,-33763824,0,32861284,-17848048,0,0,-4462012,8440956,0,-8215321,-229399,-4,1700915,-1574098,281197612767569,246705896825857 +33010200095423,37358544082241,-6295141139424,3198716,-3198716,43020416,-25149284,25149284,13745280,4,2386791,-5638312,4,-1049529,5116792,0,6287321,799679,281197612767569,145223094029929 +-7158599117489,-56051545942686,17825479563460,8141116,-16282232,-67448048,6615612,-13231224,83488528,-8,15787578,14462408,-4,-2542277,-1199802,0,-1653903,2035279,281197612767569,135279178597137 +23547351251189,46821392926475,4284476518426,16084948,-16084948,22812776,5783796,-5783796,-61794136,4,10190984,4039583,4,-5257550,-1663611,0,1445949,-4021237,281197612767569,93950153108473 +14048044506779,-5722513190423,-70368744177664,14724716,39420836,0,-26704340,4970724,0,0,1242681,-9855209,0,6676085,3681179,-4,-294829,-2266802,281197612767569,263876044014369 +1157118790366,-34605812693649,4821607719722,-10685576,-5342788,-99834712,-15091272,-7545636,69735784,4,-8444379,-12365654,-8,-545188,-227370,0,-1886409,1335697,281197612767569,98209244959369 +-27927174532754,42441569644910,4977868996103,-10662472,-10662472,-57279460,-13455688,-13455688,33309852,-4,-5260514,-8448189,4,-3066949,-5871676,0,-3363922,2665618,281197612767569,175224588317745 +10757936171131,6635823916647,70368744177664,23647724,34217372,0,-18646964,20629884,0,0,5157471,-8554343,0,4661741,5911931,4,-1228077,750284,281197612767569,214031480836633 +4281599269830,33043572453917,7387429906993,16160536,-8080268,-73874236,-13937256,6968628,-75628412,4,9061243,-8460348,8,-784617,1547863,0,-1742157,-2020067,281197612767569,238741798856257 +2044311565844,21250686397191,-70368744177664,4524112,-45961188,0,-23290928,-12250180,0,0,3062545,-11490297,0,-5822732,-1131028,-4,-1669438,-675369,281197612767569,57320160836265 +-21890568980673,26587606216318,1924010489302,9699580,19399160,52739928,-5652228,-11304456,85344088,-8,8138716,-4849114,4,6598653,-4167934,0,1413057,2424895,281197612767569,124663662225745 +-27328381767045,-43040362410619,-5043666980916,-21856788,21856788,-4649168,4955596,-4955596,52566704,-4,-8126777,-1102550,-4,5014899,59742,0,1238899,5464197,281197612767569,67624928517177 +13036486335839,-31259285170147,-555026381675,-4318852,-12956556,-120447404,6190396,18571188,-88051820,12,-9815240,13350773,-4,-4065905,5587026,0,-1547599,-1079713,281197612767569,275266281229665 +14196460744357,-16437335295436,56172283433307,22120084,22321360,-22120084,16495092,-34254256,-16495092,4,7799184,3162791,0,4123773,-5530021,4,-764380,-2417549,281197612767569,176321310656201 +29914312649425,40454431528239,4582311203801,-16627900,16627900,31116132,-17257532,17257532,-35417116,4,-5371201,-4201408,4,3483078,3577625,0,4314383,-4156975,281197612767569,91844434272881 +-20517394777139,538468883522,-49851349400525,-26993868,22882568,26993868,6072020,36562248,-6072020,-4,-6463835,4104316,0,1518005,6748467,-4,2676727,-1616326,281197612767569,227178135390809 +6259963640893,-64108780536771,29331068362105,12803316,12803316,-47943196,6834868,6834868,62344356,4,14911786,9585381,-4,674303,2400418,0,-1708717,3200829,281197612767569,48775245019265 +459103407777,-27505980267210,70368744177664,23500420,13040856,0,-9098524,42860824,0,0,10715206,-3260214,0,2274631,5875105,4,819207,2317752,281197612767569,100237887354601 +-5954944846713,-24330817071714,-70368744177664,24827420,2498168,0,11818268,-44159880,0,0,11039970,624542,0,2954567,-6206855,-4,-1955832,2093241,281197612767569,246146937036689 +403135054298,70368744177664,-9657784339389,11689832,0,-44735220,-9344088,0,-60556052,0,15139013,-11183805,4,-407338,-337023,0,-2336022,-2922458,281197612767569,53416353799289 +-15661299730079,-19130879801732,54707444447585,8864132,37005808,8864132,26382020,-16878352,26382020,-4,1487380,7794909,0,6595505,-2216033,4,2732208,1456543,281197612767569,14349113190305 +-7877547354846,5923799622039,-70368744177664,18582664,-27964836,0,17009224,34991740,0,0,8747935,6991209,0,-4252306,4645666,-4,-1337271,-391560,281197612767569,30450896194313 +17845275418337,-16832917922653,-5763516486420,-3483772,-10451316,-129924176,6819076,20457228,-68872784,12,-4537652,7555793,-4,-4226848,8308417,0,-1704769,-870943,281197612767569,272174906777777 +10115729517434,-60253014660230,27896487352603,-17791512,-17791512,-13133716,6648616,6648616,-58374964,4,-11836912,4574711,-4,-2756829,-1291282,0,-1662154,-4447878,281197612767569,256797090435737 +27274186107937,-15820371961790,-4960872880731,11209860,22419720,5399188,704068,1408136,-100099244,8,5650921,-91675,-4,9686945,720736,0,176017,-2802465,281197612767569,156038071999169 +9202779498735,11067094990785,-70368744177664,25036732,6675204,0,-9512868,42433636,0,0,10608409,-1668801,0,2378217,6259183,-4,1761390,766155,281197612767569,257753712608041 +-7248915001626,31559914588019,2997591733386,-23993448,-11996724,-13735384,-6746216,-3373108,89988648,-4,-10125750,-1412297,8,-2245662,-609252,0,-843277,2999181,281197612767569,140410657285585 +28384851933992,-41983892243672,23073028027485,13061280,13061280,40549748,-13763168,-13763168,43472532,4,5356029,-7118926,-4,5512104,-3018511,0,3440792,3265320,281197612767569,166200313064633 +-9215982276465,-51936779624734,-16651079256148,-7821764,15643528,71282352,6536188,-13072376,84378032,-8,-16342456,12227354,-4,2376026,-2796617,0,1634047,1955441,281197612767569,200266949890529 +29548635902985,-40820108274679,4211989922005,-18019292,-18019292,14290772,4218116,4218116,59137716,4,-8639399,1802838,-4,-6145030,1769855,0,1054529,4504823,281197612767569,110632736563017 +4088725475694,-33140009350985,6505572839395,21024184,10512092,45732748,-9697096,-4848548,86011660,4,10014690,-5627395,-8,1473535,-178397,0,1212137,2628023,281197612767569,132608302264049 +4302230500191,-70368744177664,-30184396486363,-3640964,0,-47452012,23077212,0,-8470220,0,-2117555,11863003,-4,2345256,1115729,0,-5769303,-910241,281197612767569,29302767266521 +-6180705916765,70368744177664,-20275747553551,-17779060,0,-34138172,12830412,0,-38691196,0,-9672799,8534543,4,-1773817,-531080,0,-3207603,-4444765,281197612767569,80977793289473 +24935019449320,-45433724728344,-16662649136187,17010592,17010592,-25707756,8230560,8230560,53749492,4,8188638,5156553,-4,5248735,1270386,0,-2057640,4252648,281197612767569,125865514360681 +-20857831808602,49510912369062,-636893978195,18034328,18034328,-30330188,-11030376,-11030376,-43880012,-4,7743369,-5294216,4,3226634,-2288331,0,-2757594,-4508582,281197612767569,260223273188369 +14932160753260,25572261917884,-9969604904405,-8287824,24863472,-25699156,-1024720,3074160,132672396,12,-12162294,-1454149,4,7001935,1656880,0,-256180,2071956,281197612767569,13671159287033 +13710526182263,-29237165630875,-5311884792162,7999964,23999892,-42892680,-3067748,-9203244,-124290056,12,12736487,-4908234,-4,6112009,-1938312,0,-766937,-1999991,281197612767569,254398121167905 +2522145930087,-6680189944421,70368744177664,30634396,5253740,0,16464316,-33929204,0,0,8482301,1313435,0,4116079,-7658599,4,86723,-774116,281197612767569,69794979185545 +-6719645462569,-13687231404003,70368744177664,-2227364,-32404364,0,-33497124,18159092,0,0,-4539773,-8101091,0,-8374281,556841,4,-2062370,-665279,281197612767569,42108335279409 +15470320802227,-54898423375437,14264291990200,-18793780,-18793780,30444256,-12515284,-12515284,-39634464,4,-8364478,-4985387,-4,-1544138,-2625677,0,3128821,-4698445,281197612767569,201101959566105 +-10923653753562,-59445090424102,9851592247941,-17630056,17630056,-26839532,-6210792,6210792,54407380,-4,-11707747,-5051228,-4,1894098,1658655,0,-1552698,4407514,281197612767569,55047468339009 +-19331363303530,51037380874134,33014778337513,-12507560,-12507560,-44130396,16781464,16781464,-30807548,-4,-7554394,6534739,4,-147493,4497860,0,-4195366,-3126890,281197612767569,190785971588009 +130687491331,-70368744177664,-34957489140152,-1701876,0,-54388448,-20335604,0,11680032,0,-2920008,-13597112,-4,2520136,-236615,0,-5083901,425469,281197612767569,189347955335761 +15760380347139,-54608363830525,7080038374099,12034060,12034060,-48119988,12757228,12757228,42547756,4,8575487,9032960,-4,2061452,2997037,0,-3189307,3008515,281197612767569,230539465915705 +-25710061817143,18948620543378,3245259027833,2656036,5312072,86757860,-12215964,-24431928,24875044,-8,1956251,-5779209,4,2131255,-7955128,0,3053991,664009,281197612767569,202178059048545 +12948699209929,31522646547877,735425021948,-7323868,21971604,44675056,2869764,-8609292,136224880,12,-15278446,4945795,4,6259258,-2074323,0,717441,1830967,281197612767569,4679388690377 +20261145807337,-50107598370327,-8158558567798,-7838812,-7838812,45457960,-23939036,-23939036,-4806872,4,-161836,-8319541,-4,-1039882,-3044949,0,5984759,-1959703,281197612767569,199154573736817 +-28575960243905,-41792783933759,8345667049520,3123452,-3123452,-48389952,22360796,-22360796,14042816,-4,1422054,7277443,-4,-2088650,-4820045,0,-5590199,780863,281197612767569,87141323115353 +-21055549418495,49313194759169,-6478549614825,-24105980,-24105980,-13385636,-634684,-634684,46353820,-4,-8106380,-2899939,4,-3482075,-446470,0,-158671,6026495,281197612767569,156189989151105 +-21659128719380,-21107306045623,48709615458284,15544240,-35374812,15544240,-25692112,-13963132,-25692112,-4,4342944,-4956023,0,-6423028,-3886060,4,-852161,-3887680,281197612767569,78400867715049 +-27573709169047,42795035008617,-1144939853299,16692644,16692644,30430260,7137956,7137956,-54436556,-4,8247418,4694471,4,5361721,2913094,0,1784489,-4173161,281197612767569,22559610312849 +-17514842463694,-36406851748965,-33961892428699,-2064184,35660396,-35660396,-31130616,-7639732,7639732,0,-1909933,-8915099,-4,4231507,1969918,-4,-3551147,2485964,281197612767569,220033137950073 +-5677811290039,-64690932887625,-26133337611613,-4752092,4752092,-55599476,-18968476,18968476,14996044,-4,-1685402,-13219541,-4,2063609,680328,0,-4742119,1188023,281197612767569,271512339378337 +-7494782964250,-31436980606707,3540273745193,-4694120,2347060,163868836,11641048,-5820524,73324676,-4,-8116175,18331472,-8,2098819,-4304265,0,1455131,586765,281197612767569,112983771347977 +-26374266624622,2166342075869,-43994477553042,32837192,18416500,-32837192,981320,-33736972,-981320,-4,5280634,2625767,0,245330,-8209298,-4,-3153609,-1978358,281197612767569,21128012183985 +-15544260443242,4112920120167,-54824483734422,27260504,-21843556,-27260504,8745752,34293628,-8745752,-4,6551772,4652925,0,-2186438,6815126,-4,-2021635,-807964,281197612767569,113575293719449 +-24845129164040,45523615013624,11289039690817,-9925664,-9925664,-39760636,22339040,22339040,-23946556,-4,-4768879,6032496,4,-1217760,3907663,0,-5584760,-2481416,281197612767569,256930179285953 +19466592986211,31435558205242,-10975857609991,14263692,-28527384,-23476252,5513644,-11027288,69859908,8,7372063,3734263,4,-5046457,-1067400,0,-1378411,3565923,281197612767569,112776357123113 +23430883168103,-28575414275672,-18362446733889,-26230372,14755488,-40985860,-16024676,-33909088,17884412,4,-4027741,-5123492,-4,-443362,-5122973,-4,-4449531,1434620,281197612767569,61278802042577 +1755679830008,34306532173828,-3393282512823,-7741472,3870736,133324068,12215008,-6107504,80507332,4,-9738709,16296372,8,649415,-738273,0,1526876,967684,281197612767569,199505509420473 +-4139397376504,22076448933720,-362730000107,1128480,376160,219664468,15288864,5096288,-17084524,-4,1333394,17229055,12,270949,3228952,0,1274072,-94040,281197612767569,268057582492385 +-31960387896955,-38408356280709,-5857579242840,-1756652,1756652,-36697440,29515636,-29515636,-24336992,-4,-2706648,5044065,-4,3377600,-4130295,0,-7378909,-439163,281197612767569,178499549237321 +24779749567936,-45588994609728,-17363846996853,-16795904,-16795904,-36641236,9836288,9836288,-45575764,4,-7988451,4898466,-4,-3405490,4261843,0,-2459072,-4198976,281197612767569,196782527023089 +-8278916924921,-34769184575421,35599559602243,18213916,-24619764,-24619764,26029308,26631532,26631532,0,6657883,6154941,-4,-4075361,1579474,4,-2431966,2974005,281197612767569,62121969298393 +23974987981978,46393756195686,-5935859992267,20834920,-20834920,-2658092,399848,-399848,-54090092,4,8923763,-877492,4,-4598760,-212969,0,99962,-5208730,281197612767569,191338426267137 +2502448814142,-70368744177664,-19880258257655,-16275208,0,-26038236,-9829320,0,53453188,0,-13363297,-6509559,-4,219009,-1380992,0,-2457330,4068802,281197612767569,136401242157161 +-22019020325499,-4288567875401,48349723852165,-15711724,-36772132,-15711724,-22905580,18051036,-22905580,-4,-2751685,-6555834,0,-5726395,3927931,4,-1761074,-2637199,281197612767569,271779881006353 +21098031395207,49270712782457,5744083542208,-15807972,15807972,23167744,-5579140,5579140,-63046912,4,-11149884,-3732797,4,4611844,2059139,0,1394785,-3951993,281197612767569,165830335131129 +14060703118813,-28042214806764,-42326529370900,-16661644,-34415536,34415536,-24307276,17366352,-17366352,0,-4341588,-8603884,-4,-4522696,786297,-4,1554123,-3379114,281197612767569,244696259253537 +3721626327789,20797109365613,70368744177664,-6547532,-47097420,0,23180564,-5216492,0,0,-1304123,11774355,0,-5795141,-1636883,4,1781695,-138944,281197612767569,14542437495945 +-5853520331531,-30992356773231,-33522867072902,22970324,-32086460,9116136,-15969964,-26707516,42677480,-4,7879877,-4825156,-4,-2789493,-2546122,-4,1202998,3196459,281197612767569,263772726158897 +86781310617,-70368744177664,16173738586565,14571108,0,-12119276,2790020,0,74948788,0,18737197,3029819,-4,-137209,841002,0,-697505,3642777,281197612767569,217748164596761 +25920879860760,18526984456144,449740833651,10293344,-20586688,-59973172,-7370144,14740288,-66439924,8,4396699,-3914605,4,-6106641,5539344,0,-1842536,-2573336,281197612767569,110079521814593 +-32100061032054,-6168622113556,-15535003417593,10083880,-20167760,-52882404,-8394776,16789552,-67629124,-8,2408755,-45849,-4,-7249263,6587376,0,-2098694,-2520970,281197612767569,240899422870697 +7489473893822,-31439635141921,-11651731437044,-11493640,-5746820,49379376,-3436808,-1718404,-181151696,4,-20162790,-5753371,-8,-4962344,-838102,0,429601,-1436705,281197612767569,108505693363025 +12907560723657,-57461183454007,-16681926060886,13782820,13782820,-39949656,-17898044,-17898044,-29810968,4,5024957,-8972302,-4,2427785,-1015112,0,-4474511,-3445705,281197612767569,218212606369337 +7435725464015,-27859659331614,-42509084846050,-27563204,-25569400,25569400,-18752772,23451656,-23451656,0,-5862914,-6392350,-4,-3451615,3487200,-4,1236578,-3403601,281197612767569,41881774841697 +-24947439125139,1119845342613,45421305052525,-9920076,30900820,-9920076,-25863148,-32933964,-25863148,-4,-5211621,-5025898,0,6465787,-2480019,4,-3021870,-2699307,281197612767569,25649341032649 +-7877965743555,-62490778434109,-4211986316931,-16624396,16624396,-19369484,-7411852,7411852,59090036,-4,-13007777,-4549022,-4,1764732,293349,0,-1852963,4156099,281197612767569,54332424639601 +-1478021935545,70368744177664,-14188502546326,20266268,0,9779624,-4869124,0,53205736,0,13301434,-2444906,4,524824,970223,0,1217281,5066567,281197612767569,146425871699033 +-6751681540771,-16355291851496,-6335060910912,401780,-3214240,377254656,2920244,-23361952,-60292352,-32,2977528,21992976,-4,-1511945,-9040086,0,730061,-100445,281197612767569,148335454194305 +25831763664706,10434200840781,34102779672177,5780744,-36907724,31126980,-33280568,17715732,15564836,4,-1569408,-5625513,4,-5460617,2156232,4,2859525,3601418,281197612767569,175648333846761 +3016302861945,-70368744177664,-33262932517075,16807396,0,4925620,851684,0,-66738764,0,16684691,1231405,-4,614530,2038975,0,212921,-4201849,281197612767569,149446172119441 +-29931709128136,-40437035049528,5245104425037,7907552,-7907552,-40481484,25852896,-25852896,10032980,-4,959598,5962971,-4,-1548647,-4157400,0,-6463224,1976888,281197612767569,202119655939705 +-7381506371926,318322113379,70368744177664,5198504,34931084,0,-29507800,18305356,0,0,4576339,-8732771,0,7376950,1299626,4,446676,-921925,281197612767569,60604806756769 +-5376327069379,26332592985339,70368744177664,15315188,-38598676,0,-18780588,-26182772,0,0,6545693,-9649669,0,-4695147,-3828797,4,2257070,695513,281197612767569,203089656950025 +22835730924994,-47533013252670,24674689937765,9424648,9424648,-47017580,-21444088,-21444088,-12483308,4,3987905,-7113730,-4,-867078,-4640665,0,-5361022,-2356162,281197612767569,122874072453809 +19225861851669,20618305769754,-51142882325995,-19909548,-32203672,-19909548,27665908,-11801176,27665908,4,-117673,7309672,0,-6916477,-4977387,-4,-2832621,741246,281197612767569,244276497831065 +30109598437486,40259145740178,7049316945745,15976888,-15976888,-23668412,-2618824,2618824,-66590972,4,9590041,-2985146,4,-7057702,2931957,0,-654706,-3994222,281197612767569,220240757238977 +35239287060089,-35129457117575,-31878004975331,12309988,12309988,-37072780,-26297276,-26297276,-12265388,4,-1447476,-6021013,-4,4513823,-3247182,0,-6574319,-3077497,281197612767569,112713693357353 +-32944491836857,373983434840,-37424252340807,28978460,10813792,-28978460,9675548,42463584,-9675548,-4,5633003,-1399274,0,-2418887,7244615,-4,-4982893,1304174,281197612767569,235138671450065 +34187605230855,-36181138946809,-17585597824095,-9889764,-9889764,48982660,-13835908,-13835908,-45317596,4,-4960759,-6914170,-4,-6368640,-5331495,0,3458977,-2472441,281197612767569,15736738410169 +-34668771283143,-35699972894521,11448445992601,-7292700,7292700,-55478684,18156836,-18156836,-16260444,-4,-2800835,6739844,-4,1264276,-7129827,0,-4539209,-1823175,281197612767569,232339284961 +-17080659121117,8852001115908,-53288085056547,-6830964,-39932912,6830964,28171820,-134256,-28171820,-4,-911382,7345167,0,-7042955,-1707741,-4,-877818,-2638061,281197612767569,91863819583817 +-27564405678039,-18606441460673,42804338499625,27245732,-6007556,27245732,6444836,39902844,6444836,-4,6494113,-887456,0,-1611209,6811433,4,3481598,2389345,281197612767569,209929134596337 +17215130937405,53153613240259,-16150029024670,-16839436,16839436,28000648,17090708,-17090708,38442440,4,-6278850,6253817,4,3331760,-746345,0,4272677,4209859,281197612767569,221895160212697 +3216511777391,12027877114372,70368744177664,-15315524,38434832,0,21645052,19194640,0,0,-4798660,9608708,0,5411263,3828881,4,-705584,-1093665,281197612767569,190519067172609 +14886605852625,40595532472414,-6119746340098,-11674812,23349624,-10472456,-29788,59576,-96465096,8,-13911316,1002722,4,5102479,-807696,0,7447,-2918703,281197612767569,98486332621161 +-15246405929960,-39875932317744,13434238816295,7630944,-15261888,-61422436,11647072,-23294144,53795228,-8,6509267,9429999,-4,-3469770,-2962805,0,-2911768,1907736,281197612767569,61846973689361 +9103921595057,26663688672517,-34601133910090,2696900,-40853484,-38156584,-28526236,14645044,-13881192,4,-485341,-8636548,4,-3955639,902598,-4,-3175920,-1576823,281197612767569,231501411192569 +23630588975601,46738155202063,-8502479701745,25789380,-25789380,1820732,3727108,-3727108,43920636,4,7180318,476689,4,-3799841,931872,0,-931777,6447345,281197612767569,174770184576545 +30083000811773,4268671479055,40285743365891,8679412,-41707460,-8679412,-27971756,4692828,27971756,4,-247453,-5837700,0,-6992939,-2169853,4,925754,4589165,281197612767569,15062111380873 +1737728370379,19473010215938,-50895733961726,-15397076,30861320,30861320,-30283348,-12425464,-12425464,0,-3106366,-7715330,4,5552484,-2593541,-4,2018353,-1255728,281197612767569,144873981017905 +6421464089362,63947280088302,-13311363918101,13861960,-13861960,-21147732,-3514232,3514232,-75860980,4,17068388,-5460029,4,-1896857,-173096,0,-878558,-3465490,281197612767569,228121362863385 +33494805587373,36873938590291,12781674187798,15811252,-15811252,-33286056,-18728076,18728076,-31782184,4,5013982,-3642575,4,-2931564,4678939,0,-4682019,-3952813,281197612767569,111059584950593 +419989169850,34974377503907,-16829874239925,3699432,-1849716,230198572,-8116568,4058284,103631436,4,13119267,-28492484,8,330675,564675,0,1014571,462429,281197612767569,26006500289961 +-2907590091415,-70368744177664,-29584222777540,20099492,0,25939184,8371620,0,-45212432,0,11303108,6484796,-4,-1346930,1844595,0,2092905,-5024873,281197612767569,16701573911633 +-32494677499792,19033510592785,37874066677872,21610944,29597764,21610944,21444544,-22728732,21444544,-4,4508374,2521203,0,5361136,-5402736,4,1173809,4878238,281197612767569,151996251684665 +-15347146082163,55021598095501,-14298244565130,-17691084,-17691084,17450456,3357044,3357044,60330840,-4,-11963760,2512481,4,-3118950,1850133,0,839261,4422771,281197612767569,169475595610209 +-14969153806447,33308487417710,-37060256759954,-32826812,-1538632,-1538632,14119972,-33636360,-33636360,0,-8409090,384658,4,-3647918,-4240299,-4,117925,-3966404,281197612767569,182282065598921 +-7534247495083,-5876337237361,1992161785172,521556,-1216964,1327891792,-2431020,5672380,286773072,-28,6027092,-27713709,-12,-7658856,35547403,0,202585,43463,281197612767569,271536449596785 +24787817320121,-45580926857543,19561941551887,16922340,16922340,-16510916,5309444,5309444,61352988,4,10304252,1497643,-4,5033995,2630086,0,-1327361,4230585,281197612767569,184423218679129 +-11407063162503,58961681015161,27249106017547,2458084,2458084,52226092,-21157724,-21157724,8508524,-4,3830557,-10702044,4,-1703426,-2354479,0,5289431,614521,281197612767569,210172141826945 +-28303622235092,-42065121942572,-14867662997999,14696624,-14696624,28079172,-9633488,9633488,58203812,-4,8189442,-4972585,-4,-6361511,2047208,0,2408372,3674156,281197612767569,273111177030121 +4626682639186,-70368744177664,-4546733341931,-15973048,0,-26339244,-11649208,0,51278164,0,-12819541,-6584811,-4,-654701,-690962,0,-2912302,3993262,281197612767569,42583847013009 +8144220592714,54080302992236,3573046459947,9437480,-18874960,60419244,7646056,-15292112,-70350452,8,13322443,11848059,4,-2132585,-1628376,0,1911514,-2359370,281197612767569,271103630573433 +7584788211295,-55199167755074,-7386317742017,5979516,11959032,-87513860,7894076,15788152,72758204,8,13854077,17475889,-4,2167737,2201288,0,-1973519,1494879,281197612767569,14320714613409 +-3592167365133,22733891626177,70368744177664,17853388,-29004028,0,16958572,35513316,0,0,8878329,7251007,0,-4239643,4463347,4,1822912,-1071817,281197612767569,219777297735177 +-16090603206159,-12443879073790,54278140971505,9847748,-37611512,9847748,-24576700,-20464888,-24576700,-4,5032865,-6817440,0,-6144175,-2461937,4,83357,-2585438,281197612767569,169628105534385 +-22293923143279,-10478043932700,48074821034385,-5627324,-35696752,-5627324,-32064668,-3323888,-32064668,-4,1761330,-6306345,0,-8016167,1406831,4,-930358,-2617843,281197612767569,219411774576025 +3786698891875,-70368744177664,-15813837967761,-15753844,0,30678460,-9423156,0,-53117956,0,-13279489,-7669615,-4,-1244011,472364,0,2355789,-3938461,281197612767569,40784589149633 +17820005060231,-34728734057202,3512620233754,-6734308,-13468616,82520168,-9874500,-19749000,-46189528,8,-5945376,-10013362,-4,-2801003,-5308340,0,2468625,-1683577,281197612767569,55315191248425 +16103356952051,13927430990608,-54265387225613,-19100724,34630720,-19100724,21439948,20073536,21439948,4,-4930817,5731328,0,5359987,4775181,-4,-87567,2926352,281197612767569,231511213134033 +4718575542367,13054865196862,-70368744177664,-19323524,25847032,0,22137308,28655032,0,0,-7163758,6461758,0,5534327,4830881,-4,546367,1329522,281197612767569,67252588892089 +-12231286533265,58137457644399,-28619746055243,-26037828,-26037828,5978836,-240772,-240772,-43185644,-4,-8944292,1412565,4,-1852119,-2907274,0,60193,-6509457,281197612767569,43608345767137 +-32312229776259,38056514401405,8156850364156,26099188,26099188,18680816,10273876,10273876,-35785616,-4,5136081,1769392,4,3810323,2900812,0,2568469,-6524797,281197612767569,252635719037513 +20813264697890,11469930223213,38085549256561,-7593848,-27720268,35314116,-33364600,26471988,6892612,4,-3300977,-5189776,4,-5024130,3638753,4,3317020,1740291,281197612767569,74446754789873 +-24149680392955,-46219063784709,1905653258723,-19914732,19914732,-7898228,-5347148,5347148,54415340,-4,-8971369,-1162086,-4,4632466,812471,0,-1336787,4978683,281197612767569,26452416703961 +-13782148963211,-11508067486439,-70368744177664,15801812,36982884,0,-29643884,1872164,0,0,468041,-9245721,0,7410971,3950453,-4,-1303655,1164776,281197612767569,134495907334145 +15412003143015,-39544737891634,-8970175199496,-231012,-462024,-97502240,-11548100,-23096200,-284448,8,-696078,-13683476,-4,383595,-5346042,0,-2887025,57753,281197612767569,112486135173737 +6775615618585,63593128559079,28956240539096,11498596,-11498596,37705568,15475556,-15475556,-47169696,4,9064943,9701648,4,-2727481,275256,0,3868889,-2874649,281197612767569,89880976205585 +6183382082423,64185362095241,-15996436703799,-4599332,4599332,82776868,-11774916,11774916,-32876348,4,-6827689,-19137176,4,1391398,1557041,0,2943729,-1149833,281197612767569,69986375905273 +-1319281971370,-70368744177664,26047102269229,6333784,0,52660404,-20341544,0,8637172,0,2159293,-13165101,-4,1841881,832936,0,5085386,1583446,281197612767569,114641168394017 +11306108909,70368744177664,-18279123288907,117684,0,160267988,7024916,0,-261324,0,65331,40066997,4,456191,-14080,0,1756229,-29421,281197612767569,165685458081417 +19384889019955,-22769679583670,-50983855157709,30018764,7893288,30018764,3366732,-36621272,3366732,4,6905598,-998623,0,841683,-7504691,-4,2249720,2971945,281197612767569,108619537717297 +28689481180055,-6737726304259,41679262997609,-25144740,16231412,25144740,-15875012,-34529132,15875012,4,-4732880,-3005353,0,3968753,-6286185,4,3899403,1052500,281197612767569,33889913525785 +-24158802628932,36059756749023,-34308987428641,26495728,19605372,19605372,-21283856,26744764,26744764,0,6686191,-4901343,4,4889774,1546849,-4,431190,5077083,281197612767569,219724197513793 +6204990287485,33929195420499,36439548757165,4662772,32457036,-32457036,34766804,542060,-542060,0,-135515,8114259,4,4512835,-1319140,4,-4178866,-153447,281197612767569,22824431287977 +-33339097489373,37029646688291,2334164620207,25269388,25269388,13939388,9831564,9831564,-39132484,-4,5229632,1624257,4,4553489,1860590,0,2457891,-6317347,281197612767569,174329951456593 +-2663049396398,29141955459945,-41226788717719,-3246776,-32036444,-32036444,-36271480,-11121596,-11121596,0,2780399,-8009111,4,-5207352,172447,-4,-3860518,639247,281197612767569,252580602257465 +-20176780095719,30015183986226,-9414219217139,-9979804,-19959608,57034804,-6182236,-12364472,-77486220,-8,-8676313,-5414357,4,-5347621,-4422172,0,1545559,-2494951,281197612767569,265720390381921 +2511748700076,62833498077436,16212385366681,-643408,1930224,197756516,5634352,-16903056,18137924,12,-5022500,44033897,4,-162673,-1801744,0,1408588,160852,281197612767569,143751280741065 +25958801620752,44409942556912,-5247595329987,-7685056,7685056,-41974540,23790656,-23790656,-16564364,4,-3056990,6479293,4,1084101,-4014342,0,-5947664,-1921264,281197612767569,39481300256369 +29810091599209,40558652578455,-3777695222737,21025188,-21025188,-19778372,15530180,-15530180,38940828,4,5402680,3132111,4,-4332527,-1812482,0,-3882545,5256297,281197612767569,240529236790873 +22085650080722,4111793935498,4443653297283,-1046712,3140136,-138025460,-8092472,24277416,8534092,12,258602,-2065853,4,797375,10813504,0,-2023118,261678,281197612767569,165612717923457 +-31452151754135,-38916592423529,11284459646190,-18250332,18250332,10107832,2020612,-2020612,60572920,-4,-8293775,2129168,-4,6849455,-397790,0,505153,4562583,281197612767569,140908268845801 +-19719420541721,-22439695660865,-50649323635943,-28272740,10307324,28272740,3499676,38546940,-3499676,-4,-7215235,-399228,0,874919,7068185,-4,2421500,-2976059,281197612767569,226817789559697 +28868275763229,41500468414435,10570046390035,-27341708,27341708,34164812,-8093548,8093548,-31065556,4,-4884215,-4010490,4,2882174,4530713,0,2023387,-6835427,281197612767569,32765868220537 +17766351764282,17069688884818,-4968476780179,-670488,2011464,-213315148,5174632,-15523896,-32920076,12,-2270417,12900718,4,1986534,-13476023,0,-1293658,-167622,281197612767569,108675237514145 +-10543452369396,10891064496979,59825291808268,-21788624,18784588,-21788624,9540272,43448812,9540272,-4,-8865563,4835580,0,2385068,5447156,4,-1996640,-139433,281197612767569,243859741380361 +17296696508915,35775351159834,-15256542993915,6216652,-12433304,78304276,-12164020,24328040,27893652,8,4863903,-9278529,4,-1054755,5148770,0,3041005,1554163,281197612767569,23883126342833 +8393517179778,-33726845893009,-70368744177664,804360,42892732,0,-26235832,712860,0,0,178215,-10723183,0,6558958,201090,-4,-3122368,-1375431,281197612767569,168838671619737 +-24418846738913,-349370401658,-45949897438751,28867708,-18474472,-28867708,-7918916,-33934184,7918916,-4,5549477,-2980068,0,-1979729,-7216927,-4,-2934069,1638550,281197612767569,243207918911169 +-21134390556451,6875477535019,49234353621213,18616180,24811692,18616180,-19978412,33852364,-19978412,-4,6409310,-3885221,0,4994603,4654045,4,2053781,-2317702,281197612767569,142164620740393 +-31679161180769,-38689582996895,-6678652581191,-19916164,19916164,25634532,8140924,-8140924,46053604,-4,-6523369,3050986,-4,4990032,-3357647,0,2035231,4979041,281197612767569,40965903649233 +-7332406082549,-63036338095115,-26597958783507,10912812,-10912812,42558388,14439436,-14439436,-46860588,-4,9129978,10562159,-4,-2585169,-77438,0,3609859,-2728203,281197612767569,97059146084537 +21235342606814,-49133401570850,-1388201548605,20500344,20500344,-30333172,9997048,9997048,40128972,4,6955485,5395970,-4,3076758,2187323,0,-2499262,5125086,281197612767569,162099185300961 +8971894218360,1332263838255,70368744177664,18127328,-24646468,0,18823904,36517084,0,0,9129271,6161617,0,-4705976,4531832,4,-1074870,-871395,281197612767569,129691018617673 +2451450053407,-22639098041419,6887106097573,-2117508,-705836,351441556,9150972,3050324,76348180,4,-6215337,28249256,-12,-441034,3112621,0,762581,176459,281197612767569,268951124808433 +-19353416935356,51015327242308,-18779788578673,-18886384,-18886384,-26433988,-13694576,-13694576,40447004,-4,-6417039,-6051056,4,-3694712,-557441,0,-3423644,4721596,281197612767569,10642006388441 +-3750456494933,-4308746468850,70368744177664,21284524,-30011336,0,-9986836,-38816072,0,0,9704018,-7502834,0,-2496709,-5321131,4,364321,-725698,281197612767569,110173197578497 +-29219320120326,41149424057338,-14344018574073,24758248,24758248,10426396,14633384,14633384,-39313220,-4,5001563,2785942,4,4826742,-179343,0,3658346,-6189562,281197612767569,229876386505577 +20218705288976,-21076828961095,-29073209927593,-26330048,-27912476,1582428,17689664,-24008220,41697884,4,-5602115,3001538,-4,-4822356,-2605931,-4,-399940,3976581,281197612767569,3009673994257 +9604626941240,12048650344553,70368744177664,-23186208,-25256540,0,18552800,-28349628,0,0,-7087407,6314135,0,-4638200,-5796552,4,1761520,130679,281197612767569,71758708101369 +-27807809373165,-14753125431334,826100211676,10372172,-20744344,39096176,5209612,-10419224,-88913296,-8,4690848,1988290,-4,-8768738,-3892877,0,1302403,-2593043,281197612767569,168694515298337 +-2461759359708,-70368744177664,-22785132928201,3130512,0,72536284,14601232,0,-21332228,0,5333057,18134071,-4,-1368526,-380985,0,3650308,-782628,281197612767569,98575389017993 +-24923296754239,-45445447423425,-6291565107553,20853508,-20853508,2178684,7363204,-7363204,-53221636,-4,8428298,817879,-4,-4877111,273208,0,1840801,-5213377,281197612767569,70590354436401 +353941433600,-19932288069201,-50436456108463,-18697216,35236540,-35236540,28398592,6697884,-6697884,0,-1674471,8809135,-4,5080216,3394593,-4,-2019432,-1279711,281197612767569,225316825995033 +-15734784931645,54633959246019,5243478737494,1750796,1750796,63566168,-17352116,-17352116,13075416,-4,2861168,-12305503,4,407686,-3586039,0,4338029,437699,281197612767569,147426743710529 +-3671944019439,15120569464534,70368744177664,-26893244,30917464,0,17802660,21398936,0,0,-5349734,7729366,0,4450665,6723311,4,-1235499,-1041350,281197612767569,83311615528873 +26402268626430,8614211720691,-43966475551234,26034168,-2151476,26034168,-12036104,-42252340,-12036104,4,6968179,460684,0,-3009026,-6508542,-4,3594906,-998553,281197612767569,221046442083921 +-19250810757461,22779214800745,-51117933420203,32272044,-11478620,-32272044,915596,34562116,-915596,-4,6202638,4696315,0,-228899,8068011,-4,-2437891,1826660,281197612767569,137406226923833 +31427994962939,-38940749214725,-17917904014578,7791596,7791596,38851640,30487212,30487212,7518136,4,900631,4878952,-4,-2780165,4833958,0,7621803,-1947899,281197612767569,136175892904545 +-12295913670587,-26333587985410,58072830507077,-19714796,34928632,-19714796,-19003276,-23441352,-19003276,-4,-6614194,-5361909,0,4750819,-4928699,4,753856,-3370249,281197612767569,27732664695753 +24872825936367,-767814998130,45495918241297,30329788,-11950536,-30329788,-7482564,-34173640,7482564,4,5503210,-2014347,0,-1870641,-7582447,4,-3040200,973287,281197612767569,69228491366257 +-884109036333,-70368744177664,17036248430521,12855116,0,-46933276,-12735572,0,-41086972,0,10271743,-11733319,-4,-899873,-630638,0,-3183893,-3213779,281197612767569,228215652618073 +-4336811559453,-8028812000428,-70368744177664,-5236,-36094640,0,31191500,-10302384,0,0,-2575596,9023660,0,-7797875,-1309,-4,1048442,-555977,281197612767569,50367570625921 +10050649743200,60318094434464,-1304496766985,1572224,-1572224,-53984292,-20954752,20954752,3388540,4,-823255,-11575738,4,23880,1920335,0,-5238688,-393056,281197612767569,195709972712425 +-21351431957005,-24810347021840,49017312220659,28257228,22751168,28257228,18666188,-24815680,18666188,-4,2676200,6452697,0,4666547,-7064307,4,3527720,-764905,281197612767569,252486549699729 +22038426632259,26291890913146,20223516659067,3839244,-7678488,66382316,15771884,-31543768,-20557620,8,-346131,6752297,4,-2742768,-4921641,0,3942971,-959811,281197612767569,46820886528377 +10294721578472,60074022599192,-27291916656721,14120864,-14120864,-17767748,4331936,-4331936,74282364,4,15433747,5161260,4,-3136844,719323,0,-1082984,3530216,281197612767569,271034455463073 +14649727138843,55719017038821,30295120887479,-7592852,7592852,61226716,-14968820,14968820,-27579652,4,-7070587,-11302838,4,-175674,4003841,0,3742205,-1898213,281197612767569,184802315288585 +-23645792568695,23077159040274,5550660575368,-678364,-1356728,-135241184,8211364,16422728,-22680032,-8,-2183312,11061202,4,-1743348,11374547,0,-2052841,-169591,281197612767569,21819797904817 +-30791066736541,39577677441123,5600778897194,-25709172,-25709172,-2149208,-5349652,-5349652,-44240920,-4,-6114187,-209364,4,-4946043,746666,0,1337413,-6427293,281197612767569,184726398605209 +14119214650815,-11463457114839,70368744177664,3963644,-34402140,0,34151740,-12360604,0,0,-3090151,8600535,0,-8537935,990911,4,-770850,-1564239,281197612767569,273402939582401 +-14322167827722,-56046576349942,-14625814691473,-9686056,9686056,49965500,15322648,-15322648,37197404,-4,-8202837,9445702,-4,1096514,-3045673,0,3830662,2421514,281197612767569,117762447235113 +7768148418800,20336974907025,-50031769270639,-25771072,-23480764,-23480764,22045632,-23602108,-23602108,0,-5900527,5870191,4,-3267208,-5228793,-4,-2244200,-1213975,281197612767569,32239794995921 +-13781480823065,56587263354599,-7132578103138,11476892,11476892,46975608,20302076,20302076,-15003848,-4,2501894,9734723,4,1249068,2009179,0,5075519,-2869223,281197612767569,265809410036153 +-8825913407688,-61542830769976,3268798149919,-15188768,15188768,30439548,8223456,-8223456,57646652,-4,-12508598,6831815,-4,1903065,-778072,0,2055864,3797192,281197612767569,196588550160097 +24577125053491,-45791619124173,8434283742700,-17062708,-17062708,35186608,-9289620,-9289620,-46829008,4,-7896714,-5213039,-4,-3810538,-3583613,0,2322405,-4265677,281197612767569,247887623574601 +-32940023148921,-37428721028743,-4391025243931,-20169188,20169188,14741396,-2551908,2551908,-53957612,-4,-7214744,-1645575,-4,6274659,2039774,0,637977,-5042297,281197612767569,151728647597041 +-2524033586223,2210147715114,-70368744177664,-25998524,-12371800,0,-9906844,38591976,0,0,-9647994,-3092950,0,-2476711,6499631,-4,268272,315081,281197612767569,73764411256793 +26736378154413,43632366023251,2374008284538,-5840204,5840204,-56922648,17830516,-17830516,-18995864,4,-2794226,8873025,4,1954740,-5357637,0,-4457629,-1460051,281197612767569,104541364525569 +-10628162966309,59740581211355,6194717031924,13428588,13428588,-45111344,-14281844,-14281844,-35865776,-4,7297879,-9870022,4,1668565,-1407814,0,-3570461,-3357147,281197612767569,225644303627369 +15573499986410,54795244191254,7711741848705,5906344,-5906344,-44855804,-23636568,23636568,-11117308,4,2811812,-8570341,4,32485,2643610,0,-5909142,-1476586,281197612767569,70894887213329 +14803583631447,-40761576914770,26603052350701,-12663460,-25326920,-35086412,-8746052,-17492104,64676820,8,-7712891,-7474735,-4,-4228157,-648434,0,-2186513,3165865,281197612767569,104031725974009 +16775839607338,-8302982187333,53592904570326,770216,34967276,-770216,32012584,-8448340,-32012584,4,2552877,6635058,0,8003146,-192554,4,440792,-2106761,281197612767569,98547074890017 +15361812719709,24939904723428,-30067026734527,-31748748,5609360,-26139388,-6202156,36558608,30356452,4,-6594887,-1716874,4,994226,4817973,-4,-2544765,3119214,281197612767569,198686618482825 +858470359951,-33194756385937,-37173987791727,34304572,-4148804,4148804,16662204,30805564,-30805564,0,7701391,1037201,-4,-2106599,4543208,-4,2058952,-4032935,281197612767569,64363025877553 +12814446501949,-11683153050607,70368744177664,19983604,-32854972,0,-22933100,-18636956,0,0,4659239,-8213743,0,-5733275,-4995901,4,-1800349,666300,281197612767569,36112574142489 +26274158561825,17820427054014,-14456661274454,-11697020,23394040,44456616,-9331644,18663288,-60788696,8,-2890032,-4016114,4,6153571,3549020,0,2332911,-2924255,281197612767569,220564219501633 +28397068724336,-41971675453328,-753292162941,-20520512,-20520512,-14961140,-10708032,-10708032,47060012,4,-7045933,-2175988,-4,-4719070,-1564297,0,-2677008,5130128,281197612767569,121862392258729 +-27686315818688,-24048467775933,-42682428358976,-64256,-35566324,64256,-31652608,2069772,31652608,-4,2390457,-5398712,0,-7913152,16064,-4,2907900,3492869,281197612767569,118049388494673 +-18246416867419,-15629493575407,1262530515980,-5944684,17834052,-8019920,-158028,474084,189182896,-12,-10506907,-365330,-4,12262939,546550,0,-39507,1486171,281197612767569,88400969785913 +21366269034360,-15135248719839,49002475143304,-5497376,36297860,5497376,-30712864,-2017084,30712864,4,1300310,-6614759,0,7678216,-1374344,4,1804581,2459706,281197612767569,248861887628129 +23938639635956,-46430104541708,4925372127349,8406992,8406992,37350868,23488848,23488848,-29567180,4,4466173,6308242,-4,2925622,3029475,0,5872212,-2101748,281197612767569,278358064901321 +2841630278875,-6826197793148,-70368744177664,-10205332,40405520,0,-24456980,-13493232,0,0,-3373308,-10101380,0,6114245,-2551333,-4,-729340,-160419,281197612767569,193952517339249 +145548001667,-10229024135128,70368744177664,-11953652,33292448,0,-23814036,-27863648,0,0,-6965912,-8323112,0,5953509,-2988413,4,879829,-417190,281197612767569,112051418665049 +13592612264731,8647461907272,56776131912933,-27484052,2526496,27484052,-10584916,-39992544,10584916,4,-8392059,334746,0,2646229,-6871013,4,1606077,966370,281197612767569,121840414994049 +-17655295095630,52713449082034,8063883549879,14822088,14822088,-26626340,19418504,19418504,41077628,-4,7136531,5411102,4,3132876,1245483,0,-4854626,3705522,281197612767569,6501841738985 +-5233442615611,59901858946442,-5320822168034,7964436,15928872,55402616,-4068332,-8136664,113065592,-8,23908148,-12091570,4,2179125,-879542,0,1017083,1991109,281197612767569,271022235350417 +-27975822185219,-10677836261974,42392921992445,-29417484,34172584,-29417484,-11335660,-25105176,-11335660,-4,-4211110,-4030769,0,2833915,-7354371,4,-2065184,-4512377,281197612767569,68797821608569 +26764953162509,-43603791015155,9258665336115,26572852,26572852,-3061556,8635508,8635508,-43365236,4,6433735,399800,-4,4407574,-1165189,0,2158877,-6643213,281197612767569,143720353930657 +-19619458083818,-11510369926210,6060135260879,-444328,1332984,133459772,-8430696,25292088,-1668004,-12,476327,-5486276,-4,297776,9292889,0,2107674,-111082,281197612767569,10520556794121 +4321387055514,70368744177664,35467084996245,24018536,0,-3766700,5832040,0,45961684,0,11490421,941675,4,29229,-3084270,0,-1458010,6004634,281197612767569,50816175650481 +-13827675023254,8011561126611,56541069154410,-28214872,-21594292,-28214872,8602856,-33320276,8602856,-4,-6938046,3534663,0,-2150714,-7053718,4,-1392023,1863910,281197612767569,5995989981337 +6336888282121,-26013861095333,70368744177664,15346724,-35285652,0,-21394460,-24173396,0,0,6043349,-8821413,0,-5348615,-3836681,4,-2521491,-623950,281197612767569,267622002479297 +12480574107644,7911228547895,-70368744177664,30101488,3526876,0,-6485392,-38163332,0,0,9540833,881719,0,-1621348,-7525372,-4,1509878,-689661,281197612767569,97458087307561 +30115171679647,40253572498017,4207586125401,-27682180,27682180,-27978396,6779004,-6779004,-33820828,4,-4735362,4414977,4,3719845,-2579622,0,-1694751,-6920545,281197612767569,64931631004625 +24330051995173,46038692182491,13816812538572,-17767276,17767276,27753264,9579188,-9579188,48406192,4,-8387643,3667242,4,3713905,-3271074,0,2394797,4441819,281197612767569,27002900411065 +-18540276960121,-51828467217543,19641150607516,8050204,-8050204,47075952,-23141924,23141924,4530544,-4,2449046,-8106437,-4,1316410,3662551,0,5785481,2012551,281197612767569,180378962446305 +-4952796115861,-33222365234554,37146378943110,26420652,7737880,7737880,-9259444,39902552,39902552,0,9975638,-1934470,-4,519853,3622900,4,1795008,2982263,281197612767569,236432434087241 +-16025313336302,-27674479964379,-42694264213285,6817864,34539668,-34539668,-30687928,9672980,-9672980,0,2418245,-8634917,-4,4104045,3000596,-4,-3567937,1296130,281197612767569,204839624131825 +-26510121186561,-43858622991103,-15340064317364,-25538564,25538564,-339664,5364700,-5364700,44157616,-4,-7172883,-1444748,-4,3866521,-1359832,0,1341175,6384641,281197612767569,78806164811993 +-29867074780666,-40501669396998,-7035296817901,-8572904,8572904,-51918772,18575512,-18575512,-18836340,-4,-2246093,7684910,-4,2462992,-5294783,0,-4643878,-2143226,281197612767569,155310103593729 +-10964474392594,15343512769711,-70368744177664,24168376,-16927044,0,21445880,31565404,0,0,7891351,4231761,0,-5361470,6042094,-4,-2398626,658075,281197612767569,215114607052137 +13543948389433,-1233617832737,70368744177664,-23384860,33191804,0,-20953116,-18406276,0,0,-4601569,-8297951,0,5238279,-5846215,4,977500,1494627,281197612767569,87320354591249 +-4392580632531,-9305791848183,70368744177664,19754164,27541540,0,-19223340,30194116,0,0,7548529,-6885385,0,4805835,4938541,4,1106736,223287,281197612767569,145176796304121 +-11737702607695,58631041569969,3656025820840,-13406524,-13406524,-34366816,18434564,18434564,-36725600,-4,-7889360,6984449,4,-1292040,1607255,0,-4608641,-3351631,281197612767569,71814660293153 +31638286866230,38730457311434,23053018471911,-18823976,18823976,-34669668,17338392,-17338392,-27878468,4,-2416000,6312183,4,4553617,-2355234,0,-4334598,-4705994,281197612767569,3976245225865 +-23833236923027,4424408417647,46535507254637,6955444,-41256516,6955444,-28411084,6648380,-28411084,-4,-1545743,-6930160,0,-7102771,-1738861,4,-116352,-3383969,281197612767569,22706969338673 +644000978512,-70368744177664,-15430321118383,12130624,0,40446276,-9080000,0,62539876,0,15634969,-10111569,-4,-354673,-757534,0,2270000,3032656,281197612767569,264837491300633 +-21410370890401,27548002396862,-14727625149698,-14878340,-29756680,-29092872,6233532,12467064,-63484808,-8,-5560954,4404284,4,-5155124,1434467,0,-1558383,-3719585,281197612767569,194204186232129 +-4765441487776,-12252945209363,-70368744177664,-10964608,35802036,0,-28805760,-8627308,0,0,-2156827,-8950509,0,7201440,-2741152,-4,-1107887,1083440,281197612767569,239551854244265 +12181651090877,-58187093086787,-18210551801438,-6544652,-6544652,62693000,14937844,14937844,28939912,4,-5016087,13383446,-4,-2218891,2289804,0,3734461,1636163,281197612767569,245936394877009 +-9512850802361,-19019102719361,-70368744177664,28174620,-26808836,0,9533564,30890076,0,0,7722519,6702209,0,-2383391,7043655,-4,-399797,-2809786,281197612767569,67917043352377 +-7809137695104,62559606482560,-7048122665273,-7169536,-7169536,58908444,-16238080,-16238080,-23619364,-4,-5656155,-12913252,4,-248686,-1813859,0,4059520,-1792384,281197612767569,20119582002273 +220250916686,70368744177664,3015184288027,-2611912,0,-125085588,-8076424,0,44280076,0,-11070019,-31271397,4,121164,69899,0,-2019106,652978,281197612767569,136794823761353 +25512415908127,19343912361410,4775714743337,10348668,-20697336,60738724,-11649028,23298056,40425764,8,2382903,-4525337,4,-3861769,5329672,0,2912257,2587167,281197612767569,64931712635249 +1960407503823,-70368744177664,22992755475379,-3394756,0,69788364,15193884,0,19307308,0,-4826827,17447091,-4,1106667,763366,0,3798471,848689,281197612767569,84724085428569 +18103006273325,25854720767819,26411017136520,-26269516,-11382484,37652000,23156340,-32826004,9669664,4,-3968291,4526530,4,-1550875,-4886470,4,4238210,1680909,281197612767569,24598967523201 +-5534819084654,-18893119247107,70368744177664,-7744952,39854068,0,24768776,17916628,0,0,-4479157,9963517,0,6192194,1936238,4,1310220,1303531,281197612767569,178048037105129 +16400852159742,37567039858180,-14070276189165,-1016840,2033680,73573452,-15076872,30153744,-16366772,8,-677075,-9921135,4,1707309,4236114,0,3769218,-254210,281197612767569,77275884613265 +-33974881505732,-36393862671932,4364032261887,-7190288,7190288,66461692,-16034192,16034192,-8378020,-4,-834656,-8704775,-4,1259849,7910648,0,4008548,-1797572,281197612767569,106671102329721 +26681959781923,-43686784395741,9840241075607,-15045492,-15045492,36526684,13830220,13830220,41256732,4,-6886817,5143200,-4,-3427366,3988471,0,3457555,3761373,281197612767569,254990707435169 +4038651816690,33165046180487,12305980435599,-18832440,9416220,48076348,9383816,-4691908,95614812,4,-11471031,5252966,8,961641,-1513155,0,1172977,2354055,281197612767569,258653120078345 +10342616772155,-27405182433823,60026127405509,-168724,-42896508,168724,-26221204,6530308,26221204,4,-3945594,-9131495,0,-6555301,42181,4,-2313017,1592632,281197612767569,34332335263665 +9729541910009,16092059855827,70368744177664,-12799004,-31915188,0,23970308,-28196180,0,0,-7049045,7978797,0,-5992577,-3199751,4,2345031,-371464,281197612767569,110135351384473 +14634983392809,-26463793999237,-15987989417513,-5679964,-17039892,-105870500,5861476,17584428,-88969316,12,-9363551,8985884,-4,-4292926,5827247,0,-1465369,-1419991,281197612767569,6842059160001 +25130237141578,16783180136259,-45238507036086,-10608344,-34107124,-10608344,-28897560,13224236,-28897560,4,-402351,-6114210,0,-7224390,2652086,-4,-2903708,-2412571,281197612767569,269482257578537 +-20294377968548,-931553395641,-50074366209116,-22232720,16643356,22232720,21088624,34854684,-21088624,-4,-6270438,2887271,0,5272156,5558180,-4,2443233,-1273568,281197612767569,9570847274193 +4111023451346,2557441995457,70368744177664,-4510904,-36067580,0,-29922168,10348196,0,0,-2587049,-9016895,0,-7480542,1127726,4,423007,485792,281197612767569,98410005091257 +-26461705260163,43907038917501,-25707033556042,7354868,7354868,-47278376,22780724,22780724,6643800,-4,3116918,6703195,4,-1455968,5116399,0,-5695181,1838717,281197612767569,173165518295265 +-20097091365123,50271652812541,3379479690750,2476020,2476020,-51560456,21286484,21286484,11453496,-4,1790031,9238466,4,1073343,3651648,0,-5321621,619005,281197612767569,254947926488649 +-19169514364692,31750218165577,38618526012087,-33926224,12415268,-12415268,12124592,28749732,-28749732,0,-7187433,3103817,4,-294465,5500224,4,-3325613,-2981332,281197612767569,56096835050993 +5723033923138,-64645710254526,-22229138183907,7762184,7762184,78024820,-8165048,-8165048,62974996,4,15108147,-17306772,-4,635602,-2199433,0,2041262,1940546,281197612767569,170198712496601 +2685431690686,-33841656243489,-7073039125399,15081208,7540604,25562532,2920824,1460412,-144360860,4,17393163,2883892,-8,1303889,622849,0,365103,-1885151,281197612767569,220066495294465 +-6073773050754,21841671576771,48527072600893,28121592,11077388,-11077388,-22454984,31191596,-31191596,0,7797899,-2769347,4,4544366,4609209,4,-1069380,-2421189,281197612767569,144875637134953 +-3044130818870,23697859832915,-70368744177664,-8557784,42796364,0,-24604376,-8521140,0,0,-2130285,-10699091,0,6151094,-2139446,-4,2163640,-257655,281197612767569,242104454253329 +9168893617674,20154189508345,-50214554669319,-21024728,-20727836,-20727836,26584680,-27341948,-27341948,0,-6835487,5181959,4,-3852003,-4425966,-4,-2794167,-830216,281197612767569,74716613555193 +7020924995217,63347819182447,-15638389492928,-1657276,1657276,57724160,-19247740,19247740,-8954624,4,-945918,-13083283,4,1292738,1347757,0,4811935,-414319,281197612767569,3504583117601 +-33024622389143,37344121788521,14093750419919,14327204,14327204,-38474948,17811332,17811332,30753372,-4,3188309,5821964,4,4500034,3796773,0,-4452833,3581801,281197612767569,264789031279241 +-14125186453778,8317715118145,56243557723886,-23444552,-21644028,-23444552,14329016,-34795388,14329016,-4,-7376148,3632053,0,-3582254,-5861138,4,-1322699,1778954,281197612767569,121731564207153 +28547031337829,13376249819545,41821712839835,-5441132,-37404060,5441132,-30780620,-4671868,30780620,4,2156905,-5816090,0,-7695155,1360283,4,988938,3534925,281197612767569,3854677629465 +16686170232903,-53682573944761,-27915171443107,-5216996,-5216996,-55499404,-18732196,-18732196,16537140,4,-5011702,-10067387,-4,877417,-3807464,0,-4683049,1304249,281197612767569,36036561235521 +-12287628612631,12382368121279,70368744177664,20179876,26290940,0,22073860,-27034724,0,0,6758681,6572735,0,5518465,-5044969,4,209134,2035449,281197612767569,3955731579561 +-20535267325743,49833476851921,7505837519185,10338116,10338116,46883140,15933252,15933252,-36650684,-4,6913664,8024705,4,2249007,3696080,0,3983313,-2584529,281197612767569,95185978224977 +16319694161719,-29602039447497,40766704730167,26370268,-15448868,-15448868,21033532,30373436,30373436,0,7593359,3862217,-4,-1285310,4714983,4,-3973073,1877584,281197612767569,142043005232185 +12027588107724,-58341156069940,-16611002063213,-22886608,-22886608,-16257460,166448,166448,-49076468,4,-10181874,2019041,-4,-2087243,2045324,0,-41612,-5721652,281197612767569,41122652722529 +5904368079761,70368744177664,31575335486884,19458628,0,-30931312,11835428,0,39047696,0,9761924,7732828,4,508591,-2831664,0,-2958857,4864657,281197612767569,52474778357449 +-24535654299683,21297435578298,-10427595145875,-3667084,-7334168,100311476,9725428,19450856,40993844,-8,-3822327,7318233,4,-3213067,8879818,0,2431357,916771,281197612767569,129014088854129 +-6970924839627,56426894498410,15908696043248,-11091756,-22183512,4914112,-1791628,-3583256,-100714048,-8,-19987482,-2238916,4,-2595515,505194,0,447907,-2772939,281197612767569,181111220048473 +-10456455555545,18086466399939,8675328718805,1498268,7491340,251849556,3971548,19857740,-83875052,-20,6001513,15951964,4,2993450,9402085,0,992887,-374567,281197612767569,207645434347649 +-17475184060071,23014092699163,-52893560117593,31908196,-7664532,-31908196,1956548,34815628,-1956548,-4,6382430,4049179,0,-489137,7977049,-4,-2321477,2133046,281197612767569,12230095781609 +6569433097639,17724667309777,70368744177664,26679964,8804164,0,-11888228,38277188,0,0,9569297,-2201041,0,2972057,6669991,4,-1641973,-1474572,281197612767569,122167674955665 +27123772660069,16121198857526,17354619212399,6631828,-13263656,-80564804,-9448780,18897560,-54986468,8,4314443,-3796485,4,-4716087,8172358,0,-2362195,-1657957,281197612767569,70116241056889 +-15973084244355,24026424959329,-30369234973980,-22886924,13951364,36838288,28526132,31805124,3278992,-4,-3711448,4649737,4,2891700,4559835,-4,4239833,1161896,281197612767569,93794219306913 +17110053281864,-16360927781849,53258690895800,-21667552,-27396964,21667552,-22503392,23508668,22503392,4,-5756168,-3924417,0,-5625848,5416888,4,120999,2924824,281197612767569,14559892689673 +-26236358973746,44132385203918,-4113311470821,9675576,9675576,-51453844,-16773064,-16773064,-27167508,-4,4504698,-7926041,4,2287179,-4937420,0,-4193266,-2418894,281197612767569,135320023820465 +-33165619186775,37203124990889,-328123304724,17042084,17042084,31040432,-10747196,-10747196,46490928,-4,6132273,-4122544,4,5490459,-3637564,0,2686799,4260521,281197612767569,271739515624089 +-4359210076574,14089599579223,70368744177664,11014536,31364444,0,-27431672,24106396,0,0,6026599,-7841111,0,6857918,2753634,4,-999792,-1037089,281197612767569,122928917095105 +17983261980238,-52385482197426,8830008369737,18342200,18342200,24069412,14277752,14277752,-42647164,4,7489190,5054977,-4,3172601,962376,0,3569438,-4585550,281197612767569,34029370166057 +6055126412924,-64313617764740,4635695321009,6638064,6638064,-64202044,13861360,13861360,35548356,4,8350655,14560064,-4,536434,1490447,0,-3465340,1659516,281197612767569,267686571109841 +28816050276356,41552693901308,13720801240361,-2715632,2715632,55234724,19512976,-19512976,17714500,4,-3566281,8021640,4,862344,-5787041,0,4878244,678908,281197612767569,211371678119097 +-27662690575429,42706053602235,6640612254360,-21552404,-21552404,3222112,6572972,6572972,51257440,-4,-7621830,997335,4,-5192530,-191807,0,1643243,5388101,281197612767569,95009632082401 +10145319353508,50078105470648,-12989228639173,-9641328,19282656,-48814868,4331024,-8662048,-94850164,8,-17274821,7794971,4,3218860,-2204373,0,-1082756,-2410332,281197612767569,167738920806217 +27093956505539,-16180831166586,25569018153549,5001996,10003992,66082100,14974604,29949208,-27258444,8,-1153593,4707543,-4,3984102,5906491,0,3743651,-1250499,281197612767569,160218819524337 +21691128746842,-18751344755175,29926270675647,32613736,34632804,2019068,-13735768,19936132,33671900,4,4362759,-3816648,-4,4055216,3311881,4,-621274,4841553,281197612767569,247152341988057 +-22010936350481,-30920637055888,-48357807827183,-4847684,-36294208,4847684,-31061764,-301632,31061764,-4,3464023,-6767926,0,-7765441,1211921,-4,3388615,2305626,281197612767569,45433121527041 +5351144634983,70368744177664,-24639383057173,13725084,0,-34920532,17476156,0,37567948,0,9391987,8730133,4,-2244012,537571,0,-4369039,3431271,281197612767569,128130400544617 +26374257611937,43994486565727,-4122448127094,-20140412,20140412,15271464,-15283836,15283836,-44313560,4,-6702356,-2681901,4,4376034,1135965,0,3820959,-5035103,281197612767569,22688087573521 +-587590803343,26416504257508,-70368744177664,1875396,-40837232,0,27517028,1162768,0,0,290692,10209308,0,-6879257,468849,-4,-2584908,90757,281197612767569,26268432389369 +16216502359777,54152241817887,-21504952576999,19445636,-19445636,28626020,-8407356,8407356,45523364,4,9400452,-4021621,4,-1980389,3134884,0,2101839,4861409,281197612767569,23308095263777 +11642154761618,29363294708023,-728855377782,12611144,-6305572,69515816,-7228920,3614460,138708712,4,14479366,-7235519,8,-5718446,2907916,0,903615,1576393,281197612767569,218168076700553 +27271881865629,43096862312035,-14368064008578,-21900684,21900684,-753160,4799476,-4799476,-51244296,4,-8091048,-1002617,4,4720026,-1190907,0,-1199869,-5475171,281197612767569,280608361321777 +23478736903435,46890007274229,6881677458975,17885228,-17885228,35232892,17561740,-17561740,-28355748,4,4294332,6306603,4,-2794605,-2501620,0,4390435,-4471307,281197612767569,123682348538649 +30357582177239,-40011162000425,-19149337573780,-17018020,-17018020,-38147664,-21843556,-21843556,17194672,4,-3930255,-4264850,-4,-368413,-5272066,0,-5460889,4254505,281197612767569,147375455016769 +694216637336,-70368744177664,-15760340691325,8097376,0,-67899892,-8982688,0,-63721428,0,15930357,-16974973,-4,660118,285923,0,-2245672,-2024344,281197612767569,262245065888681 +5668383824581,21715953678184,-70368744177664,12695316,38747552,0,26069780,-9118304,0,0,2279576,9686888,0,6517445,-3173829,-4,2194924,-199147,281197612767569,52863963474513 +25181647080874,-16501712681321,28685384415469,20598440,-10887588,-31486028,-30819608,-38369348,-7549740,4,4352867,-2955460,-4,-2465432,-4916047,4,-5239470,-233563,281197612767569,59490804696377 +22886167494663,-24596409188338,1803829782136,6489116,12978232,87538144,8029660,16059320,-65185824,8,5593282,7732604,-4,5351587,7075966,0,2007415,-1622279,281197612767569,82263641316961 +9577431073721,-30211026557742,-40157717619922,31525604,-9041080,9041080,5707716,34076936,-34076936,0,8519234,2260270,-4,345184,4805353,-4,1772113,-3076048,281197612767569,153673586212809 +10700746499125,-59667997678539,20596560972483,14687444,14687444,-5193972,-542892,-542892,76849292,4,16251042,26301,-4,2961281,1272192,0,135723,3671861,281197612767569,72808381432689 +17699824353065,31672514027512,38696230150152,28063908,14917600,-14917600,-15594556,31829728,-31829728,0,7957432,-3729400,4,142357,4796186,4,-3756282,-2219791,281197612767569,173826801668953 +23917239723980,-46451504453684,-30755305817103,18018096,18018096,33491908,-16058320,-16058320,32638084,4,7140836,-3558389,-4,1018685,-4814588,0,4014580,4504524,281197612767569,245462255626625 +-25043432397980,-45325311779684,1131142438837,-7832176,7832176,43715284,19739408,-19739408,33577652,-4,-5327612,7070853,-4,3066801,-3857968,0,4934852,1958044,281197612767569,235935279042537 +-9757788255643,-60610955922021,-7302223412280,-14158444,14158444,-35328224,9967252,-9967252,-54651104,-4,-11509629,7974654,-4,2153147,-857402,0,-2491813,-3539611,281197612767569,273537318707345 +-5879557568715,-58609629040234,-21157706965155,6990036,-13980072,73492852,5251060,-10502120,-105862764,-8,21253671,16353763,-4,-2606010,-1009725,0,1312765,-1747509,281197612767569,264190554523001 +-25282001290034,14880150769621,30206592118009,34995000,25054036,9940964,1920184,-30798444,32718628,-4,5034814,2163155,4,3144843,-4648396,4,2664797,4100354,281197612767569,125175335401633 +5355248609717,-25888498897263,-44480245280401,9908948,-30321084,30321084,-30251724,-21055196,21055196,0,5263799,-7580271,-4,-4379957,-2142746,-4,3182974,334491,281197612767569,237344669565961 +4585231713285,11299232232816,70368744177664,-23176172,-32434752,0,-16602220,25345472,0,0,-6336368,-8108688,0,-4150555,5794043,4,1079340,-401997,281197612767569,115207380795825 +-23984736899750,4693641056871,-46384007277914,-28504728,-27275876,28504728,-14352728,25764732,14352728,-4,-4485081,-4019446,0,-3588182,7126182,-4,1956102,2799523,281197612767569,91375735643033 +3859287832302,62650168513060,29024413465763,4744120,-9488240,-123009396,5557304,-11114608,93231052,8,21897279,26400815,4,-705242,-2175767,0,-1389326,1186030,281197612767569,208576751520705 +2158604788683,-12138111425902,-70368744177664,-12385492,38142536,0,-24613300,-15105272,0,0,-3776318,-9535634,0,6153325,-3096373,-4,-1177246,241591,281197612767569,238564671953961 +-29622103079181,-26078976920307,-40746641098483,-14487604,34865204,14487604,26972620,12803636,-26972620,-4,-4352513,3704834,0,6743155,3621901,-4,-1151604,-5011467,281197612767569,40076807775953 +5750323121978,-27070803727099,37547617328587,-22276888,14483476,36760364,-21004504,-36884940,-15880436,4,-6447599,-5467458,-4,2477490,-3722633,4,2773636,-1846589,281197612767569,237798858167737 +9012800978565,-61355943199099,-29469624325220,11159060,11159060,47496816,-16604844,-16604844,30219632,4,8325758,-9185039,-4,-770850,-2689165,0,4151211,2789765,281197612767569,123262734050017 +17807032206031,-859384646460,3285999954634,-1118404,4473616,313410344,-3207332,12829328,-107911704,16,179698,1009114,4,6789406,19840425,0,801833,-279601,281197612767569,125434231855177 +-34739733134093,-35629011043571,-17719733562,22341580,-22341580,-21794024,-10193076,10193076,-40451560,-4,5120987,-2757274,-4,-4991903,2691232,0,-2548269,-5585395,281197612767569,102283433594865 +31582063353703,-38786680823961,1358302877976,16515484,16515484,-11205536,446076,446076,-68475040,4,9433569,-1464402,-4,7685191,-1336982,0,111519,-4128871,281197612767569,281415043625945 +24964643533597,-45404100644067,-26411022544131,-23086988,-23086988,-30033932,15526964,15526964,-28568652,4,-6065253,2678436,-4,-1076910,4830047,0,-3881741,-5771747,281197612767569,162126088715777 +-34745703134519,35623041043145,-14282327768465,321316,321316,-75469380,-14901116,-14901116,-4114084,-4,1276770,-9534985,4,-248249,-9332360,0,-3725279,-80329,281197612767569,217097663314025 +15349931801975,8969016969764,-8972805300398,-2868772,11475088,172291400,4580060,-18320240,117400392,16,-3156878,5855754,4,6548305,-9304274,0,1145015,717193,281197612767569,211947306843409 +-16230242093055,-54138502084609,-37138729579634,-26559484,26559484,-9226696,3259556,-3259556,-41259272,-4,-7505674,5278995,-4,2809144,2972321,0,-814889,-6639871,281197612767569,177537346762233 +34266395897775,36102348279889,31349279601970,18490044,-18490044,29478088,-15821956,15821956,35667784,4,2812626,-5840227,4,-6104320,1529295,0,3955489,4622511,281197612767569,98467900595489 +19064892951137,32238958275390,-1381933528846,10978692,-21957384,40311752,6652004,-13304008,-78128248,8,9013798,4509336,4,-5259132,-2784301,0,1663001,-2744673,281197612767569,210190051818633 +22419080653337,25530582870990,10513837297804,-13360028,26720056,49189424,9270244,-18540488,50142256,8,-5240582,3463556,4,3647491,-4416900,0,2317561,3340007,281197612767569,224243245755953 +-21128935881129,-28110872415406,5922878125382,-14164644,28329288,20970776,-8384708,16769416,-67073064,-8,-6345712,-2690462,-4,5211277,1276116,0,2096177,-3541161,281197612767569,1946742053913 +15094194552203,55274549625461,32025354511961,22178348,-22178348,-14346908,-5957780,5957780,-46911708,4,9890128,-293985,4,-1837799,3292742,0,-1489445,-5544587,281197612767569,176786124881985 +-13692335786419,-10934726333867,70368744177664,-24640204,-34425516,0,-24103660,12017716,0,0,-3004429,-8606379,0,-6025915,6160051,4,-1520979,-717406,281197612767569,169206280447145 +22263336504597,-48105407673067,30886826480778,-3653548,-3653548,40299048,27002964,27002964,10320424,4,-4726900,6486387,-4,2146794,3588375,0,6750741,913387,281197612767569,93105134822225 +-4885940042182,-31281223840208,8891787099055,3141864,-25134912,-29535556,-299224,2393792,-355541220,-32,39436825,-4076393,-4,-6181060,413437,0,-74806,-785466,281197612767569,237857712793145 +14287807679305,-27505321139749,-1653526289025,7137572,21412716,71940604,-3915932,-11747796,118273468,12,11626522,-6904141,-4,5980615,-3693670,0,978983,1784393,281197612767569,193765093549921 +-19797717513981,-36563903337405,50571026663683,28620812,13387020,28620812,6229932,-36424532,6229932,-4,5734916,6123045,0,1557483,-7155203,4,3371217,-2776290,281197612767569,125464934609097 +-11547600113075,-58821144064589,-20781541059317,-18025164,18025164,-23345108,-9146444,9146444,50616748,-4,-9902329,-6209350,-4,2751858,-373073,0,-2286611,4506291,281197612767569,81624863448177 +15775808456152,-54592935721512,-8229369406243,-17057952,-17057952,18505588,12591712,12591712,52344084,4,-9784157,4087932,-4,-3301864,538465,0,3147928,4264488,281197612767569,31717570221145 +-16156092356417,-54212651821247,-11076874551686,-18692356,18692356,28824040,-7557572,7557572,-48579224,-4,-9653870,-4815969,-4,2490936,2390041,0,1889393,-4673089,281197612767569,255282593747585 +-6504274412380,57360195352904,20560387071947,-1056112,-2112224,-107220180,10461200,20922400,-4022452,-8,-2347993,21695507,4,671190,2554769,0,-2615300,-264028,281197612767569,99445386764521 +2618378139143,-17191480458628,70368744177664,4250652,-40199696,0,26522396,14046704,0,0,3511676,10049924,0,-6630599,1062663,4,-1750560,-114337,281197612767569,265844318820753 +28308146401072,-13752451375520,-9064480497205,14154944,28309888,25099052,-2499904,-4999808,75108364,8,3830695,-314625,-4,7473198,-2980069,0,624976,3538736,281197612767569,194164024436345 +-4228957196785,2003448066527,70368744177664,-3040196,-49452164,0,22409980,-5814724,0,0,-1453681,12363041,0,-5602495,-760049,4,72145,764622,281197612767569,146504360575393 +-14870094819831,32097815872864,55498649357833,18543652,29726080,18543652,-21470204,26298752,-21470204,-4,7633687,-3746502,0,5367551,4635913,4,-1058999,-3685018,281197612767569,49003409290505 +-33249090439791,-37119653737873,5551675002743,24015428,-24015428,-2784804,-5744700,5744700,47548508,-4,6383789,840916,-4,-5503338,144715,0,1436175,6003857,281197612767569,100258542623409 +-19284605109738,18759209621885,51084139067926,13422680,-27405836,13422680,-27249384,-28243820,-27249384,-4,3309830,-5868381,0,-6812346,-3355670,4,3751125,-983078,281197612767569,87398530899097 +-21501285016344,12751144829697,-48867459161320,14996384,32892932,-14996384,23488928,-23557692,-23488928,-4,5153976,5031257,0,5872232,-3749096,-4,-735447,-3191976,281197612767569,23472361108673 +4250682166149,-9757156166237,-70368744177664,3963412,32303756,0,-32706316,17500844,0,0,4375211,-8075939,0,8176579,990853,-4,-869456,-625223,281197612767569,65106826358057 +20625163018634,49743581159030,15507698396523,-10871256,10871256,-50943572,-15539672,15539672,30746540,4,-4577524,-9601933,4,3109111,3133960,0,-3884918,2717814,281197612767569,98677254119377 +2419541554729,2701051869952,-70368744177664,-23063388,27716608,0,19855684,24955904,0,0,-6238976,6929152,0,4963921,5765847,-4,-23983,459568,281197612767569,191271980168889 +-3885100553567,10327977172664,70368744177664,-24705404,11180768,0,18433220,37230816,0,0,-9307704,2795192,0,4608305,6176351,4,-1190242,-752175,281197612767569,245065037802465 +15274569759495,-55094174418169,12051933364099,-20582372,-20582372,34378252,13038908,13038908,32923564,4,-7002543,5847710,-4,-1228348,2746853,0,3259727,5145593,281197612767569,20728413489481 +23280466115161,5169675688688,47088278062503,-25729692,35761088,25729692,-22325276,-12729408,22325276,4,-2539552,-5509953,0,5581319,-6432423,4,642800,3430319,281197612767569,278881129048305 +11304440761775,12156240535488,-46908062880401,-30762308,31555328,793020,-18076516,-18057472,-36133988,4,-4569836,-5292973,4,4463661,-5094718,-4,55468,-2595859,281197612767569,72081417417945 +-357916026273,70368744177664,15803140915880,-3601028,0,-108041568,9059004,0,-40863584,0,-10215896,27010392,4,456648,339559,0,-2264751,-900257,281197612767569,65263283840769 +16595286750089,-53773457427575,25212273375370,-18511324,-18511324,-25986520,14954372,14954372,-39829016,4,-6269510,6622605,-4,-3687744,-125975,0,-3738593,-4627831,281197612767569,175413043890537 +31467340926933,-38901403250731,16591258081306,13454164,13454164,35371112,-12760492,-12760492,50136680,4,6177013,-5681526,-4,6357157,-3161252,0,3190123,3363541,281197612767569,100931338860049 +33057754008885,37310990168779,-13623443247239,1229012,-1229012,50117092,22287860,-22287860,-7239292,4,2038343,6583800,4,228520,-5945473,0,5571965,-307253,281197612767569,258834592306937 +9597721023861,-24136086264571,-36634936889232,24043988,36167700,-12123712,24803860,-9515948,34319808,4,4181409,5746942,-4,4398543,-2716014,-4,-1802422,3294983,281197612767569,219595620034081 +-12261347031621,9062009019559,-863289340793,4246252,21231260,39859740,818316,4091580,-257469892,-20,8276623,1348390,4,11218170,1723309,0,204579,-1061563,281197612767569,96175778819465 +26835906000774,-43532838176890,7191818660941,9635352,9635352,39705908,20087576,20087576,-34072908,4,4756459,6387092,-4,3761768,3539385,0,5021894,-2408838,281197612767569,108898553022257 +-15158160759527,55210583418137,-11656724462769,-10022812,-10022812,56422716,17490052,17490052,13874716,-4,-3445805,10652094,4,-22874,3453585,0,4372513,2505703,281197612767569,163309537107225 +21323819503314,-3277604341193,49044924674350,-11291832,39202012,11291832,29845192,-3904740,-29845192,4,1027901,6962146,0,7461298,2822958,4,51716,-2838357,281197612767569,85511742253377 +-10784246592733,-18140451963424,-70368744177664,32915596,-1804416,0,767660,34163584,0,0,8540896,451104,0,-191915,8228899,-4,-1259447,-2190472,281197612767569,126235761227177 +-6715085245849,-14162127633995,-70368744177664,-24162916,18518740,0,21094812,30428884,0,0,-7607221,4629685,0,5273703,6040729,-4,-335429,-1657530,281197612767569,156444747308113 +-12794844519862,-19189366098216,2750951484073,4792616,-19170464,452260,-204440,817760,-234943164,-16,16009099,-156527,-4,-10681673,-67398,0,-51110,-1198154,281197612767569,216613462067001 +6582422174672,-8561702634781,-70368744177664,-1790144,46464908,0,-23715008,-13397940,0,0,-3349485,-11616227,0,5928752,-447536,-4,-1034663,-1032152,281197612767569,117440838561889 +-11902554572116,-58466189605548,25293045029747,22395568,-22395568,22430156,10351920,-10351920,-39905428,-4,9219114,2646607,-4,-757243,-2960932,0,2587980,-5598892,281197612767569,213574656745929 +1389785777797,70368744177664,-33973415843379,-15309292,0,-41954508,17076372,0,-26746444,0,-6686611,10488627,4,-1929020,-2054949,0,-4269093,-3827323,281197612767569,128091322447217 +-2442895416107,32081868833673,70368744177664,-25452716,9095716,0,-3147788,-43110076,0,0,-10777519,-2273929,0,786947,-6363179,4,-732926,2822101,281197612767569,96884398495065 +12042198866623,-18823730810127,70368744177664,6393596,40626116,0,27759164,288900,0,0,-72225,10156529,0,6939791,-1598399,4,1868763,-2165660,281197612767569,62561007844225 +-27596730762889,-23986865294638,42772013414775,-31446564,2966344,-31446564,-8629636,-34989560,-8629636,-4,-6052303,2229072,0,2157409,-7861641,4,-2695087,-2970658,281197612767569,104325105938921 +-17597767748477,52770976429187,19205347385610,16541196,16541196,-8446936,1434892,1434892,67333672,-4,12525824,2712257,4,4307594,-600523,0,-358723,4135299,281197612767569,149868224631441 +12235500062153,-3984086036769,58133244115511,24040228,-23470212,-24040228,-13334844,-33815332,13334844,4,6795161,-5187594,0,-3333711,-6010057,4,-1658672,679959,281197612767569,185099925194617 +-26270404879997,17514851476379,44098339297667,32897548,-10632596,32897548,1801676,-34806740,1801676,-4,5565239,-3712854,0,450419,-8224387,4,3136446,1054705,281197612767569,176982365555361 +21857401310191,-15322423494827,48511342867473,25531324,-23533228,-25531324,-14296868,-30920780,14296868,4,4550834,-5445707,0,-3574217,-6382831,4,-3179361,437600,281197612767569,60446908114441 +16134476941207,54234267236457,-18210727648858,19587676,-19587676,-1888616,-2960164,2960164,-57194600,4,10828673,-1631170,4,-3469977,-1159016,0,-740041,-4896919,281197612767569,222033340412849 +31953316947378,28827363595413,38415427230286,-30830904,-12755372,30830904,-7191800,33543156,7191800,4,-3841386,-4898399,0,-1797950,7707726,4,4544403,-1709556,281197612767569,254489943350681 +-16182032657206,-54186711520458,-9250888393115,-15078616,15078616,-22002284,-9636696,9636696,60607060,-4,-11350740,-4731227,-4,3801025,769344,0,-2409174,3769654,281197612767569,137509470215617 +-34898675983743,-35470068193921,4966038148802,9782788,-9782788,57217800,-14034076,14034076,33007048,-4,4406985,-7037704,-4,-3844777,7266746,0,3508519,2445697,281197612767569,109959982726697 +-30190515696757,-40178228480907,14666265209692,-15424980,15424980,-38814352,-17273812,17273812,29525360,-4,-5114554,-4736709,-4,2266786,4966879,0,-4318453,3856245,281197612767569,210405554690257 +14791264497097,40786215183470,10947233933396,8942372,-17884744,59625808,-5873724,11747448,86741456,8,12112102,-9335464,4,-4786631,2785494,0,1468431,2235593,281197612767569,228140486940601 +-9190052790898,33608533014072,-5861937976019,3800632,15202528,-142450508,-5468744,-21874976,-91267596,-16,11353051,-16692199,4,2865962,-4730107,0,-1367186,-950158,281197612767569,91319284511969 +-2397451872163,-70368744177664,33638372601583,-21344908,0,-16179268,-12961836,0,42922972,0,-10730743,-4044817,-4,-1183442,2688683,0,-3240459,5336227,281197612767569,70023409695305 +-29399217455188,40969526722476,6519019960951,18927280,18927280,-3396132,-3990352,-3990352,-58769572,-4,8461670,-932677,4,6230723,83644,0,-997588,-4731820,281197612767569,201568511754737 +5249522641937,70368744177664,-34021422393753,-18527164,0,-26944100,11335268,0,-44285316,0,-11071329,6736025,4,-544152,-2741857,0,-2833817,-4631791,281197612767569,126301486888409 +-28887100051016,-41481644126648,-5972504555085,59104,-59104,-66250036,-16989984,16989984,-5293300,-4,1140590,-9762173,-4,-182735,6800336,0,-4247496,-14776,281197612767569,53847327707137 +31496178304225,38872565873439,-10111478135269,-11440252,11440252,-37532564,25283044,-25283044,-15468404,4,-3044482,4772393,4,822619,-4610748,0,-6320761,-2860063,281197612767569,94955036318313 +29893464113293,10581815951078,-13614482438386,-3002828,6005656,-81189832,13281588,-26563176,-15841736,8,-1880374,2761780,4,1040030,-8767839,0,-3320397,-750707,281197612767569,49625166016273 +-34350097074321,36018647103343,-12739714746338,82364,82364,-51271560,-21962980,-21962980,2140984,-4,720088,-6557183,4,-1255334,-6260707,0,-5490745,-20591,281197612767569,187495755560953 +8548699137452,36173947627856,-8698126998537,2320048,-9280192,166187996,-5925456,23701824,60843676,16,8551799,-21070987,4,-1664780,5119003,0,1481364,580012,281197612767569,23539303231265 +-10758399623265,-48851944931134,-4305163627434,4629116,-9258232,75708760,13066140,-26132280,-29525864,-8,4724726,13281388,-4,-1328370,-2822901,0,3266535,-1157279,281197612767569,174175603728009 +34531007434624,35837736743040,18005419758607,-15974912,15974912,34157628,8551936,-8551936,52193468,4,-7192387,3327106,4,5855980,-5212301,0,2137984,3993728,281197612767569,21915278434353 +25068174813223,-45300569364441,-30631033752962,-25942884,-25942884,12653048,6756476,6756476,40103864,4,-5719052,4859571,-4,-4306914,-1696309,0,1689119,6485721,281197612767569,134320667745817 +-1544497073189,-27556641352798,70368744177664,-24640660,19957384,0,-12766036,-35353080,0,0,-8838270,-4989346,0,3191509,-6160165,4,1055818,-2521851,281197612767569,87000253141569 +-1830041464806,70368744177664,17427692834801,-13920152,0,37903300,10917928,0,51154212,0,-12788553,9475825,4,-1008575,-615442,0,2729482,3480038,281197612767569,216734810572457 +34680425882421,-35688318295243,-7617952276703,-15066924,-15066924,24172676,-10172204,-10172204,-58406780,4,-7130113,-3472640,-4,-7471582,-2570529,0,2543051,-3766731,281197612767569,247675061687633 +17654501178497,-35059741820670,-974629608482,10538500,21077000,-43231368,-7858268,-15716536,-74600392,8,9237598,-5457760,-4,4706250,-2675041,0,-1964567,-2634625,281197612767569,206312130095161 +84229119409,70368744177664,-11275705728489,18453188,0,-6108068,2321156,0,60245532,0,15061383,1527017,4,-111012,737395,0,-580289,4613297,281197612767569,105832151562593 +-4476895873113,-8802995960389,-70368744177664,-33529188,23513836,0,6471100,29041548,0,0,-7260387,5878459,0,1617775,8382297,-4,259529,-1422600,281197612767569,257910010925769 +25908011153103,-44460733024561,-11698811083150,25345852,25345852,7836104,785084,785084,-44178744,4,7010939,184324,-4,4033747,1774702,0,196271,-6336463,281197612767569,105193967406705 +30693523482711,39675220694953,-8651580302302,25191772,-25191772,21604488,5002812,-5002812,-40402744,4,5848726,2270945,4,-4251960,-3130177,0,1250703,-6297943,281197612767569,135803757368921 +-19800682686287,30767378805090,15881841455950,-10322236,-20644472,47306040,10580868,21161736,60583864,-8,-5428260,6335750,4,-4858853,2745380,0,2645217,2580559,281197612767569,55293988578433 +32521603787967,5325536601730,713021097216,-8857860,17715720,63312896,11622044,-23244088,44037120,8,-892068,1153010,4,5058606,-7337607,0,2905511,2214465,281197612767569,227710731813609 +5641902963170,-30875423435474,6833168601859,-2941048,-20587336,-179052532,-2100856,-14705992,254921484,28,-27605723,-20140332,-4,-5160664,-3517543,0,-525214,735262,281197612767569,179458934197137 +-23147670056849,-47221074120815,-33992491685140,20489660,-20489660,-27165776,18063644,-18063644,31000368,-4,7382180,2082965,-4,-367912,-4708479,0,-4515911,5122415,281197612767569,186685684492409 +18656111151264,19700795534335,51712633026400,-9657728,32560124,9657728,-29234560,-18018628,29234560,4,-5356550,-5305995,0,7308640,-2414432,4,-851893,2834036,281197612767569,221246186967969 +-30651544613947,-39717199563717,-2403556662261,19036948,-19036948,-9632724,9271156,-9271156,54451660,-4,7762506,1196655,-4,-5850409,-1211526,0,-2317789,4759237,281197612767569,68023939766025 +10964032570904,27388809795775,-59404711606760,-26363808,-2783492,-26363808,572512,42766716,572512,4,-9081535,-3152770,0,143128,6590952,-4,-1610144,2456897,281197612767569,257846997666993 +29436993610286,11494756957092,7836110849241,12062904,-24125808,-46100636,9875576,-19751152,55594372,8,2820201,1210989,4,-5539196,-5157085,0,-2468894,3015726,281197612767569,29574676995737 +-2674808142219,-67693936035445,-9444692696593,9676244,-9676244,44493756,5061268,-5061268,-93084164,-4,22216651,11025302,-4,-1054390,-98137,0,1265317,-2419061,281197612767569,40728240735937 +-1657691149414,67053361878836,-22026283345329,5375592,10751184,-90026692,-2749912,-5499824,-163393060,-8,39354101,-20604971,4,747082,-950851,0,-687478,-1343898,281197612767569,115421288238889 +27953474139134,-3081276687099,42415270038530,-30664712,9453588,30664712,-9202696,39553556,9202696,4,-6061039,1760238,0,-2300674,7666178,4,3827350,-603159,281197612767569,220180255101393 +-18197853533590,52170890644074,3215285051253,-24559192,-24559192,-4847148,3011048,3011048,-45250060,-4,-8421414,617871,4,-2891101,593916,0,-752762,-6139798,281197612767569,85672387393721 +-5918237195100,-11555782827025,-70368744177664,-458096,-45943876,0,-24419440,8679804,0,0,-2169951,-11485969,0,-6104860,114524,-4,1185025,947200,281197612767569,178039370677729 +-7685864236108,28526281540629,-41842462637035,-26599728,25238612,25238612,-22884272,-20614220,-20614220,0,-5153555,-6309653,4,2838960,-4643321,-4,2882108,-2006611,281197612767569,269170298841929 +30937412260415,-39431331917249,7066600265228,-16683780,-16683780,-11687888,3772028,3772028,-64842192,4,-8988929,2056192,-4,-7221619,865780,0,-943007,-4170945,281197612767569,178021620538097 +-13339087728483,-43690568720698,-23858226886567,-3461516,6923032,-78996124,13205012,-26410024,-23907196,-8,-1472325,12848591,-4,2252237,-3450220,0,-3301253,-865379,281197612767569,6714722531033 +-15266036752639,-4951578402408,55102707425025,23484420,28649056,23484420,-15418684,29132896,-15418684,-4,5431938,-6021585,0,3854671,5871105,4,1851286,-1140679,281197612767569,255498761107713 +-21660231471068,2378596941247,-48708512706596,7516304,37231356,-7516304,-26794480,17070236,26794480,-4,3180386,-6379273,0,6698620,1879076,-4,-1087173,2928566,281197612767569,168246103288681 +28087002828321,42281741349343,-842884428888,25072772,-25072772,26578592,3522436,-3522436,-41171296,4,6195091,3917420,4,-4097733,-2727228,0,880609,-6268193,281197612767569,107062433441809 +4224851419514,-70368744177664,7971383392207,9395688,0,51430204,18055720,0,-20997988,0,5249497,12857551,-4,826512,505865,0,4513930,-2348922,281197612767569,139349029771513 +-6375016532662,31996863822501,-3295158641954,-18780888,-9390444,-59493512,-16341592,-8170796,68132088,-4,-7649309,-6872898,8,-1734404,-1127582,0,-2042699,2347611,281197612767569,105100800505889 +-1590281897354,34389231140155,10660649878886,-16428584,-8214292,-26559080,-3570408,-1785204,131293912,-4,-16108459,-2933748,8,-606560,-772274,0,-446301,2053573,281197612767569,148129931415433 +-24898128740139,45470615437525,-4024261968636,12128084,12128084,47014928,-20845356,-20845356,12026384,-4,1644764,-7768379,4,1361832,-3985353,0,5211339,3032021,281197612767569,44385239890225 +-3028408295598,70368744177664,-24243225621131,16053576,0,-31145516,13658504,0,43635060,0,10908765,7786379,4,-706924,1717779,0,-3414626,4013394,281197612767569,238920811290393 +-631373009607,70368744177664,32276113156304,-347932,0,-52665536,21356196,0,-3346624,0,-836656,13166384,4,2441361,158030,0,-5339049,-86983,281197612767569,23481285196609 +18595798084299,51772946093365,-21625388042610,9183020,-9183020,-46144968,17810508,-17810508,33108344,4,4721405,9193170,4,-3555681,-2343072,0,-4452627,2295755,281197612767569,48879484426153 +-3113743771769,67255000405895,-25558256610939,-5348836,-5348836,76583444,-13275620,-13275620,-20417004,-4,-6083835,-17812996,4,979584,-1332865,0,3318905,-1337209,281197612767569,252226902593105 +19880287098247,50488457079417,10726724653191,-14591460,14591460,-42252772,19331452,-19331452,-21183108,4,-3062934,8134989,4,2232843,-2428204,0,-4832863,-3647865,281197612767569,104529232628025 +5634271625064,-36605023798307,33763720379357,-26845792,9100148,9100148,833440,41657012,41657012,0,-10414253,2275037,-4,-733873,3402386,4,942233,3309062,281197612767569,52494056260193 +18064533137489,34239677902686,8462363253599,-12305084,24610168,-15134340,3548964,-7097928,-87133796,8,-10385889,2580887,4,5698780,-601349,0,-887241,-3076271,281197612767569,133463843292105 +-5420876154721,-12855331631710,70368744177664,362108,-43487608,0,25937404,-5677176,0,0,-1419294,10871902,0,-6484351,90527,4,-1293931,854058,281197612767569,240793312405361 +-26324692067889,-44044052109775,18367215243695,-4961476,4961476,37923516,26711836,-26711836,22753948,-4,-1817405,6257870,-4,3871082,-3223009,0,6677959,1240369,281197612767569,79299041302361 +26897332634649,-43471411543015,-1599141764135,-16413596,-16413596,-27325596,-2600156,-2600156,64266788,4,-9940230,-4126955,-4,-6126467,-2704444,0,-650039,4103399,281197612767569,68015655947649 +23968121720413,46400622457251,-7093447642378,12199284,-12199284,43922392,16393300,-16393300,-33269736,4,5897581,6933090,4,-2419853,-4047508,0,4098325,-3049821,281197612767569,116923726009321 +4572910776398,32897916700633,-3790241076146,969016,-484508,165067064,-13590728,6795364,8687416,4,1106862,-19285999,8,41870,2694768,0,1698841,121127,281197612767569,135337043215505 +-2872231337853,34663546531351,35705197646313,21239308,28474460,-28474460,-22007316,23506108,-23506108,0,5876527,-7118615,4,3031497,2403654,4,-2470332,-2906173,281197612767569,266913604192633 +31468450888769,7566308808803,38900293288895,11324676,-38701684,-11324676,-27670972,-4855476,27670972,4,1414856,-5044217,0,-6917743,-2831169,4,200987,4631204,281197612767569,32973427367073 +11554475387325,-58814268790339,17992224191025,13964020,13964020,41215172,11353172,11353172,-47119452,4,9119913,9504518,-4,2659950,799275,0,2838293,-3491005,281197612767569,127744115787785 +6382989150989,18010220714079,-70368744177664,30365748,-14613124,0,-80972,37116924,0,0,9279231,3653281,0,20243,7591437,-4,846879,2274338,281197612767569,115654758131121 +-19030962006651,-15648316060657,51337782171013,-28401132,-11987908,-28401132,-16224844,32794396,-16224844,-4,-5079315,-3765388,0,-4056211,7100283,4,-3119284,768411,281197612767569,228060074385305 +-28410923419379,-41957820758285,-5407671574454,19206196,-19206196,-19392216,16319220,-16319220,42144424,-4,6595745,2521696,-4,-3940361,-2326358,0,-4079805,4801549,281197612767569,193904457904065 +-1166188752770,70368744177664,23290992727233,-16545288,0,-20566268,-6561992,0,59892836,0,-14973209,-5141567,4,294836,-1454269,0,-1640498,4136322,281197612767569,79188120330281 +-19325826112109,-12391265841337,-2635194802021,-5379508,16138524,107132524,-5964724,17894172,-90507156,-12,-4151889,-4565164,-4,6158300,7405989,0,1491181,-1344877,281197612767569,8039848544977 +-17931291652413,2866589999889,52437452525251,4181772,-37803964,4181772,-28121620,-15015452,-28121620,-4,2510912,-7085287,0,-7030405,-1045443,4,1242951,-2365704,281197612767569,209053675002297 +9099138664955,7476510052307,-70368744177664,26074092,-18574516,0,-14495572,-32854516,0,0,8213629,-4643629,0,-3623893,-6518523,-4,677046,-1293029,281197612767569,51474232067809 +-93762533947,-70368744177664,19604033579879,-17407212,0,24457628,8288372,0,53034684,0,-13258671,6114407,-4,594931,1204222,0,2072093,4351803,281197612767569,130686014643273 +34085852053211,-36282892124453,20987807898899,-13488276,-13488276,45533260,14955244,14955244,32987084,4,-5367243,4863626,-4,-2879528,6519689,0,3738811,3372069,281197612767569,178439438939121 +22430386762246,47938357415418,-27134777144571,-13242344,13242344,36796436,16994520,-16994520,37800116,4,-4799478,7543437,4,4650551,-1655672,0,4248630,3310586,281197612767569,56583785789401 +27807920729856,42560823447808,-7046666015605,-11092992,11092992,36841004,24378368,-24378368,20533356,4,-2494468,5848307,4,2638871,-3361944,0,6094592,2773248,281197612767569,214139184407041 +24838835908763,-1206215474669,-45529908268901,-25168276,-107444,-25168276,-10327412,44690796,-10327412,4,-7273204,90475,0,-2581853,6292069,-4,-3899495,-117336,281197612767569,179378792479849 +34744368656764,-35624375520900,-3032214250999,5789168,5789168,68494372,-14870032,-14870032,18549540,4,2507878,-8606503,-4,2129507,-8517090,0,3717508,1447292,281197612767569,38813239697681 +-3334901764816,-115395974527,70368744177664,25883840,8881668,0,-17681728,37430948,0,0,9357737,-2220417,0,4420432,6470960,4,450729,-94618,281197612767569,57233517279737 +14054143889266,-56314600288398,-4648986022449,10630600,10630600,49126204,12458056,12458056,-48339972,4,9877125,9653082,-4,2207868,2628469,0,3114514,-2657650,281197612767569,232528390963489 +-14043624487342,-14194246228296,7945419658437,4690248,-18760992,88055572,-1874680,7498720,204855668,-16,10542153,-3910893,-4,-10167941,4525750,0,468670,1172562,281197612767569,61354597580937 +-23294629644759,32994709298218,-47074114532905,-8973148,-35551064,8973148,27864100,-15078488,-27864100,-4,-5787990,4893751,0,-6966025,-2243287,-4,-2018368,-3994015,281197612767569,32348263944753 +29268860428856,-3064171017573,-41099883748808,-14309152,-40608148,-14309152,28321760,1690828,28321760,4,-61426,5773673,0,-7080440,-3577288,-4,484133,4378364,281197612767569,16244155965465 +16109659220013,-5930107297612,2987061916843,3296436,13185744,-170539348,-3997324,-15989296,-134751252,16,3008617,-3452989,-4,7669799,-9795462,0,-999331,-824109,281197612767569,149917938312257 +-2976967713173,-70368744177664,28628649182912,4091308,0,-56026368,19593932,0,6873856,0,1718464,14006592,-4,-2065587,-176428,0,-4898483,1022827,281197612767569,5765313112233 +-28870587215685,-41498156961979,-22085285367520,4388588,-4388588,-44284800,-24977684,24977684,-4504448,-4,2623912,-6184615,-4,1497800,4886585,0,-6244421,-1097147,281197612767569,34026193405777 +-27730096222415,-20596029424546,42638647955249,-4826940,37140856,-4826940,28084324,17158712,28084324,-4,-4654232,5273009,0,7021081,1206735,4,364554,4012205,281197612767569,200648676993593 +-18103753324496,-52264990853168,-17952486876377,-14393152,14393152,37744796,-13357888,13357888,-43194788,-4,-8872485,-6090554,-4,1926212,3345645,0,3339472,-3598288,281197612767569,29656510843745 +25525940138171,-19316863901322,6451245995689,8746732,17493464,63739556,-13547636,-27095272,29997444,8,1437635,-4775213,-4,3030863,-5579838,0,3386909,2186683,281197612767569,191218750567625 +32973501456495,-913899955345,37395242721169,15787452,-24325700,-15787452,-25319108,-32303812,25319108,4,4209503,-3283040,0,-6329777,-3946863,4,-3866450,2798385,281197612767569,104765176742001 +-2208802422137,32558758668881,-37809985508783,-8974820,-39566012,-39566012,28237052,-966300,-966300,0,-241575,9891503,4,-3800611,-895086,-4,-3258652,-1348619,281197612767569,199561940408409 +11947320963229,10632139361519,1971163238219,-1266060,6330300,303608108,-3179468,15897340,-126840468,20,-4902467,-11423842,4,5361530,12895637,0,794867,-316515,281197612767569,236118294066817 +-13591394551278,-14288256711143,-42489092915243,29712456,824420,-30536876,-17774840,37400004,-19625164,-4,6641804,-1674563,-4,1735513,5959656,-4,-2708197,-1468458,281197612767569,128509204767977 +22504078454361,-47864665723303,20003894627316,15283556,15283556,-36184112,-13644188,-13644188,-41364528,4,8003682,-5066915,-4,2337450,-3979113,0,-3411047,-3820889,281197612767569,56269077495185 +24002614855965,22363514465734,-1197567506048,-16445324,32890648,-3004928,2780308,-5560616,-67955200,8,-5422778,98808,4,5783011,-326212,0,-695077,-4111331,281197612767569,261336651065977 +25391840245233,30921312406182,44976903932431,-23071804,21811864,23071804,18558212,31255064,-18558212,4,-7032953,950776,0,4639553,5767951,4,780813,-4502190,281197612767569,4387362104737 +-3736043213898,33121030445619,-37247713732045,16455384,23870668,23870668,31696408,-22441620,-22441620,0,5610405,5967667,4,4492270,-1860711,-4,3431832,-2253135,281197612767569,222125862320393 +-17152599749305,-53216144428359,3315522496111,-3720932,3720932,-52101700,-20338788,20338788,17795132,-4,-3603951,-9806608,-4,844832,3218817,0,-5084697,930233,281197612767569,37461536931505 +21778610643271,21942853550664,-26647279983729,-2848484,38594848,35746364,-30038276,11733536,-18304740,4,-316161,-6440448,4,4260024,2496143,-4,3249545,-3208264,281197612767569,195001489055897 +21228145880250,27912452417164,-10814549231775,8948456,-17896912,-64145020,11087976,-22175952,46338884,8,3743171,7048555,4,-3920775,-4493850,0,-2771994,2237114,281197612767569,138489042147521 +8407939473498,61960804704166,-5682674933703,-16721560,16721560,-23823132,-5884632,5884632,58948420,4,-13095061,-4906572,4,1642044,1049211,0,-1471158,4180390,281197612767569,237865412276521 +-10210070465280,24737064705749,-45631679471915,34460672,-3373228,-3373228,2085888,-32876204,-32876204,0,8219051,-843307,4,1530690,-5708995,-4,-1009218,-2906173,281197612767569,9211775730641 +-21368814015420,48999930162244,-10217653134887,-777968,-777968,-58006684,19470224,19470224,4503044,-4,1490679,10126202,4,-364918,4375469,0,-4867556,-194492,281197612767569,63637979167417 +6763548038209,-63605196139455,-13251480055067,-8966908,-8966908,-59959404,-13425852,-13425852,35786452,4,-8718774,-13126939,-4,-227839,-1862912,0,-3356463,2241727,281197612767569,92406424899553 +-22944923370491,-47423820807173,20900679900450,4799508,-4799508,50900104,-22241932,22241932,-1295288,-4,1433321,-8219432,-4,1757143,4505594,0,5560483,1199877,281197612767569,109819927383369 +4590862236027,-70368744177664,-31783409269040,8624620,0,55827264,18184556,0,-12836032,0,3209008,13956816,-4,-1843996,1884413,0,4546139,-2156155,281197612767569,109322290531569 +29229598783498,-41139145394166,25622245850641,17397800,17397800,34968644,-19398296,-19398296,25725540,4,1994134,-6694559,-4,4437251,-2047602,0,4849574,4349450,281197612767569,28703529220313 +-4504966371327,-61358811435010,11435461922576,4094980,-8189960,122092608,-6920508,13841016,68610112,-8,15518656,-26282270,-4,-816936,2120441,0,1730127,1023745,281197612767569,166524257389313 +-21391772921070,-48976971256594,-8658753595885,18924616,-18924616,-22959028,-15225080,15225080,-41023124,-4,7606426,-3412737,-4,-2649355,2327020,0,-3806270,-4731154,281197612767569,120841759739241 +-4328962915576,26828375204137,-43540368973527,30075936,245924,245924,-3374048,37407652,37407652,0,9351913,-61481,4,1097233,4648558,-4,-253721,2870426,281197612767569,198896857602577 +7843711544218,24903861606887,-45464882570777,20973160,31648668,31648668,24235688,-17111044,-17111044,0,4277761,7912167,4,3437814,-4269599,-4,2621108,-973691,281197612767569,3942462036729 +-13633251248129,15793858654713,70368744177664,-30473220,7652324,0,-10844996,-34223836,0,0,-8555959,-1913081,0,2711249,-7618305,4,-2266157,1339244,281197612767569,96284201011745 +11148017657667,-3480638231662,-4819627332993,-1494772,-8968632,-347746820,-1001044,-6006264,520340252,24,-6537221,-4146569,-4,-20591307,-13798356,0,-250261,373693,281197612767569,104126333890953 +6295449973979,-57777844229706,-24601924749315,-9631892,-19263784,-24622092,1862124,3724248,-112132748,8,-23342793,3370407,-4,-2345197,1392558,0,-465531,-2407973,281197612767569,242414302014257 +19313946996912,13707305850909,-51054797180752,31720128,16206964,31720128,-1472320,34742548,-1472320,4,6230011,-4484380,0,368080,7930032,-4,2455626,432639,281197612767569,16120889057561 +-23588906323633,-29334135878417,-41034608299247,-32724676,-2975812,2975812,3567996,-34080772,34080772,0,-8520193,743953,-4,2335969,-5020128,-4,3227968,3161041,281197612767569,229108714966337 +18038352097948,-52330392079716,-22774424660495,18143856,18143856,-22055996,-8197904,-8197904,-52088540,4,9020735,-5568576,-4,4001400,54577,0,-2049476,-4535964,281197612767569,243752208431529 +-1816851304835,-11702482248879,-70368744177664,-13359628,26544452,0,-31354380,-21977788,0,0,-5494447,-6636113,0,7838595,-3339907,-4,-1161715,726772,281197612767569,96300444549201 +-19609470229831,-50759273947833,-22498133689453,-17070364,17070364,42287692,-21588092,21588092,-12477140,-4,-3975566,-6261449,-4,-856281,4310474,0,5397023,-4267591,281197612767569,191799855237945 +15715942618488,-18333568298849,-52035175878815,-3639840,32433788,-32433788,33756128,8533564,-8533564,0,-2133391,8108447,-4,5763898,2483799,-4,-2675134,1573839,281197612767569,262935640544353 +-2418417172597,15779201029852,70368744177664,619052,44395376,0,-25389876,-2088976,0,0,-522244,-11098844,0,6347469,154763,4,-1441279,-416146,281197612767569,10201382528457 +-11390977728566,58977766449098,25904067203559,-15722712,-15722712,-40121444,-12751832,-12751832,39069468,-4,-9359817,-6959734,4,-407550,-3070627,0,-3187958,3930678,281197612767569,149416475449713 +-15339410597514,-55029333580150,-14887697789091,15650264,-15650264,-11589260,-3235688,3235688,-69545196,-4,13767468,-1437971,-4,-3618831,1459344,0,-808922,-3912566,281197612767569,161273905682777 +-31299518382595,39069225795069,6774825306526,-17931276,-17931276,31780472,18550196,18550196,29912312,-4,-3705397,4842774,4,-3772681,3102344,0,4637549,4482819,281197612767569,161323025686401 +3811857893290,-23741254293599,-46627489884065,-11782488,33356420,-33356420,-31662488,-5920028,5920028,0,-1480007,-8339105,-4,5164850,-2403545,-4,-2750772,542077,281197612767569,115474613515753 +-18165612767376,16432193059743,52203131410288,-3236416,38769276,-3236416,-28979776,-733828,-28979776,-4,1555709,-7379196,0,7244944,-809104,4,-1739166,-2313123,281197612767569,125817795294865 +-12059836084086,-29154454046789,6447562212201,11721256,-5860628,100223396,10931304,-5465652,-98643644,-4,10342453,10246636,-8,-3976005,-4562577,0,1366413,-1465157,281197612767569,266749177662329 +842956129765,-21794907975368,48573836202296,28566420,7234784,7234784,-21990956,33843936,33843936,0,8460984,-1808696,-4,3896311,4908010,4,1601428,2233595,281197612767569,85437009227425 +-25545226075555,19278292026554,-3751923959823,-10291852,-20583704,58588100,-8449324,-16898648,-61298012,-8,-4423567,-3738343,4,-5450468,-5454341,0,2112331,-2572963,281197612767569,208519373597193 +19219315239881,-31930113697902,6791004071784,-10392796,-20785592,38272416,-2778972,-5557944,-98100832,8,-11262510,-3840084,-4,-6631349,-2864010,0,694743,-2598199,281197612767569,239781618292657 +5216822028663,70368744177664,22091503316846,-16651812,0,29312440,15776188,0,39843192,0,-9960798,7328110,4,-499742,-1850187,0,3944047,4162953,281197612767569,22817238753689 +-14670767745228,-22146627682759,70368744177664,-20509488,19133668,0,25999312,30641316,0,0,-7660329,4783417,0,6499828,5127372,4,448585,2610966,281197612767569,265722258178497 +1769739213063,70368744177664,-19798263482214,17524764,0,16988776,-5947972,0,58480168,0,14620042,-4247194,4,50679,1339464,0,1486993,4381191,281197612767569,206048048644649 +19856333192526,30656077792612,-3781091401511,1441080,-2882160,-76152988,-14417608,28835216,-19399324,8,1725477,-8332711,4,-1562177,5352768,0,-3604402,-360270,281197612767569,45331564559569 +30753964129200,5686588640721,39614780048464,-17224000,-24259772,17224000,-25539392,29396196,25539392,4,-3621252,-3762293,0,-6384848,4306000,4,3727797,2302650,281197612767569,106370913819577 +-10276120004067,2203849052226,70368744177664,14603380,-39847672,0,26787252,4005256,0,0,1001314,9961918,0,-6696813,3650845,4,355959,1340424,281197612767569,224225963202785 +-32443797305896,-37924946871768,24037163469561,18331488,-18331488,32909284,-16823200,16823200,31217348,-4,5642769,-2868624,-4,-2161568,5358697,0,4205800,4582872,281197612767569,215870658035273 +3099775917498,-33634484130083,-2570919359539,7294696,3647348,-28353740,667624,333812,306095028,4,36573376,3421407,-8,3377005,245621,0,-83453,911837,281197612767569,87250234238449 +32695726797730,-37673017379934,-13124569678545,11601544,11601544,-49850180,-15734072,-15734072,-29440356,4,3206694,-7212975,-4,4153395,-5249570,0,-3933518,-2900386,281197612767569,247584787053017 +22820126968561,10423871706573,47548617209103,-26064956,-7961804,26064956,-6821244,41112308,6821244,4,-6692352,-2310225,0,-1705311,6516239,4,3585725,-319774,281197612767569,66976885421057 +-24111553944951,-46257190232713,-15453439648620,-13941212,13941212,-27286960,9387908,-9387908,-62385712,-4,-9736966,5249695,-4,5859462,-1572045,0,-2346977,-3485303,281197612767569,247395838844521 +-11230941139913,59137803037751,24731275960354,17560796,17560796,31570056,4605404,4605404,-55835000,-4,12135561,5089912,4,1823189,2802602,0,1151351,-4390199,281197612767569,149894641373969 +24005495709635,46363248468029,-20547142835866,-14871796,14871796,31600024,-23218964,23218964,-26370728,4,-2648723,-6290622,4,3943959,1609384,0,5804741,-3717949,281197612767569,233691505409017 +27888480486073,42480263691591,1083628181189,23529188,-23529188,-10180844,-1163228,1163228,-47347884,4,7150231,-1445912,4,-4686740,1099299,0,-290807,-5882297,281197612767569,57811622875937 +-30152053376143,40216690801521,-3884094738274,-14153276,-14153276,-36271496,22866596,22866596,-20948808,-4,-2677594,5377715,4,-2559608,3690159,0,-5716649,-3538319,281197612767569,139793256407689 +-14890799553606,-6287373209109,55477944624058,-14260504,30653356,-14260504,23204328,29073964,23204328,-4,-6248719,5723152,0,5801082,3565126,4,-1019772,1940187,281197612767569,268535686317105 +-20554556868201,-2727594017621,49814187309463,13871708,42985132,13871708,24194108,-6193396,24194108,-4,861630,7741739,0,6048527,-3467927,4,686719,3004544,281197612767569,216879964545561 +-14723869665333,55644874512331,28244343824012,-10431700,-10431700,-48051664,-19482516,-19482516,18188080,-4,-5550562,-8452589,4,1003542,-3560327,0,-4870629,2607925,281197612767569,34164334114369 +-32022148600903,531169812952,38346595576761,26454756,-645280,26454756,13848388,42221664,13848388,-4,5725913,137832,0,-3462097,6613689,4,4829503,23488,281197612767569,253759324179113 +10309145674729,-60059598502935,-11538007615419,-5944412,-5944412,53849364,19778468,19778468,10235156,4,-1373178,11733753,-4,-1185611,1728588,0,4944617,1486103,281197612767569,272060404808017 +-14224279688597,-11504288569093,56144464489067,-26567252,22632428,-26567252,-13573236,-30816308,-13573236,-4,-6701539,-3428540,0,3393309,-6641813,4,-1002538,-2229567,281197612767569,169119574240313 +-285442047611,-4714135695023,-70368744177664,22696468,10805572,0,-2924716,48214404,0,0,12053601,-2701393,0,731179,5674117,-4,-97877,-369162,281197612767569,261620040064353 +31252178169830,-5049200567263,39116566007834,31156120,-16855932,-31156120,2550488,-37517212,-2550488,4,5259517,-2901358,0,637622,-7789030,4,-4119786,1312625,281197612767569,245761488295625 +6177295317695,-2593639328974,-70368744177664,-18280708,-32947000,0,-23006596,20125128,0,0,-5031282,-8236750,0,-5751649,4570177,-4,-229676,-891507,281197612767569,153676265992817 +-22843834727919,24681074721826,-8295598397524,7644228,15288456,-60854608,12460132,24920264,48094256,-8,4951582,4885444,4,3535991,5164104,0,-3115033,1911057,281197612767569,43052451207769 +-1651155352848,70368744177664,33341478840169,11094976,0,55368100,11239360,0,-45389724,0,11347431,13842025,4,-1065073,1639024,0,2809840,-2773744,281197612767569,47475323684993 +9563910448751,746334372592,-70368744177664,28048828,-20886592,0,16158556,28108224,0,0,7027056,5221648,0,-4039639,7012207,-4,912212,784053,281197612767569,184853238400745 +10828005366016,-9018907571200,-3018842235269,2319360,3092480,593636844,4482048,5976064,-309133076,16,9969211,18987905,-12,11843909,22861374,0,373504,-193280,281197612767569,277617512951697 +-8907170144643,-16953279884850,70368744177664,-4856332,-32616648,0,-32127468,16063480,0,0,-4015870,-8154162,0,-8031867,1214083,4,-2443365,-739644,281197612767569,8967736339577 +21512041551946,-7960023607791,48856702625718,-21432024,29226052,21432024,-19161688,-26403452,19161688,4,-4041063,-5678970,0,4790422,-5358006,4,2559800,1627543,281197612767569,110352082925473 +-17875847636723,13546936994720,52492896540941,-26111948,-17453440,-26111948,4881300,-39855488,4881300,-4,-7667668,1998205,0,-1220325,-6527987,4,-2296204,2365155,281197612767569,48904542149385 +-9548320912614,-19315525818493,41504897446557,27755624,6304268,34059892,-22097048,35545740,13448692,-4,6164281,-3266872,-4,2802108,5248101,4,2722154,1690805,281197612767569,272623376543921 +-30226309061861,-40142435115803,-29403865595618,-28917652,28917652,8572024,5663948,-5663948,37255736,-4,-5904887,-1798344,-4,3409047,-3941350,0,1415987,7229413,281197612767569,235728768262809 +-26826834235833,5236786921415,-43541909941831,15056156,-34667748,-15056156,-26689188,-13326500,26689188,-4,1564955,-5642938,0,-6672297,-3764039,-4,-1766670,3023999,281197612767569,208048203557569 +-24354092022067,24808470180926,21206181974671,-1030348,-33351432,32321084,-34178796,-13599176,-20579620,-4,-789279,-5361376,4,-4355626,-2718895,4,4189073,-2976482,281197612767569,85728097719081 +-26641722964401,-17085298248862,13189231064070,14941500,-29883000,-4720616,-1389764,2779528,-74914792,-8,4417024,-1686782,-4,-7155837,-253314,0,-347441,-3735375,281197612767569,125986806773201 +2174575260855,-290860672193,-70368744177664,-24766756,4690172,0,6571580,44215644,0,0,-11053911,1172543,0,1642895,6191689,-4,-348385,10642,281197612767569,98039728782521 +-30039224013120,-40329520164544,-11615528295313,1161984,-1161984,-45943364,-24909056,24909056,15926140,-4,-1253972,-6534779,-4,2727563,4951062,0,-6227264,-290496,281197612767569,28379039736289 +994828029838,-70368744177664,18497407237829,8537656,0,-46512364,20934776,0,17823860,0,4455965,11628091,-4,-1312754,725451,0,-5233694,2134414,281197612767569,30877775933257 +-16995537345643,7601552600600,-70368744177664,3316308,-31762336,0,-33584428,-17845152,0,0,4461288,-7940584,0,-8396107,-829077,-4,-1984481,1828258,281197612767569,149711506226929 +-4936705274313,-55558628354725,25321533516067,621788,-1865364,176732300,6350780,-19052340,-5648148,-12,2828805,34716302,-4,472256,-3155591,0,1587695,-155447,281197612767569,238363375352537 +-28896845363714,12575053450236,6600968271033,-12689416,-25378832,-51065116,7961208,15922416,-56689756,-8,-2906049,1686195,4,-5633195,5540042,0,-1990302,-3172354,281197612767569,19495289167105 +10341179950394,-20143177813695,50225566363969,-6034200,-32857852,-32857852,-32749912,8254308,8254308,0,-2063577,-8214463,-4,-6147055,-130448,4,-2040423,1638998,281197612767569,4050204421993 +-19238258094507,16029103068870,35101383014287,-6011564,-36404456,30392892,32668756,10544408,22124348,-4,55031,6270602,4,-5586118,1327621,4,2581071,2830512,281197612767569,97812700875793 +-19148150503456,-51220593674208,29700619159749,7249792,-7249792,-38768876,25693056,-25693056,17905204,-4,547173,7819836,-4,-3929128,-1872383,0,-6423264,1812448,281197612767569,137687035141369 +-13745545458141,23612786725940,-56623198719523,-18920308,-35913520,18920308,19040844,-23365168,-19040844,-4,-6297604,5637365,0,-4760211,-4730077,-4,-456312,-3341015,281197612767569,209452872850465 +14907892605373,-55460851572291,-31259051641543,-18025740,-18025740,-29634332,14955092,14955092,-37874492,4,-9123488,3837207,-4,-345135,3571376,0,-3738773,-4506435,281197612767569,75310284149641 +9575805786781,11441962069005,60792938390883,-21145996,21879860,21145996,-12263436,-40555084,12263436,4,-9257592,-3866025,0,3065859,-5286499,4,881179,1603940,281197612767569,230579199499569 +22154251810717,10937052206619,48214492366947,14928500,37063788,-14928500,-30247148,323276,30247148,4,-1119915,-6928806,0,7561787,3732125,4,-1200734,2337141,281197612767569,132001730994969 +-12154469643654,5409801771879,-70368744177664,-27852312,-14618212,0,14343016,-32896036,0,0,-8224009,3654553,0,-3585754,-6963078,-4,1144830,-1166541,281197612767569,132459521793857 +-15198307850802,-55170436326862,5490710018465,19832632,-19832632,-2473340,4081272,-4081272,56261092,-4,10947829,871660,-4,-3117444,253325,0,-1020318,4958158,281197612767569,111409776925609 +9619699349736,-60749044827928,-27037070260477,-19643488,-19643488,-37048308,15000480,15000480,-29025268,4,-7705219,6109058,-4,448902,3153019,0,-3750120,-4910872,281197612767569,103431572910673 +-34747470421279,-35621273756385,-7025731358300,-8460412,8460412,58046096,16539940,-16539940,19599632,-4,-2893220,7134685,-4,2006688,-7376839,0,4134985,2115103,281197612767569,196639102274873 +30866125352077,39502618825587,-5295880472390,2416180,-2416180,53197544,21438836,-21438836,6039912,4,-444284,7420363,4,1065694,-5879023,0,5359709,-604045,281197612767569,200756889691745 +13376675418402,-56992068759262,14661494897349,-12354424,-12354424,-33212652,-16818104,-16818104,45920884,4,-8421877,-7368300,-4,-3058344,-934863,0,-4204526,3088606,281197612767569,255726311966665 +9360524462839,-61008219714825,-7014649765310,7434204,7434204,62144776,13716316,13716316,-36789752,4,8315810,13284285,-4,881628,2251909,0,3429079,-1858551,281197612767569,200561585359729 +-18482528702123,-51886215475541,7028870575489,10867028,-10867028,48017924,12661236,-12661236,-47661020,-4,9101854,8580107,-4,-2813401,-3424374,0,3165309,-2716757,281197612767569,232997549513561 +-1082852289426,70368744177664,-18232716789955,10213816,0,57034996,9184312,0,-58946892,0,14736723,14258749,4,821692,-442189,0,2296078,-2553454,281197612767569,147490662297985 +11478452414847,58890291762817,-26409346786155,-9582084,9582084,-48464300,-19399268,19399268,19382836,4,-5875417,-9240680,4,-1029708,2875395,0,-4849817,2395521,281197612767569,47892834277353 +29660367921931,-20317758867981,-40708376255733,-18350036,-32658484,-18350036,-24187092,18309836,-24187092,4,-4393965,-3398676,0,-6046773,4587509,-4,-183494,-4765945,281197612767569,82124407220369 +22391038995715,11860886340444,47977705181949,-16365556,-35775120,16365556,26239980,-11436304,-26239980,4,-843621,6787524,0,-6559995,-4091389,4,2015455,-2156256,281197612767569,180936730267001 +25812247803792,44556496373872,219135547239,15834688,-15834688,7135644,6197824,-6197824,-68310436,4,10808476,1141875,4,-6269133,-642036,0,1549456,-3958672,281197612767569,124197946982561 +-21684623593405,-48684120584259,-130892179343,16274700,-16274700,-22250044,-10150996,10150996,-55303004,-4,9569969,-3840816,-4,-4255782,1721695,0,-2537749,-4068675,281197612767569,39688889011209 +29809339140427,40559405037237,-19555861997307,-12019412,12019412,40349716,-13557332,13557332,-48160876,4,-5997873,-6649296,4,6042346,3438133,0,3389333,-3004853,281197612767569,67323857390001 +21823274690378,26722194796908,-117233159627,6305064,-12610128,-57584428,15316072,-30632144,38688372,8,3660173,5472105,4,-3005960,-4462001,0,-3829018,1576266,281197612767569,66825928680345 +-21503948564243,-48864795613421,1305542238092,19599284,-19599284,-13447632,11770484,-11770484,49369904,-4,8516151,2425450,-4,-3826325,-936458,0,-2942621,4899821,281197612767569,45279064363969 +6991638586087,-25193727279009,-45175016898655,31199132,-23288452,23288452,-14405316,-25334756,25334756,0,6333689,-5822113,-4,-1682668,-5585739,-4,1918661,2214044,281197612767569,168327160374313 +16610454292443,-8721861395347,-70368744177664,7164780,29138356,0,32916844,-23274572,0,0,5818643,7284589,0,8229211,-1791195,-4,353513,1941528,281197612767569,124361227759313 +20014737284091,50354006893573,27793651251178,-7789588,7789588,-52693080,17495500,-17495500,-26189848,4,-2957634,10195609,4,3589828,-2977661,0,-4373875,-1947397,281197612767569,230272728243641 +-34326488053895,36042256123769,18058236277138,1448420,1448420,-42320312,26835492,26835492,-6756664,-4,-2586827,5511948,4,897661,5068130,0,-6708873,362105,281197612767569,267191630457569 +5640135676410,32364304250627,-6845738889580,-11722776,5861388,86010448,-20464472,10232236,-41938992,4,-4573334,-10032131,8,1338080,1438350,0,2558059,-1465347,281197612767569,135688379998281 +25009973918313,45358770259351,-28664104872869,-15719004,15719004,35292524,13294628,-13294628,41777388,4,-5378426,7288025,4,5065921,-1535106,0,3323657,3929751,281197612767569,247405938513905 +-694879369871,-70368744177664,-8150512045454,-11390524,0,-47070776,-13951004,0,41193480,0,-10298370,-11767694,-4,505666,-213625,0,-3487751,2847631,281197612767569,170458859289561 +16732741764053,30943615789445,-39425128388219,-28632236,-11341292,-11341292,-13154028,34112468,34112468,0,-8528117,-2835323,4,185437,4684610,-4,-3473944,2473449,281197612767569,146911120885249 +4268297753168,70368744177664,-4635743588905,16320832,0,-23954596,-7780544,0,-57565700,0,14391425,-5988649,4,-1001070,94453,0,-1945136,-4080208,281197612767569,50263278682217 +1277813020099,-16183900485435,-70368744177664,11856652,-38375660,0,-23844852,-17782252,0,0,4445563,-9593915,0,-5961213,-2964163,-4,1451728,507505,281197612767569,75144762180881 +-3367144333567,25085420279429,70368744177664,7100420,39364116,0,-27404124,6641972,0,0,1660493,-9841029,0,6851031,1775105,4,-2362837,-1103692,281197612767569,4444301426169 diff --git a/src/main/resources/villager_lattice_data.nbt b/src/main/resources/villager_lattice_data.nbt new file mode 100644 index 0000000000000000000000000000000000000000..052149fd075b5f7db8c8d6592bdd1f391a5ac07c GIT binary patch literal 172231 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 o#7_~ZZ$^6djJ3c literal 0 HcmV?d00001 From f047024e57d9da14d769340b0803ab504af0419f Mon Sep 17 00:00:00 2001 From: joe Date: Wed, 19 Jun 2024 20:38:58 +0100 Subject: [PATCH 10/78] Fixes to villager cracking --- .../clientcommands/ClientCommands.java | 2 +- .../features/VillagerCracker.java | 2 +- .../features/VillagerRngSimulator.java | 27 ++++++++---------- src/main/resources/villager_lattice_data.nbt | Bin 172231 -> 172231 bytes 4 files changed, 14 insertions(+), 17 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java index 0ed2df87d..decb2b2e4 100644 --- a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java +++ b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java @@ -89,7 +89,7 @@ public void onInitializeClient() { lattice_inverse.add(new LongArrayTag(inverse)); long[] offsets = new long[2]; for (int i = 0; i < 2; i++) { - offsets[i] = Long.parseLong(values[i + 11]); + offsets[i] = Long.parseLong(values[i + 18]); } offset.add(new LongArrayTag(offsets)); } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 0579a935b..57107d23d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -15,7 +15,7 @@ public class VillagerCracker { // This value was computed by brute forcing all seeds - public static final float MAX_ERROR = 0x1.4p-24f; + public static final float MAX_ERROR = 5 * 0x1.0p-24f; @Nullable private static UUID villagerUuid = null; diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 37d57a129..0d5ada909 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -292,28 +292,25 @@ public OptionalLong crackSeed() { float firstMax = Math.min(1.0f - 0x1.0p-24f, first + VillagerCracker.MAX_ERROR); float secondMin = Math.max(-1.0f + 0x1.0p-24f, second - VillagerCracker.MAX_ERROR); float secondMax = Math.min(1.0f - 0x1.0p-24f, second + VillagerCracker.MAX_ERROR); - int callsBetweenSounds2m = (ticksBetweenSounds - 1) * 2; - int callsBetweenSounds = ticksBetweenSounds * 2; - int callsBetweenSounds2p = (ticksBetweenSounds + 1) * 2; - OptionalLong seed2m = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, callsBetweenSounds2m); - OptionalLong seed = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, callsBetweenSounds); - OptionalLong seed2p = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, callsBetweenSounds2p); + OptionalLong seed2m = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, ticksBetweenSounds - 1); + OptionalLong seed = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, ticksBetweenSounds); + OptionalLong seed2p = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, ticksBetweenSounds + 1); System.out.println("Seed 2M: " + seed2m); System.out.println("Seed: " + seed); System.out.println("Seed 2P: " + seed2p); return seed; } - private OptionalLong crackSeed0(float firstPitch, float secondPitch, float firstMin, float firstMax, float secondMin, float secondMax, int callsBetweenSounds) { - System.out.printf("%f, %f, %f, %f, %f, %f, %d%n", firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, callsBetweenSounds); + private OptionalLong crackSeed0(float firstPitch, float secondPitch, float firstMin, float firstMax, float secondMin, float secondMax, int ticksBetweenSounds) { + System.out.println(firstPitch + ", " + secondPitch + ", " + firstMin + ", " + firstMax + ", " + secondMin + ", " + secondMax + ", " + ticksBetweenSounds); - if (!(80 <= callsBetweenSounds && callsBetweenSounds - 80 < LATTICES.length)) { + if (!(80 <= ticksBetweenSounds && ticksBetweenSounds - 80 < LATTICES.length)) { return OptionalLong.empty(); } - BigMatrix lattice = LATTICES[callsBetweenSounds - 80]; - BigMatrix inverseLattice = INVERSE_LATTICES[callsBetweenSounds - 80]; - BigVector vector = OFFSETS[callsBetweenSounds - 80]; + BigMatrix lattice = LATTICES[ticksBetweenSounds - 80]; + BigMatrix inverseLattice = INVERSE_LATTICES[ticksBetweenSounds - 80]; + BigVector offset = OFFSETS[ticksBetweenSounds - 80]; firstMax = Math.nextUp(firstMax); secondMax = Math.nextUp(secondMax); @@ -345,13 +342,13 @@ private OptionalLong crackSeed0(float firstPitch, float secondPitch, float first .withUpperBound(2, secondCombinationModMax) .build(); - System.out.printf("%s, %s, %d, %d, %d, %d, %s, %s%n", lattice, vector, firstCombinationModMin, firstCombinationModMax, secondCombinationModMin, secondCombinationModMax, inverseLattice, inverseLattice.multiply(vector)); + System.out.printf("%s, %s, %d, %d, %d, %d, %s, %s%n", lattice, offset, firstCombinationModMin, firstCombinationModMax, secondCombinationModMin, secondCombinationModMax, inverseLattice, inverseLattice.multiply(offset)); - return EnumerateRt.enumerate(lattice, vector, optimize, inverseLattice, inverseLattice.multiply(vector)).mapToLong(vec -> vec.get(0).getNumerator().longValue() & ((1L << 48) - 1)).flatMap(seed -> { + return EnumerateRt.enumerate(lattice, offset, optimize, inverseLattice, inverseLattice.multiply(offset)).mapToLong(vec -> vec.get(0).getNumerator().longValue() & ((1L << 48) - 1)).flatMap(seed -> { System.out.println(seed); JRand rand = JRand.ofInternalSeed(seed); float simulatedFirstPitch = (rand.nextFloat() - rand.nextFloat()) * 0.2f + 1.0f; - rand.advance(callsBetweenSounds); + rand.advance(ticksBetweenSounds * 2L); float simulatedSecondPitch = (rand.nextFloat() - rand.nextFloat()) * 0.2f + 1.0f; if (simulatedFirstPitch == firstPitch && simulatedSecondPitch == secondPitch) { return LongStream.of(rand.getSeed()); diff --git a/src/main/resources/villager_lattice_data.nbt b/src/main/resources/villager_lattice_data.nbt index 052149fd075b5f7db8c8d6592bdd1f391a5ac07c..c29cf23750163eabfc47173207db9172e52c14ec 100644 GIT binary patch delta 20195 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 From c4194147334429117b1d4b5cc03311af54596cc3 Mon Sep 17 00:00:00 2001 From: RTTV Date: Wed, 19 Jun 2024 18:55:33 -0400 Subject: [PATCH 11/78] IT WORKS!! btw i still have villager adjustment shenanigans --- .../clientcommands/ClientCommands.java | 32 - .../command/VillagerCommand.java | 47 +- .../features/VillagerCracker.java | 18 +- .../features/VillagerRngSimulator.java | 85 +- .../commands/villager/VillagerMixin.java | 2 - .../rngevents/ClientPacketListenerMixin.java | 25 + .../mixin/rngevents/LivingEntityMixin.java | 8 - .../mixin/rngevents/MerchantScreenMixin.java | 40 + .../util/EstimatedServerTick.java | 2 +- .../assets/clientcommands/lang/en_us.json | 11 +- src/main/resources/mixins.clientcommands.json | 1 + src/main/resources/villager_lattice_data.csv | 1002 ----------------- 12 files changed, 168 insertions(+), 1105 deletions(-) create mode 100644 src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java delete mode 100644 src/main/resources/villager_lattice_data.csv diff --git a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java index decb2b2e4..708287b61 100644 --- a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java +++ b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java @@ -68,38 +68,6 @@ public class ClientCommands implements ClientModInitializer { @Override public void onInitializeClient() { - try { - String file = new String(ClientCommands.class.getResourceAsStream("/villager_lattice_data.csv").readAllBytes()); - file = file.substring(file.indexOf('\n') + 1); - CompoundTag root = new CompoundTag(); - ListTag lattice = new ListTag(); - ListTag lattice_inverse = new ListTag(); - ListTag offset = new ListTag(); - for (String line : file.split("\n")) { - String[] values = line.split(","); - long[] longs = new long[9]; - for (int i = 0; i < 9; i++) { - longs[i] = Long.parseLong(values[i]); - } - lattice.add(new LongArrayTag(longs)); - long[] inverse = new long[9]; - for (int i = 0; i < 9; i++) { - inverse[i] = Long.parseLong(values[i + 9]); - } - lattice_inverse.add(new LongArrayTag(inverse)); - long[] offsets = new long[2]; - for (int i = 0; i < 2; i++) { - offsets[i] = Long.parseLong(values[i + 18]); - } - offset.add(new LongArrayTag(offsets)); - } - root.put("lattices", lattice); - root.put("lattice_inverses", lattice_inverse); - root.put("offsets", offset); - NbtIo.write(root, Path.of("villager_lattice_data.nbt")); - } catch (IOException e) { - throw new RuntimeException(e); - } // Config configDir = FabricLoader.getInstance().getConfigDir().resolve("clientcommands"); try { diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index a0a41a072..79f4cc4d5 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -15,7 +15,10 @@ import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.ChatFormatting; import net.minecraft.advancements.critereon.MinMaxBounds; +import net.minecraft.client.Minecraft; import net.minecraft.commands.CommandBuildContext; +import net.minecraft.core.BlockPos; +import net.minecraft.core.GlobalPos; import net.minecraft.network.chat.Component; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; @@ -28,10 +31,12 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.function.Predicate; import java.util.stream.Collectors; import static com.mojang.brigadier.arguments.IntegerArgumentType.*; +import static dev.xpple.clientarguments.arguments.CBlockPosArgument.*; import static dev.xpple.clientarguments.arguments.CEntityArgument.*; import static dev.xpple.clientarguments.arguments.CItemPredicateArgument.*; import static net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument.*; @@ -70,6 +75,9 @@ public static void register(CommandDispatcher dispatc .executes(ctx -> setVillagerTarget(null)) .then(argument("entity", entity()) .executes(ctx -> setVillagerTarget(getEntity(ctx, "entity"))))) + .then(literal("clock") + .then(argument("pos", blockPos()) + .executes(ctx -> setClockPos(getBlockPos(ctx, "pos"))))) .then(literal("brute-force") .executes(ctx -> bruteForce()))); } @@ -120,14 +128,24 @@ private static int setVillagerTarget(@Nullable Entity target) throws CommandSynt VillagerCracker.setTargetVillager((Villager) target); if (target == null) { - ClientCommandHelper.sendFeedback("commands.cvillager.targetCleared"); + ClientCommandHelper.sendFeedback("commands.cvillager.target.cleared"); } else { - ClientCommandHelper.sendFeedback("commands.cvillager.targetSet"); + ClientCommandHelper.sendFeedback("commands.cvillager.target.set"); } return Command.SINGLE_SUCCESS; } + private static int setClockPos(BlockPos pos) { + VillagerCracker.setClockPos(pos == null ? null : new GlobalPos(Minecraft.getInstance().player.level().dimension(), pos)); + if (pos == null) { + ClientCommandHelper.sendFeedback("commands.cvillager.clock.cleared"); + } else { + ClientCommandHelper.sendFeedback("commands.cvillager.clock.set"); + } + return Command.SINGLE_SUCCESS; + } + private static int bruteForce() throws CommandSyntaxException { Villager targetVillager = VillagerCracker.getVillager(); @@ -140,7 +158,7 @@ private static int bruteForce() throws CommandSyntaxException { } VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(1, new VillagerTrades.ItemListing[0]); - int adjustment = 3 + Configs.villagerAdjustment - (iVillager.clientcommands_getCrackedRandom().currentCorrectionMs() + 40) / 50; + int adjustment = 2 + Configs.villagerAdjustment; Pair pair = iVillager.clientcommands_bruteForceOffers(listings, profession, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))).mapFirst(x -> x + adjustment); int ticks = pair.getFirst(); Offer offer = pair.getSecond(); @@ -159,6 +177,8 @@ private static int bruteForce() throws CommandSyntaxException { price = VillagerCommand.displayText(offer.first()) + " + " + VillagerCommand.displayText(offer.second()); } ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", VillagerCommand.displayText(offer.result()), price, ticks).withStyle(ChatFormatting.GREEN)); + VillagerCracker.targetOffer = offer; + System.out.println(offer); iVillager.clientcommands_getCrackedRandom().setCallsUntilOpenGui(ticks, offer.result()); } @@ -182,7 +202,26 @@ public String toString() { } } - public record Offer(ItemStack first, @Nullable ItemStack second, ItemStack result) {} + public record Offer(ItemStack first, @Nullable ItemStack second, ItemStack result) { + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Offer other)) { + return false; + } + return ItemStack.isSameItemSameComponents(this.first, other.first) && this.first.getCount() == other.first.getCount() + && (this.second == other.second || this.second != null && other.second != null && ItemStack.isSameItemSameComponents(this.second, other.second) && this.second.getCount() == other.second.getCount()) + && ItemStack.isSameItemSameComponents(this.result, other.result) && this.result.getCount() == other.result.getCount(); + } + + @Override + public String toString() { + if (second == null) { + return String.format("%s = %s", displayText(first), displayText(result)); + } else { + return String.format("%s + %s = %s", displayText(first), displayText(second), displayText(result)); + } + } + } public static String displayText(ItemStack stack) { String quantityPrefix; diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 57107d23d..780386485 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -1,11 +1,10 @@ package net.earthcomputer.clientcommands.features; -import net.earthcomputer.clientcommands.command.ClientCommandHelper; +import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.interfaces.IVillager; import net.minecraft.client.Minecraft; -import net.minecraft.network.chat.Component; +import net.minecraft.core.GlobalPos; import net.minecraft.network.protocol.game.ClientboundSoundPacket; -import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; import org.jetbrains.annotations.Nullable; @@ -21,6 +20,10 @@ public class VillagerCracker { private static UUID villagerUuid = null; @Nullable private static WeakReference cachedVillager = null; + @Nullable + private static GlobalPos clockPos = null; + @Nullable + public static VillagerCommand.Offer targetOffer = null; @Nullable public static Villager getVillager() { @@ -45,6 +48,11 @@ public static Villager getVillager() { return null; } + @Nullable + public static GlobalPos getClockPos() { + return clockPos; + } + public static void setTargetVillager(@Nullable Villager villager) { Villager oldVillager = getVillager(); if (oldVillager != null) { @@ -55,6 +63,10 @@ public static void setTargetVillager(@Nullable Villager villager) { VillagerCracker.villagerUuid = villager == null ? null : villager.getUUID(); } + public static void setClockPos(@Nullable GlobalPos pos) { + VillagerCracker.clockPos = pos; + } + public static void onSoundEventPlayed(ClientboundSoundPacket packet) { Villager targetVillager = getVillager(); if (targetVillager == null) { diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 0d5ada909..b90920210 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -5,16 +5,15 @@ import com.seedfinding.latticg.math.component.BigVector; import com.seedfinding.latticg.math.lattice.enumerate.EnumerateRt; import com.seedfinding.latticg.math.optimize.Optimize; -import com.seedfinding.mcseed.lcg.LCG; import com.seedfinding.mcseed.rand.JRand; -import com.seedfinding.mcseed.rand.Rand; import net.earthcomputer.clientcommands.command.ClientCommandHelper; -import net.earthcomputer.clientcommands.command.PingCommand; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.minecraft.ChatFormatting; -import net.minecraft.nbt.*; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.NbtIo; +import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; -import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.item.ItemStack; @@ -24,12 +23,9 @@ import java.io.DataInputStream; import java.io.IOException; -import java.math.BigInteger; -import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.OptionalLong; import java.util.function.Predicate; import java.util.stream.LongStream; @@ -166,10 +162,6 @@ public void simulateServerAiStep() { totalCalls += 1; } - public int currentCorrectionMs() { - return PingCommand.getLocalPing() / 2; - } - public void updateProgressBar() { ClientCommandHelper.updateOverlayProgressBar(Math.min(callsInBruteForce, totalCalls - callsAtStartOfBruteForce), callsInBruteForce, 50, 60); } @@ -266,15 +258,17 @@ public void onAmbientSoundPlayed(float pitch) { secondPitch = pitch; ambientSoundTime = -80; madeSound = true; - OptionalLong seed = crackSeed(); - if (seed.isPresent()) { - random = new LegacyRandomSource(seed.getAsLong() ^ 0x5deece66dL); - // simulate a tick to advance it by one - simulateTick(); - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.crackSuccess", Long.toHexString(seed.getAsLong())).withStyle(ChatFormatting.GREEN), 100); + long[] seeds = crackSeed(); + if (seeds.length == 1) { + random = new LegacyRandomSource(seeds[0] ^ 0x5deece66dL); + random.nextInt(100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.crack.success", Long.toHexString(seeds[0])).withStyle(ChatFormatting.GREEN), 100); } else { - reset(); - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.crackFailed").withStyle(ChatFormatting.RED), 100); + totalAmbientSounds = 1; + firstPitch = pitch; + secondPitch = Float.NaN; + ambientSoundTime = -80; + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.crack.failed", seeds.length).withStyle(ChatFormatting.RED), 100); } return; } @@ -285,41 +279,28 @@ public void onAmbientSoundPlayed(float pitch) { } } - public OptionalLong crackSeed() { - float first = (firstPitch - 1.0f) / 0.2f; - float second = (secondPitch - 1.0f) / 0.2f; - float firstMin = Math.max(-1.0f + 0x1.0p-24f, first - VillagerCracker.MAX_ERROR); - float firstMax = Math.min(1.0f - 0x1.0p-24f, first + VillagerCracker.MAX_ERROR); - float secondMin = Math.max(-1.0f + 0x1.0p-24f, second - VillagerCracker.MAX_ERROR); - float secondMax = Math.min(1.0f - 0x1.0p-24f, second + VillagerCracker.MAX_ERROR); - OptionalLong seed2m = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, ticksBetweenSounds - 1); - OptionalLong seed = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, ticksBetweenSounds); - OptionalLong seed2p = crackSeed0(firstPitch, secondPitch, firstMin, firstMax, secondMin, secondMax, ticksBetweenSounds + 1); - System.out.println("Seed 2M: " + seed2m); - System.out.println("Seed: " + seed); - System.out.println("Seed 2P: " + seed2p); - return seed; - } - - private OptionalLong crackSeed0(float firstPitch, float secondPitch, float firstMin, float firstMax, float secondMin, float secondMax, int ticksBetweenSounds) { - System.out.println(firstPitch + ", " + secondPitch + ", " + firstMin + ", " + firstMax + ", " + secondMin + ", " + secondMax + ", " + ticksBetweenSounds); - + public long[] crackSeed() { if (!(80 <= ticksBetweenSounds && ticksBetweenSounds - 80 < LATTICES.length)) { - return OptionalLong.empty(); + return new long[0]; } - + BigMatrix lattice = LATTICES[ticksBetweenSounds - 80]; BigMatrix inverseLattice = INVERSE_LATTICES[ticksBetweenSounds - 80]; BigVector offset = OFFSETS[ticksBetweenSounds - 80]; - + + float firstMin = Math.max(-1.0f + 0x1.0p-24f, (firstPitch - 1.0f) / 0.2f - VillagerCracker.MAX_ERROR); + float firstMax = Math.min(1.0f - 0x1.0p-24f, (firstPitch - 1.0f) / 0.2f + VillagerCracker.MAX_ERROR); + float secondMin = Math.max(-1.0f + 0x1.0p-24f, (secondPitch - 1.0f) / 0.2f - VillagerCracker.MAX_ERROR); + float secondMax = Math.min(1.0f - 0x1.0p-24f, (secondPitch - 1.0f) / 0.2f + VillagerCracker.MAX_ERROR); + firstMax = Math.nextUp(firstMax); secondMax = Math.nextUp(secondMax); - + long firstMinLong = (long) Math.ceil(firstMin * 0x1.0p24f); long firstMaxLong = (long) Math.ceil(firstMax * 0x1.0p24f) - 1; long secondMinLong = (long) Math.ceil(secondMin * 0x1.0p24f); long secondMaxLong = (long) Math.ceil(secondMax * 0x1.0p24f) - 1; - + long firstMinSeedDiff = (firstMinLong << 24) - 0xFFFFFF; long firstMaxSeedDiff = (firstMaxLong << 24) + 0xFFFFFF; long secondMinSeedDiff = (secondMinLong << 24) - 0xFFFFFF; @@ -342,20 +323,26 @@ private OptionalLong crackSeed0(float firstPitch, float secondPitch, float first .withUpperBound(2, secondCombinationModMax) .build(); - System.out.printf("%s, %s, %d, %d, %d, %d, %s, %s%n", lattice, offset, firstCombinationModMin, firstCombinationModMax, secondCombinationModMin, secondCombinationModMax, inverseLattice, inverseLattice.multiply(offset)); - return EnumerateRt.enumerate(lattice, offset, optimize, inverseLattice, inverseLattice.multiply(offset)).mapToLong(vec -> vec.get(0).getNumerator().longValue() & ((1L << 48) - 1)).flatMap(seed -> { - System.out.println(seed); JRand rand = JRand.ofInternalSeed(seed); float simulatedFirstPitch = (rand.nextFloat() - rand.nextFloat()) * 0.2f + 1.0f; - rand.advance(ticksBetweenSounds * 2L); + rand.nextInt(100); + for (int i = -80; i < ticksBetweenSounds - 80 - 1; i++) { + if (rand.nextInt(1000) < i) { + return LongStream.empty(); + } + rand.nextInt(100); + } + if (rand.nextInt(1000) >= ticksBetweenSounds) { + return LongStream.empty(); + } float simulatedSecondPitch = (rand.nextFloat() - rand.nextFloat()) * 0.2f + 1.0f; if (simulatedFirstPitch == firstPitch && simulatedSecondPitch == secondPitch) { return LongStream.of(rand.getSeed()); } else { return LongStream.empty(); } - }).findAny(); + }).toArray(); } public enum CrackedState { diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index 8cd483aa7..1dfc8b481 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -61,8 +61,6 @@ public void clientcommands_onServerTick() { if (result.consumesAction() && result.shouldSwing()) { minecraft.player.swing(InteractionHand.MAIN_HAND); } - minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.success", rng.currentCorrectionMs()).withStyle(ChatFormatting.GREEN), 100); } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java index 4f8425d09..d8a369a77 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java @@ -3,10 +3,16 @@ import com.mojang.brigadier.StringReader; import net.earthcomputer.clientcommands.features.PlayerRandCracker; import net.earthcomputer.clientcommands.features.VillagerCracker; +import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.core.GlobalPos; +import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; +import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.resources.ResourceKey; import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @@ -35,4 +41,23 @@ private void onHandleSoundEvent(ClientboundSoundPacket packet, CallbackInfo ci) VillagerCracker.onSoundEventPlayed(packet); } } + + @Inject(method = "handleChunkBlocksUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void onHandleChunkBlocksUpdate(ClientboundSectionBlocksUpdatePacket packet, CallbackInfo ci) { + if (Minecraft.getInstance().level != null) { + ResourceKey key = Minecraft.getInstance().level.dimension(); + packet.runUpdates((pos, state) -> { + if (new GlobalPos(key, pos).equals(VillagerCracker.getClockPos())) { + VillagerCracker.onServerTick(); + } + }); + } + } + + @Inject(method = "handleBlockUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackInfo ci) { + if (Minecraft.getInstance().level != null && new GlobalPos(Minecraft.getInstance().level.dimension(), packet.getPos()).equals(VillagerCracker.getClockPos())) { + VillagerCracker.onServerTick(); + } + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java index ab420840a..003e80f41 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java @@ -130,12 +130,4 @@ private void testSoulSpeed(CallbackInfo ci) { private boolean isThePlayer() { return (Object) this instanceof LocalPlayer; } - - @Inject(method = "makeSound", at = @At("TAIL")) - private void onMakeSound(SoundEvent sound, CallbackInfo ci) { - Villager targetVillager = VillagerCracker.getVillager(); - if (!level().isClientSide && targetVillager != null && targetVillager.getUUID().equals(uuid)) { - System.out.println("(Server) Post-call seed: 0x" + Long.toHexString(((LegacyRandomSource) random).seed.get())); - } - } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java new file mode 100644 index 000000000..47baba04b --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java @@ -0,0 +1,40 @@ +package net.earthcomputer.clientcommands.mixin.rngevents; + +import net.earthcomputer.clientcommands.Configs; +import net.earthcomputer.clientcommands.command.ClientCommandHelper; +import net.earthcomputer.clientcommands.command.VillagerCommand; +import net.earthcomputer.clientcommands.features.VillagerCracker; +import net.minecraft.ChatFormatting; +import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; +import net.minecraft.client.gui.screens.inventory.MerchantScreen; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.inventory.MerchantMenu; +import net.minecraft.world.item.trading.ItemCost; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(MerchantScreen.class) +public abstract class MerchantScreenMixin extends AbstractContainerScreen { + public MerchantScreenMixin(MerchantMenu menu, Inventory playerInventory, Component title) { + super(menu, playerInventory, title); + } + + @Inject(method = "render", at = @At("HEAD")) + private void onRender(CallbackInfo ci) { + if (VillagerCracker.targetOffer != null) { + if (menu.getOffers().stream().map(offer -> new VillagerCommand.Offer(offer.getBaseCostA(), offer.getItemCostB().map(ItemCost::itemStack).orElse(null), offer.getResult())).peek(offer -> System.out.println("offer: " + offer)).anyMatch(offer -> offer.toString().equals(VillagerCracker.targetOffer.toString()))) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.success", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.GREEN), 100); + minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); + } else { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.RED), 100); + minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); + } + VillagerCracker.targetOffer = null; + } + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java b/src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java index a91506eb4..56e0743df 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java @@ -43,6 +43,6 @@ public static void onSetTime(long gameTime) { } }, "Estimated Server Tick Thread").start(); - MoreClientEvents.ESTIMATED_SERVER_TICK.register(VillagerCracker::onServerTick); +// MoreClientEvents.ESTIMATED_SERVER_TICK.register(VillagerCracker::onServerTick); } } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index db2c114a3..b555b2c28 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -244,8 +244,10 @@ "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %d calls.", "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls.", - "commands.cvillager.crackFailed": "Failed to crack villager seed, re-cracking.", - "commands.cvillager.crackSuccess": "Villager RNG cracked: %d", + "commands.cvillager.clock.cleared": "Clock cleared", + "commands.cvillager.clock.set": "Clock set", + "commands.cvillager.crack.failed": "Failed to crack villager seed (found %d seeds), re-cracking.", + "commands.cvillager.crack.success": "Villager RNG cracked: %d", "commands.cvillager.goalAdded": "Added goal successfully.", "commands.cvillager.inSync": "Your villager's RNG is %d%% synced", "commands.cvillager.listGoals.noGoals": "There are no villager goals.", @@ -257,8 +259,9 @@ "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals.", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", "commands.cvillager.success": "Got the correct trade with correction of %dms", - "commands.cvillager.targetCleared": "Target entity cleared", - "commands.cvillager.targetSet": "Target entity set", + "commands.cvillager.failure": "Got the incorrect trade with correction of %dms", + "commands.cvillager.target.cleared": "Target entity cleared", + "commands.cvillager.target.set": "Target entity set", "commands.cwe.playerNotFound": "Player not found", diff --git a/src/main/resources/mixins.clientcommands.json b/src/main/resources/mixins.clientcommands.json index 2a335f746..02dde2796 100644 --- a/src/main/resources/mixins.clientcommands.json +++ b/src/main/resources/mixins.clientcommands.json @@ -70,6 +70,7 @@ "dataqueryhandler.ClientPacketListenerMixin", "events.ClientPacketListenerMixin", "lengthextender.ChatScreenMixin", + "rngevents.MerchantScreenMixin", "scrambletitle.MinecraftMixin", "serverbrand.ClientCommonPacketListenerImplMixin", "suggestionshook.ClientPacketListenerMixin" diff --git a/src/main/resources/villager_lattice_data.csv b/src/main/resources/villager_lattice_data.csv deleted file mode 100644 index fb2b4bd6b..000000000 --- a/src/main/resources/villager_lattice_data.csv +++ /dev/null @@ -1,1002 +0,0 @@ -l00,l01,l02,l10,l11,l12,l20,l21,l22,li00,li01,li02,li10,li11,li12,li20,li21,li22,o1,o2 --3476554084835,28255265391812,-42113478785852,15148148,25330448,25330448,-27574892,28215696,28215696,0,7053924,-6332612,4,4474174,1953561,-4,2419549,1833476,281197612767569,172263588355769 -12408218695821,-33144088090201,11237077975074,-7074252,-21222756,81737864,5975924,17927772,90107144,12,-11325962,8777495,-4,-3733608,3885657,0,1493981,1768563,281197612767569,201206084637665 -1602613649463,-12026233802062,70368744177664,-22952740,-11156792,0,8610812,-44867448,0,0,-11216862,2789198,0,-2152703,-5738185,4,-112445,-1044196,281197612767569,161003732889929 --12329864442980,16801320061067,-70368744177664,25640560,20354604,0,17921136,-29684308,0,0,7421077,5088651,0,4480284,-6410140,-4,-230588,-2422115,281197612767569,249134577176817 -32622245201238,37746498976426,7745155264947,-590504,590504,42179276,26476568,-26476568,15473964,4,-2803635,5640098,4,1064856,-4904721,0,6619142,147626,281197612767569,836491779289 -23509883930646,-16485223278971,-46858860247018,18483288,26453524,18483288,19502296,-33002540,19502296,4,6636331,3321364,0,4875574,-4620822,-4,1614304,3292017,281197612767569,70648974266113 -6895670548764,-35890391433844,-2246799087477,-2263952,-11319760,-197781972,4560624,22803120,-98893748,20,-12791792,25128483,-4,-2386329,4863402,0,-1140156,-565988,281197612767569,230155805389161 -19872089964001,50496654213663,-12819105457601,-22195324,22195324,-15102724,2233988,-2233988,-49206788,4,-8929447,1698598,4,3372250,-2077083,0,-558497,-5548831,281197612767569,84128279961105 -17174215164515,-53194529013149,-7169935869527,2825612,2825612,51192484,-21444756,-21444756,9941060,4,2424967,-9602632,-4,60298,-3195489,0,5361189,706403,281197612767569,272644608294649 -20352156869675,21101248121487,28915339186502,-18119508,-18936260,37055768,-24931220,36082428,-11151208,4,-4542642,-4723231,4,-1754840,4540711,4,4477965,10834,281197612767569,269324635098657 -8728276822537,-61640467355127,-18950317931798,-10001372,-10001372,43590568,-20691452,-20691452,-22391704,4,-3510527,-10219282,-4,-2087399,-678360,0,5172863,-2500343,281197612767569,87559348770185 -14749827991492,-55618916186172,-18090665508531,-18575600,-18575600,-25808588,10136848,10136848,-46527820,4,-9845313,3905856,-4,-1786642,2546291,0,-2534212,-4643900,281197612767569,47732792454961 --18192233826070,-15513661186801,-52176510351594,22477736,18765884,-22477736,18664168,-34507492,-18664168,-4,5367905,4717472,0,4666042,-5619434,-4,-3258968,26001,281197612767569,166573851575577 --18548560215540,30996920595025,39371823582639,-34383824,5072196,-5072196,10831152,31147268,-31147268,0,-7786817,1268049,4,-537507,5143746,4,-3245295,-3452210,281197612767569,28772858958145 -6635313999154,-34403094847883,-35965649329781,-28201784,19596756,-19596756,-18696824,-26931020,26931020,0,-6732755,-4899189,-4,1754144,-4065463,-4,-2920062,2984983,281197612767569,84219543494057 -679467483691,-70368744177664,-26173736256862,17628332,0,16327304,3186860,0,-60917112,0,15229278,4081826,-4,-149288,1678633,0,796715,-4407083,281197612767569,54989266732113 --17723997367094,52644746810570,-17284716852249,-15668440,-15668440,-18041956,-6751384,-6751384,64083708,-4,-11571099,-4336580,4,-4449828,-173909,0,-1687846,3917110,281197612767569,11537315573561 -22094520762725,48274223414939,29636162462236,-5385836,5385836,39753840,-27544876,27544876,-5734544,4,-3883667,-6250894,4,-2450031,3687566,0,6886219,-1346459,281197612767569,64617847461985 --33507228868266,-36861515309398,-15627295282179,-3642024,3642024,44047348,25676440,-25676440,-1394604,-4,-1242903,5566168,-4,-1591554,-5445669,0,6419110,910506,281197612767569,24474283264457 --5503785216671,-28825883512764,-70368744177664,-3886716,-42323696,0,26397188,-2231536,0,0,-557884,10580924,0,-6599297,-971679,-4,2746973,-429532,281197612767569,126472728714609 -16928453150971,16724763738115,36715527288578,29022188,-32599028,3576840,-15795892,-21051796,36847688,4,4935418,-4464739,4,-4276504,-3570529,4,-327531,3685018,281197612767569,232501607923033 --25573063045165,44795681132499,15083705793408,10654540,10654540,-36311552,20919692,20919692,34377216,-4,4349958,6349803,4,4244346,2728085,0,-5229923,2663635,281197612767569,253370774610817 -24744389011837,20879966153990,-8270689147546,-15396364,30792728,-17351272,-6032172,12064344,66329560,8,-5274854,-382332,4,5653768,1977743,0,-1508043,3849091,281197612767569,223942364092905 --19050704186021,51318039991643,5496886509440,-11826836,-11826836,40959488,-16408468,-16408468,-38371840,-4,-6675450,-7698629,4,-2917510,-2541243,0,4102117,-2956709,281197612767569,215005482154641 --12852700529477,-18957942059756,8424651188627,-2382100,9528400,175897164,5242316,-20969264,85551148,-16,-5134435,12132239,-4,4063338,-7960513,0,1310579,595525,281197612767569,245876592668537 --19801117297829,-50567626879835,-16090944486380,-22675092,22675092,22167632,9941804,-9941804,39934288,-4,-7742625,2686210,-4,2240947,-2855698,0,2485451,5668773,281197612767569,3981803975329 --23853307764859,46515436412805,8135371541155,18074132,18074132,-16695668,-11756940,-11756940,-51433172,-4,8159835,-3281450,4,4698458,-892467,0,-2939235,-4518533,281197612767569,270412568055305 --33873695926765,-36495048250899,7503894385005,15248460,-15248460,-26480204,19822796,-19822796,39413044,-4,4581696,3839841,-4,-5271565,-2780210,0,-4955699,3812115,281197612767569,169123345062833 -19681637176475,-20773331307312,50687107001189,7439980,-33516736,-7439980,-30447924,-14164672,30447924,4,303620,-6584669,0,-7611981,-1859995,4,-3237548,1794515,281197612767569,105858529625497 -32090285076227,-38278459101437,4250048274206,20336652,20336652,-39959432,-13582004,-13582004,-28675848,4,4104775,-5127112,-4,3064187,-4862746,0,-3395501,-5084163,281197612767569,30325612234177 -32873540801129,-37495203376535,16903558321289,-14580316,-14580316,-34795996,11024900,11024900,-50909564,4,-6119565,5510764,-4,-6607826,3188235,0,-2756225,-3645079,281197612767569,40235896284713 -19179198791735,-51189545385929,-13622850413044,-23706404,-23706404,-4274128,-6908196,-6908196,46247984,4,-8745085,370044,-4,-2816911,-1438576,0,-1727049,5926601,281197612767569,277256898035921 --2745204197029,28056858011329,42311886166335,23009644,17987332,-17987332,-18170036,34727588,-34727588,0,8681897,-4496833,4,3070052,3283427,4,-1472457,-2468984,281197612767569,236533133459385 --21462494033268,48906250144396,-53992773633,21723696,21723696,15844348,-6597328,-6597328,47016380,-4,8167826,-2757121,4,3586269,-1203966,0,1649332,5430924,281197612767569,185701192228065 --27783654384506,42585089793158,19328056851003,23370264,23370264,-14115604,15359320,15359320,38899596,-4,4830543,3740354,4,4894356,-211453,0,-3839830,5842566,281197612767569,214329415918153 --8140355554195,62228388623469,4706998051577,11042228,11042228,50563044,8988212,8988212,-60805532,-4,13593172,10993805,4,1608211,1646956,0,2247053,-2760557,281197612767569,216453714946545 --3179689164013,22396351671217,-6345024530712,-15769524,-5256508,47430560,-3925332,-1308444,-202385248,-4,-16132849,-3655454,12,-2197765,-891278,0,327111,-1314127,281197612767569,100794912120281 -17741298711947,-596450670124,-9117733830418,2255404,-9021616,248482744,-2581396,10325584,214803000,16,-120698,818774,4,-13455362,15734865,0,645349,563851,281197612767569,54581474703361 --8111320699039,62257423478625,18390756168318,20257156,20257156,-20934152,-9436188,-9436188,-45828808,-4,9520011,-5953818,4,1937191,720280,0,-2359047,-5064289,281197612767569,145930115875433 --32988701444515,-37380042733149,17238095250666,4244852,-4244852,-44160088,-23719820,23719820,-18476632,-4,1001058,-6124449,-4,-3618100,4915573,0,-5929955,-1061213,281197612767569,88765010876177 --23503147051142,9327188155085,46865597126522,16266728,-32073932,16266728,25817640,18308948,25817640,-4,2192926,5879339,0,-6454410,4066682,4,2384311,2139144,281197612767569,238248515936249 -12826417145930,28771163515867,841208670912,20855080,-10427540,-8148224,-3044952,1522476,-106784000,4,10919552,-801713,8,-4856896,433630,0,-380619,-2606885,281197612767569,237039169427233 --17348149709099,-53020594468565,-7653614457209,23521108,-23521108,-17973732,-7288908,7288908,-42297796,-4,8165702,-2746093,-4,-2408747,1747340,0,-1822227,-5880277,281197612767569,19700769916553 --21178028960358,19026795343725,30163919873581,-30036376,-35624524,5588148,20416872,-13269196,33686068,-4,-3699046,4195399,4,-4722471,-2798362,4,381747,4710732,281197612767569,175053049989169 -13374320705058,-28261601907977,56994423472606,25637000,520156,-25637000,-3848504,43838908,3848504,4,9263126,2468769,0,962126,6409250,4,-1696601,2598808,281197612767569,239427853338137 --8404370651775,32454674210874,-37914069966790,-13962748,-38184728,-38184728,-24172092,14531176,14531176,0,-3632794,-9546182,4,-3689805,740620,-4,-2353218,2750067,281197612767569,10574924298817 --15056862021332,40255020135000,15230839426201,9155760,18311520,60272228,10246448,20492896,-55519548,-8,9048991,7628955,4,2415448,3719551,0,2561612,-2288940,281197612767569,2014714097321 --5785566913775,64583177263889,-8462600387277,15337540,15337540,36890828,-9332668,-9332668,50960588,-4,11412091,-8925562,4,1328056,-297145,0,2333167,3834385,281197612767569,276792004377937 -21455739128394,16596470215339,32316534833931,-31080152,31964844,-884692,10905960,25009292,-35915252,4,-4989005,3722092,4,3989808,3500919,4,1263318,-4269119,281197612767569,134145913458745 --12362671005334,14624424335071,-70368744177664,20618664,34865020,0,-25726936,11103036,0,0,2775759,-8716255,0,6431734,5154666,-4,849022,2602579,281197612767569,38206713487713 --3621173379697,-9761231300379,-70368744177664,-31991236,-4509804,0,11229276,-33611020,0,0,-8402755,1127451,0,-2807319,-7997809,-4,821824,1051401,281197612767569,210403630463689 -20435175485779,4355960904628,49933568691885,-12052148,37822160,12052148,30156492,-1218352,-30156492,4,-250551,6523126,0,7539123,3013037,4,-555139,-2932414,281197612767569,133260978091633 --8472462464277,-30201394404272,40167349773392,32481196,6967616,6967616,-947444,-34866368,-34866368,0,8716592,1741904,-4,-1184689,-4844894,4,947828,-3275405,281197612767569,32902074564185 -26173939142337,44194805035327,-11790061081703,10163972,-10163972,42412644,-25675836,25675836,3632420,4,1645808,-6233537,4,737703,4369624,0,6418959,2540993,281197612767569,4324181822593 --7832741307919,-14748511539107,-70368744177664,-16153660,37858676,0,18523684,26286164,0,0,-6571541,9464669,0,4630921,4038415,-4,-239112,-1899919,281197612767569,167945336417001 --10156086704332,-16974261408117,-70368744177664,31313104,12201516,0,-10493744,31867180,0,0,7966795,-3050379,0,2623436,7828276,-4,-1782643,-1448076,281197612767569,238788538725265 -23851175764897,46517568412767,-11109912840107,18475652,-18475652,37940564,9943332,-9943332,-40520588,4,7089045,5540954,4,-3041102,-3944187,0,2485833,-4618913,281197612767569,241295234535545 -5659191690264,64709552487400,15231484533969,1421408,-1421408,-67760316,16526944,-16526944,4241540,4,1869431,15500808,4,809046,-1439271,0,-4131736,355352,281197612767569,25287740160929 -30793090984886,39575653192778,16247530820149,-15198504,15198504,30921940,-10177000,10177000,-53374156,4,-8091903,-3470354,4,5251636,4260131,0,2544250,-3799626,281197612767569,7070136893193 --6192811350418,-35404546597997,-34964197579667,15081912,-26951092,26951092,-30204232,-20677940,20677940,0,5169485,-6737773,-4,-4206844,-1280483,-4,3344214,2489995,281197612767569,257153099199665 -34843136834195,-13292841254721,-35525607343469,-1622452,-37411076,-1622452,-29511252,13468636,-29511252,4,-3093596,-4645117,0,-7377813,405613,-4,-273563,-4707652,281197612767569,224597960541849 -19985804772941,20639039344121,-50382939404723,-5028556,-40029212,-5028556,28079092,-381020,28079092,4,1990687,7533792,0,-7019773,-1257139,-4,-2085942,2473511,281197612767569,186890417499841 -30273884605767,40094859571897,19575823284985,-3524324,3524324,-53286940,20771516,-20771516,-5405116,4,674668,7835595,4,2025947,-5486140,0,-5192879,-881081,281197612767569,32475994847017 -34229814023149,-1460733208451,36138930154515,22739892,24628724,-22739892,18494900,-29480972,-18494900,4,3881080,3044103,0,4623725,-5684973,4,-3489163,-3113078,281197612767569,270972026288593 --3162183131148,-5517780108997,-70368744177664,-5230640,36149484,0,28927056,15333068,0,0,-3833267,9037371,0,7231764,1307660,-4,-394803,-508652,281197612767569,280712319508665 -9582106252206,32040319168840,713163497639,3790520,-15162080,-137296228,5432888,-21731552,100246108,16,11466083,15590025,4,-3398861,-4683508,0,-1358222,947630,281197612767569,56171242137057 -26905955367752,43462788809912,-7898174980133,16239904,-16239904,33305452,-18910176,18910176,30547468,4,5247479,-4687032,4,-2389388,3639331,0,4727544,4059976,281197612767569,47812984263497 -24333353040089,-21702038097486,-15336517126085,16473956,32947912,-551700,-902684,-1805368,-68314004,8,5168719,-1837745,-4,5954891,849910,0,-225671,-4118489,281197612767569,165426748982001 -613321008509,70368744177664,28060760903125,-21822988,0,-14859436,8490388,0,-45811212,0,-11452803,3714859,4,946243,2143196,0,-2122597,-5455747,281197612767569,96329145163481 -18899295738082,-51469448439582,14674183751909,3578760,3578760,48951188,-20805368,-20805368,30025044,4,4405616,-9137601,-4,3100645,-3100196,0,5201342,894690,281197612767569,227274668351745 -6481089188274,27444005862565,-70368744177664,27279048,3915412,0,1152392,41438836,0,0,10359709,-978853,0,-288098,6819762,-4,841789,2569572,281197612767569,177352443368297 --9636296503703,-60732447673961,-7679793694213,-22055516,22055516,9935852,1661092,-1661092,50300140,-4,-10898331,1542044,-4,1676704,-941919,0,415273,5513879,281197612767569,275293441167377 -24582872340535,-45785871837129,10245774104137,6399196,6399196,-50719452,22084412,22084412,904900,4,951074,8017301,-4,-724849,4662562,0,-5521103,1599799,281197612767569,104996193714425 -9403758898333,20321661759777,5097394581485,564852,-188284,-262247500,12853428,-4284476,12251636,4,962122,18930085,12,-176543,-8771620,0,-1071119,47071,281197612767569,45666356715553 --3488607244915,5769032448000,70368744177664,-25632204,10805248,0,-10590316,-39460864,0,0,-9865216,-2701312,0,2647579,-6408051,4,-706135,391430,281197612767569,209045990455177 --18121940115266,-16002923831866,-15960046498823,-2831624,8494872,-119919644,-8332296,24996888,44742500,-12,-1126421,-7299560,-4,3353068,7560117,0,-2083074,707906,281197612767569,215306691060017 --20436497345775,-27710341425286,49932246831889,387140,-39176728,387140,28800868,-6260952,28800868,-4,1724695,6911642,0,-7200217,96785,4,-3289933,2882540,281197612767569,263920618309401 --33910613674001,36458130503663,26272721740064,24200124,24200124,-17562496,11439100,11439100,38222976,-4,3883123,4533614,4,5672621,-142990,0,-2859775,6050031,281197612767569,11338940015425 -26932125592071,-43436618585593,-9441637397437,1027100,1027100,-43530996,-25855044,-25855044,-393428,4,-806554,-6752063,-4,904911,-4130686,0,-6463761,-256775,281197612767569,230327819878313 -3153761480983,22404994232227,-7944188926622,1607772,-535924,-260321912,-12766116,4255372,-33835640,4,2573166,-20736367,12,-739412,2871377,0,-1063843,-133981,281197612767569,150924661962321 --127382841341,30128239667705,-40240504509959,30864396,-11164700,-11164700,-1667860,37082244,37082244,0,9270561,2791175,4,255224,4417519,-4,161741,3298580,281197612767569,147308842479929 --19795357393026,-50573386784638,25439182260535,-16988680,16988680,-38836004,-14727816,14727816,32605852,-4,-7189456,-5442367,-4,962007,4266634,0,-3681954,4247170,281197612767569,227951711136353 --916585133688,34726079521988,-16082008913045,10749472,5374736,-73588308,-4492000,-2246000,-178728884,-4,22178432,-8771639,8,325357,-853799,0,-561500,-1343684,281197612767569,130622231260105 --5010434819705,25456794242480,70368744177664,25422364,-21399872,0,9534876,36261568,0,0,9065392,5349968,0,-2383719,6355591,4,1507820,-1918285,281197612767569,94716040662897 --21378440761279,48990303416385,17732767507628,-24404732,-24404732,-3186000,-2092252,-2092252,-46407632,-4,-7945369,-982966,4,-3656539,1779466,0,523063,-6101183,281197612767569,59410052808537 --16742815739213,34807977361034,35560766816630,10428108,28807720,-28807720,-32227060,18940328,-18940328,0,4735082,-7201930,4,5198094,-396095,4,-2858671,-3003122,281197612767569,128590283879809 --10801064657545,-15860174167770,70368744177664,-9881124,34876568,0,-31458692,-2907432,0,0,-726858,-8719142,0,7864673,-2470281,4,1661025,-1895090,281197612767569,233935437429737 --18909385936075,-4462150324542,51459358241589,1071316,-37981432,1071316,30144980,-17781496,30144980,-4,-2772939,6926796,0,-7536245,267829,4,-1672435,2568562,281197612767569,220998906113169 --3927991906303,-26956744032864,-43412000144800,-32695292,14251648,-14251648,15444644,27703936,-27703936,0,-6925984,3562912,-4,2768643,4843726,-4,-1092518,-3330097,281197612767569,118351926735225 -34291562109338,36077182068326,-16423940447453,12303976,-12303976,46833804,-15528216,15528216,32400460,4,5058893,-5284846,4,-3041222,6423605,0,3882054,3075994,281197612767569,30410301506721 -20313468230605,18367437957077,50055275947059,-12870860,36481876,12870860,-27397484,-9819724,27397484,4,-3534064,-5647769,0,6849371,-3217715,4,-1079133,3472700,281197612767569,197887976288265 --6909306135499,9687492742302,70368744177664,4586708,42007160,0,25494612,-11978888,0,0,2994722,10501790,0,6373653,-1146677,4,-583402,1189001,281197612767569,249056884166065 -6530893668537,-22977527047370,70368744177664,-22118684,26268888,0,12426500,36144536,0,0,-9036134,6567222,0,3106625,5529671,4,1853047,1196104,281197612767569,270688257214361 -17221772683051,18703426128511,-7098089974594,-4222804,12668412,-130770184,5210092,-15630276,-105279624,12,-7389768,8369941,4,6310046,-8107535,0,-1302523,-1055701,281197612767569,145716686985153 --15965891122865,-38436961931934,1769367289713,-6256324,12512648,73013700,-13153828,26307656,-26451676,-8,-3446751,-10049079,-4,1583084,4102173,0,3288457,-1564081,281197612767569,45654725412905 -11629984837236,58738759340428,-5620070242189,-19830320,19830320,8222156,6431184,-6431184,54110156,4,-11163407,2111758,4,2364132,56219,0,1607796,4957580,281197612767569,45336814138065 --7276301136861,582292548137,-70368744177664,-13548404,-33299292,0,20068204,-33778364,0,0,-8444591,8324823,0,-5017051,-3387101,-4,831676,-888835,281197612767569,107494392234425 --3002018962971,7281994748398,-70368744177664,4477844,-43528264,0,23803604,20047672,0,0,5011918,10882066,0,-5950901,1119461,-4,-829634,-348397,281197612767569,172400695471841 -15338740654831,16151424388080,38878579134753,-8785988,36270016,-27484028,-33940516,11964864,21975652,4,391647,-6586848,4,5885560,284159,4,-2599569,2480656,281197612767569,170300705096777 --5189742925446,12005744571521,70368744177664,-29721112,-12931580,0,12234472,-32558972,0,0,-8139743,3232895,0,-3058618,-7430278,4,-78475,1506122,281197612767569,130471013833713 --13558329224802,-56810414952862,6449762708569,-17494408,17494408,-32821916,13869624,-13869624,-38336380,-4,-8055286,6223615,-4,1528809,-1981864,0,-3467406,-4373602,281197612767569,54346476658649 --8103459437403,21679181535842,48689562641822,32562836,-1269368,1269368,-12396460,35059464,-35059464,0,8764866,317342,4,3153677,5669266,4,54562,-2471443,281197612767569,265587983321601 -2551656855136,-67817087322528,-17442845956859,-6203008,-6203008,-83894252,9633152,9633152,-51222540,4,-12938248,19828639,-4,132613,1144924,0,-2408288,-1550752,281197612767569,10830599365737 --22545202520337,47823541657327,3230998561840,-14491716,-14491716,32460992,-20586308,-20586308,-31579968,-4,-5129236,-5681579,4,-2765756,-2433669,0,5146577,-3622929,281197612767569,162340229744913 --8368577286671,-62000166890993,29514214468310,-470076,470076,65770328,17119844,-17119844,-165608,-4,1831589,14536444,-4,1790187,-1906138,0,4279961,117519,281197612767569,81430600770041 -34678198748601,-35690545429063,3306315941498,-650524,-650524,-43060760,25895972,25895972,-16601496,4,-1800857,5467672,-4,-2349517,5297518,0,-6473993,-162631,281197612767569,217616373508385 --28833908404664,9204579231161,-32330256541839,19732768,-11889948,-31622716,-26359776,-41174332,-14814556,-4,5213744,-2399783,4,-1510105,-5505896,-4,-5079839,572704,281197612767569,246083854133385 -1894984646831,-17945029583154,70368744177664,30828220,-5471432,0,-8232132,-35060680,0,0,8765170,-1367858,0,-2058033,-7707055,4,-760868,-1928573,281197612767569,205300125776433 -28611080061252,-41757664116412,-15144640134557,22312208,22312208,-6546036,-13213296,-13213296,-46584596,4,6200030,-2171623,-4,5446119,535114,0,-3303324,-5578052,281197612767569,199921331030041 -8013518681087,27818012730386,42550731447278,31454204,-18282424,18282424,13014076,28230600,-28230600,0,7057650,4570606,4,-2771063,4234454,4,482456,-3629097,281197612767569,148485973314625 --18940644319977,-14153219098715,-51428099857687,1194076,-39146860,-1194076,28654076,3502964,-28654076,-4,2080818,7092455,0,-7163519,298519,-4,1205077,-2694260,281197612767569,238732027170985 --18334773394543,33699197388578,9965763298867,12429892,24859784,-27792180,5046852,10093704,79295692,-8,9136193,4207553,4,5343865,1370246,0,-1261713,3107473,281197612767569,44236653358929 --18187009074278,10363264225349,52181735103386,1295976,-42824428,1295976,26337448,-1532620,26337448,-4,-1253812,7986797,0,-6584362,323994,4,870657,2719310,281197612767569,247673076109881 -26250867388639,44117876789025,697578968510,7628668,-7628668,-43999496,-23360708,23360708,-12851592,4,2072230,-6877495,4,-1140668,4122379,0,-5840177,-1907167,281197612767569,134233672938337 -11014323535679,-15142677172470,59354420641985,19669244,38884392,-19669244,15425820,-26746136,-15425820,4,6469810,7141365,0,3856455,-4917311,4,-216724,-2579733,281197612767569,63716713635017 --11037611103791,-37255910866291,-11115135388759,-5422268,16266804,-100136284,5849028,-17547084,-99626204,-12,-12493568,13896355,-4,4137661,-3712572,0,-1462257,-1355567,281197612767569,18766040180849 --34647143250174,-35721600927490,-15088564029461,-25963512,25963512,9622444,-4581304,4581304,-41666804,-4,-5533459,170612,-4,4883242,2576223,0,1145326,-6490878,281197612767569,153930229186649 -26425024646605,43943719531059,-8908844100082,-20159692,20159692,11034680,11908340,-11908340,49330872,4,-7324603,2360794,4,5008115,-397876,0,2977085,5039923,281197612767569,212801983422081 --19498632669487,-1855852383534,50870111508177,-6555836,-36420792,-6555836,28013988,-16109048,28013988,-4,-2726634,6625443,0,-7003497,-1638959,4,-1300628,2479755,281197612767569,34260210060521 -15563643317021,39241457543622,-16231529704848,-6121356,12242712,-86472256,10556788,-21113576,-34801216,8,-6069300,11349426,4,1315502,-5134319,0,-2639197,-1530339,281197612767569,186556135564689 --9684218735441,-17341141447714,-70368744177664,30324412,-11733128,0,12202524,32407096,0,0,8101774,2933282,0,-3050631,7581103,-4,-363200,-2271911,281197612767569,246584330015353 -1946992827933,31719723055679,-38649021121985,25716,30346492,30346492,-37092172,10989500,10989500,0,2747375,-7586623,4,5017070,213441,-4,4255973,-207012,281197612767569,61824986516897 --28097010510215,-42271733667449,-2341499741517,19486180,-19486180,13319884,-14166076,14166076,48096108,-4,7105200,-2162471,-4,-4918827,1167500,0,3541519,4871545,281197612767569,148257148363017 --12996253123391,-57372491054273,18663609502235,9293572,-9293572,45440108,19524740,-19524740,-25683732,-4,6529681,8645744,-4,108748,-2714283,0,4881185,-2323393,281197612767569,97015221954225 --17212474599654,-6988206356573,53156269578010,22393960,-25611636,22393960,23127464,23826412,23127464,-4,5073782,4280755,0,-5781866,5598490,4,882821,2122154,281197612767569,137463118317721 --31514471044075,38854273133589,-6784842001105,16104532,16104532,25475260,22786324,22786324,-33867012,-4,4125683,3904750,4,4341070,2464065,0,5696581,-4026133,281197612767569,36390982762689 --15155716319936,55213027857728,12938621629695,-18262784,-18262784,-20449284,1740032,1740032,-59701604,-4,-11790817,3171762,4,-3134584,1940559,0,-435008,-4565696,281197612767569,163716703689001 --33677059438116,-36691684739548,21547621216353,18888560,-18888560,-19194492,-11645072,11645072,-47773820,-4,5336099,-3948066,-4,-6607356,850557,0,-2911268,-4722140,281197612767569,208648704453585 -31374462036366,38994282141298,26541701022777,437816,-437816,41028836,27513080,-27513080,6691716,4,-3521388,5725235,4,-1848459,-4531974,0,6878270,-109454,281197612767569,202201814491833 --11558385489269,20851365910376,-37958992778019,29040172,33930656,4890484,16581356,-19396704,-35978060,-4,5281006,4938083,4,3713509,-3715462,-4,431830,-3544581,281197612767569,83838238636001 -5707736998723,18425414336068,-46235592842873,8200460,30238992,38439452,30738092,-23951216,6786876,4,3490000,7483367,4,5186719,-2126496,-4,2497804,76381,281197612767569,177395654473033 -23106289029288,-14017125600561,47262455148376,29991584,-5066948,-29991584,-6494560,38637756,6494560,4,6811086,2344337,0,1623640,7497896,4,-2848353,1077600,281197612767569,267023137551601 --20502566712469,30348282291305,40020461886359,8462764,-32649820,32649820,-31495412,-11530556,11530556,0,2882639,-8162455,4,-3638174,-3581451,4,4235679,-1465760,281197612767569,269323034534105 --457456490393,69453831196878,16992872996538,-1301092,-2602184,314725096,-3016484,-6032968,-135683480,-8,-33115626,-77815380,4,-402622,-432947,0,754121,-325273,281197612767569,20245418832641 -3959692111895,27984831261968,38424220803801,34767964,-13732800,-21035164,-4371716,34110016,-29738300,4,7613011,-216692,4,178436,5042099,4,-914493,-3649892,281197612767569,218467666244969 -12557638946155,3092440796188,-70368744177664,-8705620,34553968,0,28310188,16962672,0,0,-4240668,8638492,0,7077547,2176405,-4,-445736,1637225,281197612767569,41699163243025 --5952056782895,-70368744177664,10187012820698,16243524,0,-31812760,12448228,0,44934056,0,11233514,7953190,-4,-1400694,-84833,0,-3112057,4060881,281197612767569,188185582076665 --30765710257262,39603033920402,-12786557659369,12371528,12371528,42147932,11163848,11163848,-52973796,-4,6946180,6492141,4,6297269,4044842,0,2790962,-3092882,281197612767569,115593801921057 --14984380832522,13164159986365,-55384363345142,25295832,23598836,-25295832,5099288,-39752108,-5099288,-4,8060301,3460372,0,1274822,-6323958,-4,-1877726,-2439337,281197612767569,264088286665097 -23875023721538,-23494071681127,-46493720456126,-4454136,35879524,-4454136,29100040,18365924,29100040,4,-604749,6298316,0,7275010,1113534,-4,-3986732,2671565,281197612767569,204177889153841 --29090378285311,10281238806779,30997127085574,-16197628,-42682388,26484760,-29254364,-7578036,-21676328,-4,42767,-5667742,4,-5461849,-953448,4,1851742,-5002855,281197612767569,147181965904153 -5994606855410,-46390316756024,3415011087261,4066248,16264992,-137479564,-3926200,-15704800,-144144588,16,23947227,-22460879,-4,3022230,-2977253,0,-981550,-1016562,281197612767569,91252959098177 --24246920219841,-46121823957823,24016113850491,20574460,-20574460,17503724,5019036,-5019036,-50453236,-4,8695384,1112657,-4,-3917925,-3263274,0,1254759,-5143615,281197612767569,228839023206825 --25138770148434,20091203880796,15227267400007,7706296,15412592,-60684004,12050104,24100208,51211548,-8,2351617,5165313,4,5225635,5002844,0,-3012526,1926574,281197612767569,21697026107473 -18849518295874,32669707585916,1331602908257,14886152,-29772304,-30478972,6502472,-13004944,62320420,8,7294813,3396729,4,-4142646,-2111507,0,-1625618,3721538,281197612767569,13242793472825 --14244029078115,-41880686021434,11693006515525,164468,-328936,-106757868,-10518092,21036184,-18306476,-8,1849939,-15898177,-4,-1363340,5395645,0,-2629523,-41117,281197612767569,17750016998497 --18971114194357,-51397629983307,-92347342630,-16425684,16425684,18930536,-9041972,9041972,-58124248,-4,-10616516,-3451347,-4,3914546,1281287,0,2260493,-4106421,281197612767569,193616921333193 -17240737168121,53128007009543,-3890641350062,-18290716,18290716,-26754744,10198116,-10198116,-46638520,4,-8943917,4797100,4,2715713,-1891586,0,-2549529,-4572679,281197612767569,136063219466609 --4179837079501,-2442900823718,-70368744177664,-25258804,-17834648,0,-3400404,42173608,0,0,-10543402,-4458662,0,-850101,6314701,-4,655780,45621,281197612767569,87418725466457 --23047547573756,47321196603908,2242397494013,-20965360,-20965360,-3745804,7637776,7637776,-52338252,-4,-8859884,462717,4,-4224679,473734,0,-1909444,-5241340,281197612767569,198326416967553 -4347991891375,-15399798970430,70368744177664,21158588,-15575288,0,22595676,36579272,0,0,9144818,3893822,0,-5648919,5289647,4,-1801280,917015,281197612767569,199453619265001 -32046395118346,26452076711767,38322349059318,13755432,-28442276,-13755432,-29354456,-21154724,29354456,4,5638814,-2579679,0,-7338614,-3438858,4,350133,4530890,281197612767569,208418987531921 --3729724723103,-32962069570599,-70368744177664,15998340,-36705436,0,20820004,22608132,0,0,5652033,9176359,0,-5205001,3999585,-4,2138550,-2359853,281197612767569,104483304993657 -9493097807769,27376260737895,33499385632000,3635812,30421404,-34057216,-35092060,16048732,19043328,4,57865,-6932970,4,4818697,1581334,4,-3954318,672381,281197612767569,45188478211745 --35132535449109,35236208728555,-5285312401967,-23372884,-23372884,-44220,8305996,8305996,48186916,-4,-6188202,-444413,4,-5858527,433358,0,2076499,5843221,281197612767569,278649599463945 --32126091059090,38242653118574,12222015487923,-16053832,-16053832,-30223668,-7115080,-7115080,56737612,-4,-8017613,-3409266,4,-6166790,-4146651,0,-1778770,4013458,281197612767569,193910933831601 -25862675360776,-44506068816888,2687558283037,25595936,25595936,-13850508,-4044512,-4044512,46176020,4,7262611,1945612,-4,4281394,1517015,0,1011128,6398984,281197612767569,157755950959001 -5754292307040,32307225935312,-15643489869667,7639424,-3819712,-96309644,-20465280,10232640,-36756172,4,3650114,-11266547,8,-1888815,1544317,0,-2558160,-954928,281197612767569,37844746168769 -34799580946387,-35569163231277,2516443706468,-10366132,-10366132,-56311408,10965356,10965356,-49046768,4,-6099863,7208582,-4,-6161829,6869270,0,-2741339,-2591533,281197612767569,244420682672681 --8947514713782,30710614731941,-1992364270397,-9110232,-4555116,-105707764,-17004248,-8502124,49869068,-4,-5380835,-11565596,8,-1705597,-3295749,0,-2125531,1138779,281197612767569,95906250630353 -26647243932989,43721500244675,-9642440949615,15040756,-15040756,45522500,-23694828,23694828,3141604,4,1299695,-6555760,4,514294,4824865,0,5923707,3760189,281197612767569,45035917624249 -33641372022092,-36727372155572,-3136702677419,-25483984,-25483984,14353748,-13897680,-13897680,-36352876,4,-4588517,-2156892,-4,-4499702,-1431545,0,3474420,-6370996,281197612767569,52420387799265 --10671032688601,18184453277996,59697711489063,-25033572,7664816,-25033572,-5402180,-43321552,-5402180,-4,-8839016,-3242895,0,1350545,-6258393,4,-1991372,1326691,281197612767569,177524298557001 --20314782880453,29739178416758,-2781618836317,-8951572,-17903144,-52181364,-9513876,-19027752,70317580,-8,-7241351,-5690135,4,-5169022,-3677603,0,-2378469,2237893,281197612767569,280892506869233 -11843681931986,11150334517734,1933236471219,-2768056,13840280,172485324,-1553016,7765080,-309974740,20,-12332655,-6737766,4,13032206,7276713,0,388254,-692014,281197612767569,173687765770713 -7531788635196,-20429180249835,-70368744177664,28033264,-1478572,0,-10701328,-39598572,0,0,9899643,-369643,0,-2675332,-7008316,-4,1836282,1995063,281197612767569,229418591640577 -20246606749315,50122137428349,-4119001477284,18025996,-18025996,544112,-1285844,1285844,62420976,4,11134095,166896,4,-4471149,302924,0,321461,4506499,281197612767569,60138253338217 --23223716462308,-3537285540509,-47145027715356,29955184,-1218164,-29955184,-4089744,37752460,4089744,-4,6271869,-172412,0,1022436,7488796,-4,-3166246,-476953,281197612767569,161394016582417 --24452186651741,-15131593776943,-45916557525923,-5561716,40443716,5561716,-29355924,11033060,29355924,-4,221683,-6298530,0,7338981,-1390429,-4,-2536582,3812399,281197612767569,47979147535353 -14014458447588,-42339827282488,7353700045445,14748560,29497120,-27421164,3633296,7266592,69584468,8,10656829,3354097,-4,3369644,1750597,0,-908324,3687140,281197612767569,98739931708193 -27846943438999,-7376757690027,-42521800738665,-18504100,30069076,-18504100,-24142724,-21614156,-24142724,4,-2632482,-5027415,0,6035681,-4626025,-4,-2771057,-2489854,281197612767569,183753807448713 -3210735649755,-4043206625799,-70368744177664,1852268,33149924,0,34525676,10054500,0,0,-2513625,8287481,0,8631419,-463067,-4,-610629,404742,281197612767569,74619827186737 -857849085767,18913385764266,-51455358413398,-27393764,-14324056,-14324056,-20526852,30367208,30367208,0,-7591802,-3581014,4,-3659885,5051404,-4,-1471828,1797037,281197612767569,170514938382873 --3602011416763,22255577586967,154637391375,-11949804,-3983268,144063548,11116500,3705500,148639868,-4,-11750576,11392961,12,-1908239,1837004,0,926375,995817,281197612767569,126119467277889 -20078804032884,-50289940144780,5970072733253,-5429808,-5429808,56714516,17472848,17472848,24850932,4,-4810609,10017776,-4,-1402124,4160853,0,4368212,1357452,281197612767569,132643923210921 -6205205790719,64163538386945,18257595396804,13378556,-13378556,29637392,-5307396,5307396,72399632,4,16159576,-7623769,4,-1940332,-214421,0,1326849,3344639,281197612767569,225725972996433 -29688296420325,-40680447757339,18642214997870,-12084332,-12084332,47433144,19478452,19478452,16713848,4,-3705652,6054971,-4,-472810,5803315,0,4869613,3021083,281197612767569,234066239591481 --10694314849102,-59674429328562,-12751272409221,-18404664,18404664,-9317908,1986376,-1986376,-60169044,-4,-12666222,2809215,-4,2376039,479738,0,-496594,-4601166,281197612767569,29801049425249 -23746218478732,-22876307220200,-5165981490581,229936,459872,69238188,-16224080,-32448160,11194444,8,1505335,-5618753,-4,646638,-5845397,0,4056020,57484,281197612767569,206075146469065 --1241136011615,-33649579971560,-36719164206104,6026884,33116256,-33116256,35644164,9043040,-9043040,0,-2260760,8279064,-4,4689751,-932246,-4,-4221290,574475,281197612767569,188599917238897 --26825066949073,43543677228591,-12714494859268,23837884,23837884,23080944,-7067492,-7067492,40388464,-4,5928778,-4647361,4,4168338,-1122875,0,1766873,5959471,281197612767569,18379447435865 -32561059306115,-37807684871549,-31709959717611,-1376756,-1376756,-42991532,26067020,26067020,-3805164,4,-3447726,5619517,-4,2496435,5128366,0,-6516755,-344189,281197612767569,109685582852225 -12912336443611,57456407734053,-21001773950633,563052,-563052,-46126756,24187276,-24187276,18149884,4,1900174,9457689,4,-2637297,-2074000,0,-6046819,140763,281197612767569,39574819745513 -19066327970361,51302416207303,-6704477920215,19383524,-19383524,23448740,16180708,-16180708,-38511196,4,7404568,3812135,4,-2223231,-2050050,0,4045177,-4845881,281197612767569,12860757301137 --13433286676509,32270410532082,-38098333645582,-30682228,17107912,17107912,-14708884,-28494072,-28494072,0,-7123518,-4276978,4,631015,-4969384,-4,3046206,-2701173,281197612767569,180548516582521 --32609284964797,37759459212867,-17159837934220,12750092,12750092,43132368,-14140212,-14140212,40470224,-4,4566978,-6563441,4,5550578,-4219651,0,3535053,3187523,281197612767569,115893597577121 --1308760766909,70368744177664,33685362521442,19115276,0,-4387448,67500,0,-58916024,0,14729006,-1096862,4,265861,2267210,0,16875,-4778819,281197612767569,102616276681481 --27207912053231,43160832124433,6952125787358,4666436,4666436,-51741832,-21835324,-21835324,835704,-4,-667454,-8049249,4,458528,-4886209,0,-5458831,-1166609,281197612767569,169363907926193 --21494282162570,-48874462015094,29483033593499,-12639784,12639784,-43299220,-19004776,19004776,23972556,-4,-6153173,-6194394,-4,-160034,4630411,0,-4751194,3159946,281197612767569,225390080084633 -692005726349,-22994910908322,-3243721864728,-340428,-226952,-690714720,4865268,3243512,-50487904,8,-4161954,56424864,-12,-68057,1702044,0,-405439,-28369,281197612767569,177143669920449 -10753961578458,-26378541039165,-33236241560041,1349480,-35546356,36895836,-30911704,-20082900,-10828804,4,1356540,-7654981,-4,-4063741,-1568978,-4,3664185,-1231608,281197612767569,184321854946089 --32204152700209,38164591477455,-8928338330552,21622588,21622588,-9383648,3874108,3874108,50389280,-4,6955061,586444,4,5642259,1759468,0,-968527,5405647,281197612767569,259202953502161 -27529472523334,42839271654330,7316139393581,-3335912,3335912,-49695564,22890200,-22890200,3489748,4,1126090,7650157,4,253653,-4773734,0,-5722550,-833978,281197612767569,82501250065593 --16954100840038,18905172407187,-53414643337626,30834280,926284,-30834280,6869224,36720908,-6869224,-4,6507045,1895196,0,-1717306,7708570,-4,-2673182,2126767,281197612767569,42120302971361 --16370143349147,-31440279849086,38928464328578,-5659244,-34433528,-34433528,33407732,4319688,4319688,0,1079922,8608382,-4,-4871572,-2785283,4,-3480361,1370472,281197612767569,247678237873993 -25833861416465,-44534882761199,184680264964,17478724,17478724,-17546224,-11646268,-11646268,-52724208,4,8349649,-2764690,-4,4831403,-1621866,0,-2911567,-4369681,281197612767569,264989615941361 -20004867996943,-30359008183778,-450315241873,-2041796,-4083592,-67748420,16457244,32914488,-5361764,8,-630961,7300599,-4,-354740,4818253,0,-4114311,-510449,281197612767569,62956180382425 -18534084246313,19576670877625,51834659931351,-28628828,1891044,28628828,-808604,39380900,808604,4,-7195900,-1642901,0,-202151,7157207,4,2649325,-2115662,281197612767569,136085038646529 -30016947667912,-40351796509752,-32173179717881,-6099168,-6099168,-44900324,-23746016,-23746016,9787580,4,-4117351,-5739690,-4,1670456,-5485391,0,-5936504,1524792,281197612767569,70639357089641 -1010796699473,-70368744177664,-29197669054979,-1304252,0,129795060,-8485820,0,-18771212,0,-4692803,-32448765,-4,-947651,-330812,0,2121455,-326063,281197612767569,190216390243345 -7775794177202,70368744177664,12949250585773,-22181176,0,-3309900,-7163384,0,49690324,0,-12422581,-827475,4,1702255,-929008,0,-1790846,5545294,281197612767569,82981634622713 -24588767035010,45779977142654,-11520336149753,-21646840,21646840,-12513252,-5726072,5726072,48702172,4,-8155434,-1149223,4,4020109,1979090,0,-1431518,5411710,281197612767569,19600365093921 -11061103359915,-21738014520158,70368744177664,15127212,-34968952,0,24018508,18906184,0,0,4726546,8742238,0,-6004627,3781803,4,-2597879,-205914,281197612767569,83730948127625 --24600920736559,32883507024672,-37485237152992,-33648828,-734080,-734080,-983356,33438848,33438848,0,-8359712,-183520,4,-3053514,4417001,-4,2807675,3995206,281197612767569,108463213053233 --6590631926677,-70368744177664,-27085951441546,11961772,0,-39125544,20423180,0,27323032,0,6830758,9781386,-4,1325536,-2067175,0,-5105795,2990443,281197612767569,124970756147993 --5296638338783,-29614466333464,40754277844200,27771012,1799072,1799072,3769412,-40298080,-40298080,0,10074520,449768,-4,-212540,-4054771,4,1154893,-2887982,281197612767569,251909633115969 -7602870855522,-62765873322142,-4271625836139,-15018616,-15018616,-12471724,880712,880712,-74235596,4,-16567100,2553139,-4,-1991799,564792,0,-220178,-3754654,281197612767569,18245061051305 -14263000773333,11691508407506,56105743404331,-24389804,-26285240,24389804,-11474092,33796936,11474092,4,-6260069,-6252444,0,-2868523,6097451,4,2189165,318866,281197612767569,129626436803153 --11146151631975,6047926081286,70368744177664,27331172,164888,0,454404,-41191976,0,0,10297994,41222,0,113601,-6832793,4,1621401,593782,281197612767569,239322958263609 --13645814726305,32579998555667,37788745621997,23046524,20106316,-20106316,-27672260,24711436,-24711436,0,6177859,-5026579,4,4913075,2119308,4,-2004990,-3642323,281197612767569,187001196891745 --18742919499936,-23231667450191,28394157227537,33176960,-12101948,21075012,-2240128,-33119068,-35359196,-4,6259317,518636,-4,-2580482,-4750117,4,2020450,-3544123,281197612767569,11045268975561 -22632454493236,-25103835191192,-4272619033673,-9371440,-18742880,-18681124,-1303856,-2607712,117542492,8,-10522815,-1381603,-4,-9431404,-1644339,0,-325964,2342860,281197612767569,125699428496241 --16722062336939,26165206855080,-53646681840725,-25330348,-24308064,25330348,14048756,-30966880,-14048756,-4,-7207955,2278260,0,-3512189,-6332587,-4,533765,-3798756,281197612767569,106935503553369 --30392913892746,589131771647,39975830284918,-22212136,13426684,-22212136,18793048,39328572,18793048,-4,-5546215,1953384,0,4698262,5553034,4,-4285928,1403287,281197612767569,64451945879937 -34033292496265,-36335451681399,-4362996204068,13300260,13300260,35522416,7397764,7397764,-64894480,4,8491862,4379409,-4,7731758,4501195,0,1849441,-3325065,281197612767569,272096504463337 -6389007819914,-19873379378331,44106356979419,-16176600,-35178092,-19001492,-34624472,-5694828,28929644,4,-1150197,-6853900,-4,-6082214,2103527,4,-2573904,1940623,281197612767569,273594460885137 -10016735021547,25147768409961,45220975767703,-3859540,-35620444,35620444,32331916,6678852,-6678852,0,1669713,8905111,4,-5432032,-1887673,4,2650947,-922788,281197612767569,215169341175161 --5899940850176,-32234401663744,3467280836353,-10201088,5100544,87848964,-19933184,9966592,-49082044,-4,-5498085,-10123258,-8,1274341,1715725,0,2491648,-1275136,281197612767569,101199326881953 --16875495033223,10886669713060,-53493249144441,7329252,-36181360,-7329252,-28539964,-12727792,28539964,-4,1315022,-7159605,0,-7134991,-1832313,-4,-1866926,1885735,281197612767569,145434918319113 -4705816388864,-11505789881583,-70368744177664,-2452480,-48535484,0,22680576,-10229308,0,0,-2557327,12133871,0,-5670144,-613120,-4,756091,911686,281197612767569,219040657207729 --10190206113997,20059512687889,8156064458377,1929420,643140,-279554524,-11758548,-3919516,-46928316,-4,3230807,-19941286,12,2039658,-10064773,0,-979879,-160785,281197612767569,42568864730009 -16845775815088,-53522968362576,-32430454330883,10634944,10634944,-40233996,23231168,23231168,17980084,4,742340,8875883,-4,3752681,1182616,0,-5807792,2658736,281197612767569,128277070232513 --10095768229756,-19889903028884,-5333290111749,4854288,-24271440,-25663508,472976,-2364880,229438732,-20,16257668,1353577,-4,-8220403,-1012460,0,-118244,1213572,281197612767569,183754154970153 -12010944087795,27046761897668,-43321982279996,1437644,-30741744,-30741744,35901900,15450896,15450896,0,3862724,7685436,4,-6184995,-1090526,-4,-2790480,1449937,281197612767569,173046494172881 --16635069128162,26866837524751,-12062693905378,3035256,1517628,133855352,-16227016,-8113508,26266936,-4,2159477,-12841556,8,2247780,-7780726,0,2028377,379407,281197612767569,39655228704185 --33147994587071,-37220749590593,-14397905398626,16702724,-16702724,33167992,-19849404,19849404,27991544,-4,2686123,-5240330,-4,-4311763,3051668,0,4962351,4175681,281197612767569,115871485629153 -5239748488647,-21337860860999,-70368744177664,9354012,-39367964,0,-27358148,-5223996,0,0,1305999,-9841991,0,-6839537,-2338503,-4,2171194,-23745,281197612767569,170630928271433 --8870701429245,21412459629475,-70368744177664,-5846004,39273100,0,28787596,-800244,0,0,200061,9818275,0,7196899,1461501,-4,2164720,-792975,281197612767569,128679531528177 -22709046866928,24950650443808,12593155521767,-7204928,14409856,82409372,7507392,-15014784,70399100,8,-6912113,6660279,4,5343831,-6971032,0,1876848,1801232,281197612767569,6114328290265 -5502030547670,30653987251001,39714756926663,-22670504,-24737564,24737564,-17016872,31095204,-31095204,0,-7773801,-6184391,4,-1793176,3682247,4,2461042,-1985379,281197612767569,171936100298241 --23561529201083,23111091787297,-23696123189284,-30472940,-21318524,9154416,9884916,-30032156,-39917072,-4,-5805748,1043069,4,-4173520,-3331673,-4,1702291,-4286562,281197612767569,143241593841769 --1651810875235,70368744177664,-25832823155506,-2355596,0,-74753224,14717300,0,-10924744,0,-2731186,18688306,4,-1414815,222494,0,-3679325,-588899,281197612767569,89638431091985 -22960764460602,-14374075467355,47407979717062,8933608,35631764,-8933608,30192936,-5604940,-30192936,4,2485885,5545138,0,7548234,-2233402,4,1084650,-3362803,281197612767569,178909080643065 -1145478611384,70368744177664,-12352198068769,-8640800,0,-54756484,-15631136,0,31246396,0,-7811599,-13689121,4,-558795,602026,0,-3907784,2160200,281197612767569,254367411997985 -31737701553363,6893341070938,4884878348242,-88244,176488,87144264,-12914196,25828392,-5686520,8,-587504,-2131106,4,417063,9827480,0,3228549,-22061,281197612767569,8211717729417 -5337530678692,-32515606749486,-14314892190133,-14424432,-7212216,46853420,-5733232,-2866616,-137487444,4,-15736576,-5779233,-8,-2898709,-154889,0,716654,-1803054,281197612767569,244949979766321 -18110398675216,-52258345502448,19051499905691,21931072,21931072,-16073108,-928192,-928192,52018380,4,9594853,1499722,-4,3409742,2518555,0,232048,5482768,281197612767569,43965623716889 --19347897769305,-31672948639054,20645196007189,13635228,-27270456,31336532,5960924,-11921848,-68873452,-8,8624405,1525949,-4,-4296979,-3154092,0,1490231,-3408807,281197612767569,119319017697345 --9982581363679,60386162813985,17417764464535,-15004540,-15004540,-29269412,4577252,4577252,-66108420,-4,-14465795,5350820,4,-2061310,1966533,0,-1144313,-3751135,281197612767569,214088803177641 -15635233652303,-39098276873058,18370351256413,15785276,31570552,-7653004,-723652,-1447304,-70975116,8,9953255,997399,-4,3895262,-1455325,0,-180913,-3946319,281197612767569,42815528719185 --12061619593679,24857342349310,45511401828354,25793732,-18577416,18577416,-19671964,-29481800,29481800,0,7370450,-4644354,4,-1917401,-4966632,4,3000590,1481801,281197612767569,9485629019705 --10604755028821,28643597616958,41725146560706,-14235988,-33987336,33987336,-26870420,14937208,-14937208,0,-3734302,-8496834,4,-4545973,829812,4,2171632,-2729185,281197612767569,64515262486369 --24951006144325,45417738033339,6662322803428,18224876,18224876,24460176,-3377268,-3377268,57245456,-4,9316848,-3515431,4,4994516,-2599613,0,844317,4556219,281197612767569,183586919342281 -8396378205541,-24111140963853,37861225008270,30310804,28883916,-1426888,21211156,-16932532,-38143688,4,5544984,3762951,-4,3990938,-4119673,4,1311851,-3458028,281197612767569,237056911477873 --1640495753641,-17096308140975,53272436036689,-14934692,21163332,21163332,-33630660,-27731612,-27731612,0,-6932903,-5290833,-4,6526622,-2703221,4,1881043,-1030452,281197612767569,128900623598681 -112175643173,-33464421834166,36904322343498,-674668,-33021656,-33021656,34363476,13101224,13101224,0,3275306,8255414,-4,-4500191,-75296,4,-4090678,-93371,281197612767569,1669065261697 --33432843800487,36935900377177,10948920506594,-14992028,-14992028,25959304,-4366652,-4366652,-67538872,-4,-8692776,-3989615,4,-8191942,-2500211,0,1091663,-3748007,281197612767569,120293718937833 --12378070273755,-27297274395648,-43071469782016,9080980,34607104,-34607104,31778196,-2879488,2879488,0,719872,8651776,-4,4736091,-2911450,-4,-3208458,-641205,281197612767569,246723323677073 -22181219557243,-30207698474771,-40161045702893,-30723604,-12890188,12890188,11760844,-31711788,31711788,0,-7927947,3222547,-4,-4177046,-3367873,-4,-1236835,4313028,281197612767569,257255540938361 --9899991951506,29797564171773,-40571180005891,-28908104,23757812,23757812,20772664,21875764,21875764,0,-5468941,5939453,4,2224715,5002356,-4,2968451,2224670,281197612767569,128260739838369 -20449816887807,-49918927289857,-32387581003517,-25940996,-25940996,-6850548,7095068,7095068,-41528660,4,-8181396,-1769941,-4,-2200769,3482578,0,-1773767,-6485249,281197612767569,203583147123977 -34692604819488,35676139358176,-19064377626033,4677760,-4677760,43822396,23924864,-23924864,-16558148,4,3719135,5237536,4,-420402,-5718063,0,5981216,-1169440,281197612767569,182164063783601 -5090218684159,5256579171218,-70368744177664,9166844,34375240,0,-25940772,25546376,0,0,6386594,-8593810,0,6485193,2291711,-4,946430,-450453,281197612767569,211690744401049 --29702792217459,40665951960205,-8008870540657,-22995404,-22995404,-21098948,-6834956,-6834956,42690684,-4,-5973238,-3702553,4,-4699433,-1572184,0,-1708739,5748851,281197612767569,136847165777089 --26823818592491,-43544925585173,19820999674482,-17102764,17102764,-35249720,21964084,-21964084,-20562296,-4,-4727716,4248877,-4,412858,-4563553,0,-5491021,-4275691,281197612767569,167387631246633 --35230527734777,24509360100914,-35138216442887,-15928292,37376200,15928292,25692700,10396872,-25692700,-4,939281,6052848,0,6423175,3982073,-4,3538499,-3291202,281197612767569,161802617507793 -32809121956893,-37559622220771,-3907913854323,10615924,10615924,-53971404,-16288364,-16288364,-23247532,4,2875975,-7349256,-4,2935908,-6143595,0,-4072091,-2653981,281197612767569,47107557353145 --64073958941,70368744177664,-9976002306225,7797644,0,-70229700,5600844,0,93945596,0,23486399,17557425,4,-177119,292350,0,-1400211,1949411,281197612767569,269541522922465 --16242783940787,-21640392355303,6485679647520,-3512012,10536036,118893696,-7495276,22485828,-66844544,-12,-4621037,-9383568,-4,4030033,6779952,0,1873819,-878003,281197612767569,16579332012361 -23103101143600,21034086818327,-47265643034064,-7509824,-34124708,-7509824,30187712,-12750372,30187712,4,114811,6291460,0,-7546928,-1877456,-4,-3302404,2239717,281197612767569,153035265022193 -23551699569749,-46817044607915,12308421270116,-19645100,-19645100,44915088,13122548,13122548,27309584,4,-5116163,6611570,-4,-1711233,4617202,0,3280637,4911275,281197612767569,163377659749593 -24404070547213,-45964673630451,13412598165567,18753588,18753588,-24976132,17744884,17744884,36403772,4,6790275,3184956,-4,2310668,3059077,0,-4436221,4688397,281197612767569,137685176620801 --6396772145155,70368744177664,-30548990309022,23464948,0,-12882552,1508564,0,-48810424,0,12202606,-3220638,4,1272988,-2839461,0,377141,-5866237,281197612767569,146515223017833 -5014414819989,-65354329357675,-12026257235043,-10742188,-10742188,21854836,2954580,2954580,98799988,4,-22813660,5533339,-4,-1886337,-69630,0,738645,2685547,281197612767569,141300623074833 -19244574782765,51124169394899,-17482996653208,8093876,-8093876,-48960096,-18583340,18583340,-26693984,4,3694166,-9395327,4,-2979330,2844697,0,-4645835,-2023469,281197612767569,37966455244537 --18593910428163,-51774833749501,-19374464751889,-13818892,13818892,-36831300,-15690188,15690188,39656572,-4,-6214490,-7725973,-4,3699653,1481852,0,-3922547,3454723,281197612767569,199847694865953 -13611102482445,29535436730329,-15794887502384,1961012,-5883036,-119793856,-8857196,26571588,-33075904,12,1979629,-12900208,4,-2096449,5682752,0,-2214299,-490253,281197612767569,55990044515721 -12921007845213,-25581689383342,-31866046949109,-35346060,-16920248,-18425812,-2483468,30664776,-33148244,4,-6484247,-240938,-4,-1802814,4847391,-4,-1181947,-3989124,281197612767569,133398882957105 --5894856295667,-19526343862110,2240804252136,9967668,-6645112,54593440,-1643820,1095880,329862304,-8,22891770,-3734328,-12,-6895133,1222688,0,136985,830639,281197612767569,245934070336793 -5951050967602,27645105631539,42723638546125,-4677432,-33974068,33974068,31489096,-11991028,11991028,0,-2997757,8493517,4,-4526049,-1428256,4,3346225,-258898,281197612767569,96341375244609 -16305530632121,54063213545543,11714289262596,-8332572,8332572,48689168,23612228,-23612228,-2851440,4,-435003,9005002,4,-1147863,-3167290,0,5903057,2083143,281197612767569,25839479006633 --26774824252194,43593919925470,-14439429827941,-18285704,-18285704,-26640788,7299960,7299960,-50937236,-4,-7514510,5064079,4,-5219799,1596118,0,-1824990,-4571426,281197612767569,82781156379729 -1975382975924,34196680600870,-8272542555479,-19446064,9723032,-60963164,13245264,-6622632,-74273468,4,-9218198,7120717,8,131971,-999357,0,-1655658,-2430758,281197612767569,36682090395449 --8592486751327,30316423863060,-40052320314604,3074692,32021584,32021584,-34153788,10486096,10486096,0,2621524,-8005396,4,5179999,-540000,-4,3358448,1308673,281197612767569,178144541827169 --21023217123497,49345527054167,-28572623148249,24428892,24428892,-13422436,10259068,10259068,40452028,-4,8133068,-126691,4,1979939,3482300,0,-2564767,6107223,281197612767569,152969827668425 --20793440002421,26830041949428,49575304175243,30928428,-5487664,30928428,2624428,35937744,2624428,-4,6079443,3914606,0,-656107,7732107,4,2904993,-2542690,281197612767569,159880387782001 --13976015954881,-21126263320545,-70368744177664,14456060,-31464324,0,27137756,18817628,0,0,4704407,7866081,0,-6784439,3614015,-4,1102492,-2647299,281197612767569,215750484165977 -5715628903488,-18831040695919,70368744177664,-22662912,32334404,0,21127424,19536644,0,0,-4884161,8083601,0,5281856,5665728,4,1810163,859596,281197612767569,254697152686977 --11663682253118,-13039239609985,58705061924546,20574984,-20829700,20574984,-17005624,-37505636,-17005624,-4,8610041,-3391160,0,-4251406,-5143746,4,766368,-1816265,281197612767569,41132209758697 -16278498394866,-30983640708807,39385103468857,-27982904,25239780,25239780,18537928,23514596,23514596,0,-5878649,6309945,-4,1233985,5375168,4,3400497,1620558,281197612767569,190765873185425 -23462466609393,46906277568271,-11682424024806,-15818812,15818812,33201256,-7406492,7406492,-55629656,4,-8962979,-6189358,4,4944435,2110956,0,1851623,-3954703,281197612767569,32018077841273 -14723541002871,-40921662171922,11627926741291,4976092,9952184,-87394132,-11509092,-23018184,-24129940,8,4458979,-12294485,-4,786753,-4777024,0,-2877273,-1244023,281197612767569,106259024919201 -9591203252665,-23301531957064,-47067212220600,-7068956,33178336,-33178336,-32280380,-7765024,7765024,0,-1941256,-8294584,-4,5133215,-2312590,-4,-2936880,-545351,281197612767569,137486353913353 --19488643012963,18610676620005,50880101164701,-25721228,-26462316,-25721228,19423732,-23789804,19423732,-4,-5584569,3082746,0,-4855933,-6430307,4,-362882,3532833,281197612767569,26398006748081 -3072535387157,-32835852569741,37532891607923,-31228844,13279692,13279692,21111284,27075884,27075884,0,-6768971,3319923,-4,2519499,4309126,4,2758322,3498085,281197612767569,230939541638553 --14437019636553,4598716287515,70368744177664,13367004,31087724,0,-29060324,16644012,0,0,4161003,-7771931,0,7265081,3341751,4,378896,-1812897,281197612767569,255908496379329 -4415938098983,-23005229227308,70368744177664,23683228,13482832,0,4125244,-45191472,0,0,11297868,3370708,0,1031311,-5920807,4,-371829,-2147180,281197612767569,49210748612137 --16194254855161,-54174489322503,-28682363364516,26121244,-26121244,-8290960,2565660,-2565660,42288496,-4,8400558,-1066029,-4,-2171566,-3138769,0,-641415,6530311,281197612767569,230914271807697 --29256115695649,41112628482015,13289295865979,17752956,17752956,35083756,-17311780,-17311780,29208524,-4,5083580,-4286211,4,2218551,-4484728,0,4327945,4438239,281197612767569,79169784956857 -21966396277824,48402347899840,-18408817182101,-22802176,22802176,11460012,3907840,-3907840,47412844,4,-7897520,3461951,4,3955691,596948,0,976960,5700544,281197612767569,265905831879905 -21299441801273,-49069302376391,-18895410871656,-22848284,-22848284,-11031968,8491972,8491972,-45176992,4,-8445734,389389,-4,-2848514,2368603,0,-2122993,-5712071,281197612767569,161835615447625 --3384776143419,-70368744177664,-19094948041882,17597204,0,11687320,6776724,0,-59480936,0,14870234,2921830,-4,-1174992,1053233,0,1694181,-4399301,281197612767569,138716260921841 --25526051494862,-44842692682802,-3009847778941,-8025912,8025912,-53536244,16015112,-16015112,-33455508,-4,-5158654,8614855,-4,3205223,-4769206,0,-4003778,-2006478,281197612767569,259524955645401 -27439336091691,42929408085973,14054725908239,24032428,-24032428,-28524484,6815468,-6815468,38759804,4,6251799,3150440,4,-3438152,-3980681,0,-1703867,6008107,281197612767569,198125750353921 --30978089097090,39390655080574,5787192200715,12052984,12052984,37334060,15732024,15732024,-44682676,-4,6576514,4976855,4,4594155,4356660,0,3933006,-3013246,281197612767569,259681193593449 --7797641318479,32166336889297,38202407288367,37214916,3253060,-3253060,8688068,31013444,-31013444,0,7753361,-813265,4,-320005,4960772,4,1852012,-4342957,281197612767569,130074647781137 --10499343303207,-59869400874457,-25255897358981,-11570332,11570332,-42980884,-20634876,20634876,20655820,-4,-2541964,-10180155,-4,2621991,565066,0,-5158719,2892583,281197612767569,94740846356473 --32031904728823,-38336839448841,-26345095177257,28942372,-28942372,5780316,-4256412,4256412,38051356,-4,4784202,-3496185,-4,-4728637,-2051106,0,1064103,7235593,281197612767569,148129474027297 -5934863189659,-34759565039710,-10772849956371,1527404,9164424,-250653772,3846156,23076936,105961748,24,12202079,31304179,-4,2381393,5226544,0,-961539,381851,281197612767569,188047241121417 -28422233133362,12690515718029,-41946511044302,-24167224,28502580,-24167224,-15668280,-28108876,-15668280,4,-4895312,-3157969,0,3917070,-6041806,-4,-2131907,-3967676,281197612767569,40302593790001 -32262894155741,38105850021923,20309330007668,-12596364,12596364,39193040,26311700,-26311700,7515216,4,-2915878,4397053,4,-1037074,-5401207,0,6577925,3149091,281197612767569,33606694325785 --24894119899263,-20580504379138,10721681156430,-13821436,27642872,35892536,5894596,-11789192,66152888,-8,-4387814,3677288,-4,6075204,-2647923,0,1473649,3455359,281197612767569,81895606747713 --28021718366075,-42347025811589,-5140457775964,-20484588,20484588,27878032,4072180,-4072180,49421328,-4,-7509652,3820061,-4,4845680,-3149447,0,1018045,5121147,281197612767569,112424008545961 -33153301854962,37215442322702,-18376930313867,2024392,-2024392,62878164,17515464,-17515464,-12131884,4,2747576,8181319,4,-285395,-7538222,0,4378866,-506098,281197612767569,272938558735697 --13251499882974,-18630152825105,-70368744177664,-32026488,-19349572,0,-7227448,30788636,0,0,-7697159,-4837393,0,-1806862,8006622,-4,1927859,-1208802,281197612767569,59157456361529 --11482894064728,-58885850112936,-20516083732365,20639392,-20639392,-92724,-1394528,1394528,-54544756,-4,11512656,1484961,-4,-2123533,1508142,0,-348632,-5159848,281197612767569,270188195359073 -22321190711675,3405172042639,3003398504151,6060524,-18181572,-74072228,2661004,-7983012,153252988,12,1939174,702095,4,-12124691,-5938654,0,-665251,1515131,281197612767569,50952869954249 -15777661864085,-11272729740961,54591082313579,26553940,17598844,-26553940,11572436,-34730756,-11572436,4,7199370,2349781,0,2893109,-6638485,4,-1483319,-2049930,281197612767569,137831556169329 -5992602434972,-32188070871346,2974923636921,17041008,8520504,64749284,9622000,4811000,-95580156,4,10879221,7494458,-8,2136597,1198405,0,1202750,-2130126,281197612767569,187219150603865 --11523567296329,11461614522128,-47383562359207,10929884,-24445888,-35375772,33595420,27871296,-5724124,-4,4458775,5555722,4,-5889806,3288221,-4,-2509049,-555750,281197612767569,153733793420417 --11346539999915,-24982584178004,4346598731105,-48812,195248,-202370684,5564724,-22258896,4857316,-16,87389,17958591,-4,-281735,-8158520,0,-1391181,-12203,281197612767569,231032122438377 -31711974953271,38656769224393,-4730109772269,14780636,-14780636,28265548,-7583780,7583780,61671244,4,8597152,-3633505,4,-6820659,3432882,0,1895945,3695159,281197612767569,127506334530449 -24003045862433,46365698315231,64657780451,986244,-986244,-49492084,22891300,-22891300,-7136404,4,-1170279,8152310,4,613822,-4220711,0,-5722825,246561,281197612767569,279074764658809 -1428364862713,3555813611500,70368744177664,-22376476,-22663248,0,22358820,-27670864,0,0,-6917716,5665812,0,-5589705,-5594119,4,422872,167671,281197612767569,52956438807457 -21176482584443,49192261593221,8861832549779,22352364,-22352364,7645772,-5362292,5362292,48536300,4,8313672,-2039953,4,-3820403,-128510,0,1340573,5588091,281197612767569,101315627779849 --24368383131189,11341189471136,46000361046475,-12158164,42266240,-12158164,-23902292,-9511296,-23902292,-4,-591323,-7397284,0,5975573,-3039541,4,-1786501,-3169276,281197612767569,51257013320881 --15059074734856,25191519973096,-2004739683997,3257312,9771936,151337356,-5473568,-16420704,91346668,-12,8058415,-13614028,4,4926084,-8073437,0,1368392,814328,281197612767569,149049461821081 -25829897639014,-7239521784371,-44538846538650,-20055656,16311092,-20055656,-22275048,-38022668,-22275048,4,-5443557,-3096796,0,5568762,-5013914,-4,-4062110,-980977,281197612767569,144757295134401 -27802045863288,-42566698314376,-9818289787787,-10979872,-10979872,-42123820,-22365472,-22365472,16737972,4,-3311381,-5987276,-4,-873112,-4543679,0,-5591368,2744968,281197612767569,278987667242793 -11961728836653,22521828831052,2703616278316,1522868,-6091472,162778288,-6449484,25797936,49947824,16,3748712,-13082988,4,-2184561,6902896,0,1612371,380717,281197612767569,24020655325649 -4612019606714,6849878514451,70368744177664,28388072,16105548,0,-8635096,34762028,0,0,8690507,-4026387,0,2158774,7097018,4,-779723,-426950,281197612767569,236429793929401 --2265437113225,2392502107326,-70368744177664,-18999844,-32556296,0,24110492,-17944968,0,0,-4486242,8139074,0,-6027623,-4749961,-4,-60507,-423524,281197612767569,31571357036001 -1630326644623,-2210819460334,70368744177664,-25402820,21775432,0,12377692,33711624,0,0,-8427906,5443858,0,3094423,6350705,4,292480,73399,281197612767569,181618939845449 -79257724128,-17572371613384,-1490436804481,-4975744,-1243936,-447879684,5555072,1388768,-405084292,4,-25296606,27954365,-16,-84649,152461,0,-347192,-310984,281197612767569,242696745569009 --27135863673426,16097016830812,-12247651961165,5914296,11828592,-81875252,-9577352,-19154704,-57784020,-8,4138025,-4167599,4,5153990,-8150607,0,-2394338,-1478574,281197612767569,183132164630233 -4593523981389,65775220196275,26043982479344,6561076,-6561076,75382720,9916660,-9916660,-57666624,4,12558010,18222549,4,-1858646,-623131,0,2479165,-1640269,281197612767569,188339549825281 -13946097456345,7438387209377,70368744177664,-28061852,-29626748,0,18881220,-20187932,0,0,-5046983,7406687,0,-4720305,-7015463,4,1499205,-726326,281197612767569,182062283725673 -26833380847621,-19332281195113,-43535363330043,-24572908,31349340,-24572908,-21445868,-18458788,-21445868,4,-1382050,-6536479,0,5361467,-6143227,-4,-3232647,-1300856,281197612767569,215976105269265 --459796783441,70368744177664,15525489830962,16375484,0,25995464,12828700,0,-48390136,0,12097534,6498866,4,-628554,945697,0,3207175,-4093871,281197612767569,180294832441593 --17103388103237,1955191764716,1827605036569,1272556,5090224,-301435804,-3225940,-12903760,-120612444,-16,754019,-2126895,4,7349773,-18308014,0,-806485,-318139,281197612767569,65025229236257 -13983886229202,-56384857948462,8192302449039,-14847160,-14847160,44493372,-12652792,-12652792,-37915300,4,-7963423,-8480754,-4,-1515402,-2642589,0,3163198,-3711790,281197612767569,35137469693833 --14213101159212,-41942541859240,10501607889701,-2874544,5749088,100546708,10082640,-20165280,39005716,-8,-5059885,15196943,-4,2345772,-4969867,0,2520660,718636,281197612767569,67574931614001 --12241935317250,-58126808860414,14468069727369,-15244296,15244296,-32362972,8014264,-8014264,-56843196,-4,-12150510,5899639,-4,2060289,-2191104,0,-2003566,-3811074,281197612767569,52462604652313 --5252945858766,13428175083945,-70368744177664,242888,48603812,0,23158856,-1199004,0,0,299751,12150953,0,5789714,-60722,-4,1082451,-918642,281197612767569,8302573857601 --2738648572556,30938978464237,39429765713427,796112,-36932684,36932684,-30495408,474004,-474004,0,-118501,-9233171,4,-4276490,-470863,4,3347362,-271835,281197612767569,77001925937065 --12912005978612,28728369099526,-9084866983137,2353200,1176600,-143732612,15456304,7728152,12844156,-4,1560355,14631902,8,90329,6669349,0,-1932038,294150,281197612767569,77536887504465 -17018375881917,23822785616906,-53350368295747,-9601292,37947432,-9601292,24854036,19034216,24854036,4,-5711253,6379892,0,6213509,2400323,-4,952699,3106966,281197612767569,47536046438713 -13900307224569,42568129728526,-21846671812644,-12231708,24463416,6123376,-1922524,3845048,-91085200,8,-13476598,-2824780,4,4647351,-646968,0,480631,-3057927,281197612767569,128579411047009 -23463905233691,-46904838943973,-2252173449840,-12492692,-12492692,34166336,12204300,12204300,56747072,4,-9358651,5793418,-4,-4828117,2748166,0,3051075,3123173,281197612767569,26788323996617 -1621312160263,6285128049919,70368744177664,25365532,9156604,0,9748380,-40867972,0,0,10216993,2289151,0,2437095,-6341383,4,-453076,513651,281197612767569,28166792681329 --1727525013158,70368744177664,34391170669261,7486824,0,70227764,-11119448,0,46081748,0,11520437,-17556941,4,-1075774,-1345771,0,2779862,1871706,281197612767569,9795425797977 -564985795673,-15632272085071,70368744177664,-12268188,28236484,0,-28539868,-26086524,0,0,-6521631,-7059121,0,7134967,-3067047,4,1637380,-624661,281197612767569,6034387926401 --905481910254,34731631133705,-1232315800648,-15624120,-7812060,72789728,14382856,7191428,77116384,-4,-9546994,8947435,8,-185108,302562,0,1797857,1953015,281197612767569,257531606107113 --9197368084301,-27702198367150,-70368744177664,3126988,44607816,0,-25182772,815944,0,0,203986,-11151954,0,6295693,781747,-4,-2505099,1149836,281197612767569,10219909493905 -8048354899397,15725111319824,-70368744177664,-12049644,40645696,0,28025908,-1098176,0,0,274544,10161424,0,7006477,3012411,-4,1597119,1835378,281197612767569,149906242025849 --12442352525782,-57926391651882,23380703560019,-1994584,1994584,-72984244,-15575768,15575768,-5457652,-4,-170638,-14854177,-4,-1535051,3391884,0,-3893942,498646,281197612767569,139776283135137 --18373020211923,14670577477512,51995723965741,19873972,-23757280,19873972,16706580,36680992,16706580,-4,5905177,5424424,0,-4176645,4968493,4,3265071,514896,281197612767569,209835732875273 -13136353659884,-28616195258890,6083037286551,1376176,688088,-118421924,18842032,9421016,14889180,4,1717311,12024512,-8,287673,5556457,0,-2355254,172022,281197612767569,247090979853745 -5459564793791,-70368744177664,17792879491655,-5610756,0,-51057380,-20661284,0,12652284,0,-3163071,-12764345,-4,-1551469,-635650,0,-5165321,1402689,281197612767569,249745255993241 -12203250283254,58165493894410,31694715066769,15414232,-15414232,-30211516,-7902632,7902632,-57553916,4,12783103,-4507392,4,-1605376,3045487,0,-1975658,-3853558,281197612767569,275095744077761 -6522771840242,18138997116293,70368744177664,20343752,21332500,0,-16297848,38253812,0,0,9563453,-5333125,0,4074462,5085938,4,-1936753,-816656,281197612767569,136915707973673 -6799104269635,-27314559517668,43054184659996,26282252,25165936,25165936,21068556,-22665104,-22665104,0,5666276,6291484,-4,3770111,-3412222,4,1497028,-3158341,281197612767569,187451146336977 -18299754118665,-52068990058999,-17731878456637,-23350236,-23350236,-41204,-1568572,-1568572,-48220692,4,-8821349,-1463356,-4,-3233824,1473657,0,392143,-5837559,281197612767569,183901358361017 --30663375060645,-13489747322714,-39705369117019,-23185044,26413720,23185044,-17889748,-28180456,17889748,-4,-4832556,-2614819,0,4472437,-5796261,-4,2212558,3988611,281197612767569,53900268058337 --7690523191760,-34749340052045,-35619404125619,-21718848,-29218100,29218100,-20450624,24327788,-24327788,0,-6081947,-7304525,-4,-1923246,3546727,-4,3189410,-1882985,281197612767569,276122042616905 --2384734177011,-70368744177664,24364642067120,20189236,0,-26817856,-10383180,0,-41975104,0,10493776,-6704464,-4,-1254399,-1520384,0,-2595795,-5047309,281197612767569,126144215622641 -1733742962484,21745690921689,70368744177664,-22459184,-4610204,0,-8457392,48394884,0,0,-12098721,-1152551,0,-2114348,5614796,4,951474,-1706715,281197612767569,22856286840793 -10070815718890,50227112739884,-14552311464537,12586920,-25173840,31685276,-2720984,5441968,82600412,8,15020779,-4352509,4,-2814662,1784405,0,680246,3146730,281197612767569,45804618666497 -15879998863239,-38608746451186,-17255092767972,-11541988,-23083976,-58139536,8066748,16133496,-56914192,8,-8795704,6559654,-4,-2716422,3987615,0,-2016687,-2885497,281197612767569,31384100645993 --15068369213179,55300374964485,22161387651626,-19992556,-19992556,-43900760,17881876,17881876,-17049944,-4,-4757636,7050949,4,495150,3924241,0,-4470469,-4998139,281197612767569,117227374629137 -16567665283713,53801078893951,-12649720314515,11150852,-11150852,-34750028,22185636,-22185636,31831508,4,5087228,7143243,4,-2870649,-1544264,0,-5546409,2787713,281197612767569,156584691722745 --304498061465,70368744177664,-23006702099809,9552284,0,58404476,-10602404,0,53041980,0,13260495,-14601119,4,923981,717586,0,2650601,2388071,281197612767569,57364101476641 -20951272890235,-49417471287429,28963568450258,-16240148,-16240148,20603720,4091788,4091788,64136968,4,-11681321,1946216,-4,-4352921,3204714,0,1022947,4060037,281197612767569,112748090585225 --16011104743279,54357639434385,-16730074611080,-21963196,-21963196,18950624,10379716,10379716,42307040,-4,-8787155,2354260,4,-1789605,2383396,0,2594929,5490799,281197612767569,215223026745905 -11389885792100,36199086801364,-21255462117145,-7541360,22624080,59180956,-4375024,13125072,-114963588,12,-13793757,-9319414,4,4982380,1825275,0,1093756,-1885340,281197612767569,145582235144217 -28863934654817,12640874868030,-12280809217028,-1769084,3538168,94838768,11675972,-23351944,10494192,8,547562,4413524,4,1585555,-9648084,0,2918993,442271,281197612767569,62286936069185 -429860259535,-70368744177664,28256098564156,-4587716,0,100823280,-8499748,0,-58619024,0,-14654756,-25205820,-4,763733,-614516,0,2124937,-1146929,281197612767569,280060053657769 -12035425936379,-14610497939151,58333318241285,22430700,21594308,-22430700,11496428,-39126844,-11496428,4,8705453,3310930,0,2874107,-5607675,4,-1076258,-2087647,281197612767569,188365602305873 -10243958148878,-30062393014393,-4564846228684,9061432,4530716,-118891312,10763000,5381500,107286864,4,11371292,12771435,-8,4079132,4179958,0,-1345375,1132679,281197612767569,65183408970297 --351245440035,18992975755930,70368744177664,-31614092,-18922904,0,7403188,-31182616,0,0,-7795654,4730726,0,-1850797,-7903523,4,460630,2156825,281197612767569,124546590358369 --14422816451141,-41523111275382,-14918015249032,-7795988,15591976,68384224,11107212,-22214424,46991072,-8,-8109462,9261656,-4,1819153,-3917200,0,2776803,1948997,281197612767569,125176078705865 --15003426031154,25358466084202,-5530630390681,-3084488,-9253464,-130910820,6827576,20482728,-75246308,-12,-6376583,11975754,4,-4144998,6917317,0,-1706894,-771122,281197612767569,279202987733105 -31288891229054,7790961719556,-14011202466097,-1747464,3494928,82976572,13181368,-26362736,18401052,8,802955,2470683,4,2701609,-9136730,0,3295342,436866,281197612767569,255219198953561 --15235090808366,27566826684649,-3279134093672,-4948152,-2474076,-148055456,-13415224,-6707612,53677152,-4,-5178839,-14528936,8,-3061610,-7955992,0,-1676903,618519,281197612767569,261382826387073 --12431367869187,-16722879687053,-41214496621424,-17489932,33041868,-15551936,-29765932,-8140564,37906496,-4,-3444054,-5762065,-4,6032570,-1874081,-4,-1408913,2498402,281197612767569,98325301761257 -29590535860724,-2759678363719,-40778208316940,-18778160,-42542364,-18778160,24341456,-4811804,24341456,4,-935754,5979145,0,-6085364,-4694540,-4,-267197,4656446,281197612767569,173373032279441 -27255480386989,-43113263790675,-14747688781382,-26950988,-26950988,-28131608,-5449516,-5449516,36087592,4,-5813027,-2896814,-4,-3208871,-4136088,0,-1362379,6737747,281197612767569,234811489704569 -26428760303063,16364286507949,43939983874601,26434396,-19621196,-26434396,17071132,29921012,-17071132,4,5663330,1526157,0,-4267783,6608599,4,-1816923,-3379142,281197612767569,173932927800737 --18675271311661,-33018201554342,-6689304970250,-12923060,25846120,41506776,5402604,-10805208,69771032,-8,-8441224,4254682,-4,4500767,-3061006,0,1350651,3230765,281197612767569,205253085194505 --23676043334767,23016657508130,-12125542540115,-14661052,-29322104,-22995276,-7176252,-14352504,65539636,-8,-4740995,-3143515,4,-5821957,-1302652,0,-1794063,3665263,281197612767569,217019846258353 -20775218963448,-21204315948979,-28389209265237,28880864,-6484684,35365548,-15460640,-35512876,20052236,4,5092376,-3318225,-4,-79317,-5523162,-4,3785843,1697054,281197612767569,173232430272665 --21582313632306,48786430545358,-4148932593579,16269112,16269112,4713812,5638072,5638072,-67571180,-4,11628617,1056824,4,5264178,121629,0,1409518,-4067278,281197612767569,40971486038209 --1023521604773,12039215668947,-70368744177664,-30072468,-7155892,0,5312140,-36175508,0,0,-9043877,1788973,0,-1328035,-7518117,-4,-95666,-1312277,281197612767569,250407468278057 -14624762010218,11773408049089,55743982167446,27623848,-5391612,-27623848,8529320,39093508,-8529320,4,8098933,-87670,0,-2132330,6905962,4,-1674444,-1435573,281197612767569,75544535970769 -22462523381917,-47906220795747,-671315412870,-1356172,-1356172,53459432,-20846700,-20846700,-8440792,4,-1386879,-9101874,-4,-723319,-4262984,0,5211675,-339043,281197612767569,278023562488505 -176249602114,-70368744177664,14586524205523,-8472312,0,22371148,1480072,0,128983564,0,-32245891,5592787,-4,-4065,453058,0,370018,2118078,281197612767569,89083797110753 --3532281699562,-27108159690951,-43260584486713,-23497640,16160996,-16160996,-21557864,-33088572,33088572,0,-8272143,-4040249,-4,3728516,-3408603,-4,-1660950,2465807,281197612767569,163303028145481 --327420916375,4030305472476,-70368744177664,-21532252,27610992,0,-11461596,-37591696,0,0,-9397924,-6902748,0,2865399,-5383063,-4,207841,-276192,281197612767569,72622763506929 -9776644989096,30296049594284,-10440599644535,-4267360,2133680,-161802716,-12511328,6255664,53295940,4,-5968450,-17336199,8,1387085,5778281,0,-1563916,533420,281197612767569,103719257614553 --29476246242959,-11416251691746,1478611164666,6947268,-13894536,-69578776,-12771196,25542392,-34156696,-8,1251174,-2895012,-4,-3644000,7249841,0,-3192799,-1736817,281197612767569,242503385529089 -27621018738683,15126706700298,-13430544217585,13251564,-26503128,9702460,2086924,-4173848,-83435556,8,4683053,-743175,4,-8087918,-1584395,0,521731,-3312891,281197612767569,116176173710697 --10545007757996,59823736419668,-5664648168123,-16775856,-16775856,33898772,-11779760,-11779760,-43311084,-4,-9442257,-6867118,4,-1385514,-1607575,0,2944940,-4193964,281197612767569,263645311519249 -33043998052774,-37324746124890,8485417293107,16969368,16969368,-12703540,8842840,8842840,59729068,4,8186900,1172979,-4,6745367,2002906,0,-2210710,4242342,281197612767569,269403634699001 --19698272183719,-50670471993945,14353508727723,4187492,-4187492,49472172,22962852,-22962852,2417260,-4,735816,8692329,-4,1340131,-3675714,0,5740713,-1046873,281197612767569,277334381345313 --28193212076142,-10756979024337,42175532101522,2700872,33348796,2700872,-31626744,26356700,-31626744,-4,2740562,-5100121,0,7906686,675218,4,3848613,-3237078,281197612767569,221310243938697 --21651901349687,-48716842827977,-1889659353570,-16072924,16072924,-37494664,-17036636,17036636,30306680,-4,-5131015,-6597368,-4,2445655,2776298,0,-4259159,4018231,281197612767569,162544506542897 -10779675560791,-48809393056082,9640687682548,4256092,8512184,82100176,12521276,25042552,-23002544,8,3131052,14528194,-4,1309792,2998425,0,3130319,-1064023,281197612767569,23249925804313 -19734744504191,-30899255169282,-9080059218120,-10255876,-20511752,-45941536,3718716,7437432,-93122848,8,-10462596,4381602,-4,-6409058,3551891,0,-929679,-2563969,281197612767569,61554057772353 -27433252932037,42935491245627,10808577428812,5272340,-5272340,44664112,21863412,-21863412,-28334672,4,3482550,7015409,4,-3601118,-4150619,0,5465853,-1318085,281197612767569,274807456197033 --22593104924168,-25182534329328,18867965653303,9955296,-19910592,-51443492,13305824,-26611648,44338396,-8,2182949,5937117,-4,-4450825,-3461878,0,-3326456,2488824,281197612767569,89336215138385 -10883106298948,29742818939358,8932630770465,-13115120,6557560,52373636,-3874928,1937464,-156220892,4,-16568991,-5326098,8,5917241,2441213,0,484366,-1639390,281197612767569,128568344394553 -9409881713801,-23087236620508,-37871625843355,-36540892,-11768688,-24772204,3139684,31823248,-28683564,4,-6634417,448432,-4,-536474,5744619,-4,-1321395,-3390604,281197612767569,61424673981537 -11839915632399,58528828545265,24773339548357,-6193092,6193092,-43550956,-23797156,23797156,14453364,4,-910928,-9600889,4,2702413,1286850,0,-5949289,1548273,281197612767569,164217843422665 -28297943043851,-42070801133813,13902762479382,22065196,22065196,-35707816,13843884,13843884,28622680,4,4961888,4247231,-4,2193782,4679723,0,-3460971,5516299,281197612767569,93033616099697 --35127142060045,-17764363566677,-35241602117619,30184396,10549932,-30184396,-1772500,-37920244,1772500,-4,4859606,3225875,0,-443125,-7546099,-4,-4620455,588392,281197612767569,25703003982169 --5141221049968,-65227523127696,-546060966417,10069568,-10069568,54066108,12882496,-12882496,-42642692,-4,9856800,12548529,-4,-803873,-967998,0,3220624,-2517392,281197612767569,114612209799041 --29120106516131,-41248637661533,-4785039864789,14463348,-14463348,-40819540,8353876,-8353876,54268108,-4,8094713,5736008,-4,-5472314,-4468877,0,-2088469,3615837,281197612767569,54402923668969 --21271495277509,49097248900155,-22316278399512,3720428,3720428,-55552096,20237292,20237292,450464,-4,1683054,9394899,4,-1570438,4493125,0,-5059323,930107,281197612767569,93473765009041 -34054151847619,36314592330045,3468879485841,-15560948,15560948,21891652,12446444,-12446444,54844132,4,-7229124,2632587,4,6481909,-2840326,0,3111611,3890237,281197612767569,241838780349305 -2161471222057,22735757651869,8726886866738,9502884,-3167628,-81890104,-2284572,761524,-335752376,4,27143551,-6516352,12,-2507441,923470,0,-190381,-791907,281197612767569,206461741129377 -12607640904282,-5714068107277,-70368744177664,-23994008,10032076,0,-26802136,-35718036,0,0,-8929509,-2508019,0,6700534,-5998502,-4,-2143954,37739,281197612767569,249963636201993 --12747391147869,57621353029795,-14947263804885,-11692404,-11692404,47914156,15420172,15420172,33103148,-4,-7595480,9187705,4,-680307,2790834,0,3855043,2923101,281197612767569,224768177276849 --25672258623990,-44696485553674,4820840440041,-4444120,4444120,44154788,-26413208,26413208,9083844,-4,1894839,-7087622,-4,-376122,3951075,0,6603302,-1111030,281197612767569,8012292231577 --8939989324756,706887867129,-70368744177664,7897264,-41064476,0,-26133072,-6680668,0,0,1670167,-10266119,0,-6533268,-1974316,-4,-277816,1284425,281197612767569,90841787150785 -1999965365977,70368744177664,24865068821274,16062308,0,27460712,-16886332,0,41226280,0,10306570,-6865178,4,-1784638,-1223803,0,4221583,4015577,281197612767569,44323357454889 --4610593600175,-65758150577489,6519195808371,-7286460,7286460,61185484,13246276,-13246276,43288524,-4,-9806265,14462906,-4,1015866,-833465,0,3311569,1821615,281197612767569,241042865122513 -28771707681563,-41597036496101,-22757227462185,3743852,3743852,-44905636,24391244,24391244,8172220,4,-764320,6938951,-4,2807375,4287458,0,-6097811,935963,281197612767569,160385428769721 --4965630575315,13272382667309,-70368744177664,-6774604,-29846348,0,32812532,-21634572,0,0,-5408643,7461587,0,-8203133,-1693651,-4,-1165543,-845976,281197612767569,122015889901793 -16683713175553,-26308497079798,53685031002111,20798468,-21323736,-20798468,-19228188,-34419992,19228188,4,4767648,-6010985,0,-4807047,-5199617,4,-3837350,-680051,281197612767569,223476972301897 --23984194536591,46384549641073,16929992316738,-11793980,-11793980,46863624,-18822076,-18822076,-20674040,-4,-2274797,-8432082,4,-2893713,-3283824,0,4705519,-2948495,281197612767569,135971565884913 -26625957180241,-43742786997423,14112010714103,21391684,21391684,2569180,-3617948,-3617948,52198076,4,7930484,-1471757,-4,5119035,829462,0,904487,5347921,281197612767569,178966901074393 --13321908555543,-7333704509564,-70368744177664,-917596,-33763824,0,32861284,-17848048,0,0,-4462012,8440956,0,-8215321,-229399,-4,1700915,-1574098,281197612767569,246705896825857 -33010200095423,37358544082241,-6295141139424,3198716,-3198716,43020416,-25149284,25149284,13745280,4,2386791,-5638312,4,-1049529,5116792,0,6287321,799679,281197612767569,145223094029929 --7158599117489,-56051545942686,17825479563460,8141116,-16282232,-67448048,6615612,-13231224,83488528,-8,15787578,14462408,-4,-2542277,-1199802,0,-1653903,2035279,281197612767569,135279178597137 -23547351251189,46821392926475,4284476518426,16084948,-16084948,22812776,5783796,-5783796,-61794136,4,10190984,4039583,4,-5257550,-1663611,0,1445949,-4021237,281197612767569,93950153108473 -14048044506779,-5722513190423,-70368744177664,14724716,39420836,0,-26704340,4970724,0,0,1242681,-9855209,0,6676085,3681179,-4,-294829,-2266802,281197612767569,263876044014369 -1157118790366,-34605812693649,4821607719722,-10685576,-5342788,-99834712,-15091272,-7545636,69735784,4,-8444379,-12365654,-8,-545188,-227370,0,-1886409,1335697,281197612767569,98209244959369 --27927174532754,42441569644910,4977868996103,-10662472,-10662472,-57279460,-13455688,-13455688,33309852,-4,-5260514,-8448189,4,-3066949,-5871676,0,-3363922,2665618,281197612767569,175224588317745 -10757936171131,6635823916647,70368744177664,23647724,34217372,0,-18646964,20629884,0,0,5157471,-8554343,0,4661741,5911931,4,-1228077,750284,281197612767569,214031480836633 -4281599269830,33043572453917,7387429906993,16160536,-8080268,-73874236,-13937256,6968628,-75628412,4,9061243,-8460348,8,-784617,1547863,0,-1742157,-2020067,281197612767569,238741798856257 -2044311565844,21250686397191,-70368744177664,4524112,-45961188,0,-23290928,-12250180,0,0,3062545,-11490297,0,-5822732,-1131028,-4,-1669438,-675369,281197612767569,57320160836265 --21890568980673,26587606216318,1924010489302,9699580,19399160,52739928,-5652228,-11304456,85344088,-8,8138716,-4849114,4,6598653,-4167934,0,1413057,2424895,281197612767569,124663662225745 --27328381767045,-43040362410619,-5043666980916,-21856788,21856788,-4649168,4955596,-4955596,52566704,-4,-8126777,-1102550,-4,5014899,59742,0,1238899,5464197,281197612767569,67624928517177 -13036486335839,-31259285170147,-555026381675,-4318852,-12956556,-120447404,6190396,18571188,-88051820,12,-9815240,13350773,-4,-4065905,5587026,0,-1547599,-1079713,281197612767569,275266281229665 -14196460744357,-16437335295436,56172283433307,22120084,22321360,-22120084,16495092,-34254256,-16495092,4,7799184,3162791,0,4123773,-5530021,4,-764380,-2417549,281197612767569,176321310656201 -29914312649425,40454431528239,4582311203801,-16627900,16627900,31116132,-17257532,17257532,-35417116,4,-5371201,-4201408,4,3483078,3577625,0,4314383,-4156975,281197612767569,91844434272881 --20517394777139,538468883522,-49851349400525,-26993868,22882568,26993868,6072020,36562248,-6072020,-4,-6463835,4104316,0,1518005,6748467,-4,2676727,-1616326,281197612767569,227178135390809 -6259963640893,-64108780536771,29331068362105,12803316,12803316,-47943196,6834868,6834868,62344356,4,14911786,9585381,-4,674303,2400418,0,-1708717,3200829,281197612767569,48775245019265 -459103407777,-27505980267210,70368744177664,23500420,13040856,0,-9098524,42860824,0,0,10715206,-3260214,0,2274631,5875105,4,819207,2317752,281197612767569,100237887354601 --5954944846713,-24330817071714,-70368744177664,24827420,2498168,0,11818268,-44159880,0,0,11039970,624542,0,2954567,-6206855,-4,-1955832,2093241,281197612767569,246146937036689 -403135054298,70368744177664,-9657784339389,11689832,0,-44735220,-9344088,0,-60556052,0,15139013,-11183805,4,-407338,-337023,0,-2336022,-2922458,281197612767569,53416353799289 --15661299730079,-19130879801732,54707444447585,8864132,37005808,8864132,26382020,-16878352,26382020,-4,1487380,7794909,0,6595505,-2216033,4,2732208,1456543,281197612767569,14349113190305 --7877547354846,5923799622039,-70368744177664,18582664,-27964836,0,17009224,34991740,0,0,8747935,6991209,0,-4252306,4645666,-4,-1337271,-391560,281197612767569,30450896194313 -17845275418337,-16832917922653,-5763516486420,-3483772,-10451316,-129924176,6819076,20457228,-68872784,12,-4537652,7555793,-4,-4226848,8308417,0,-1704769,-870943,281197612767569,272174906777777 -10115729517434,-60253014660230,27896487352603,-17791512,-17791512,-13133716,6648616,6648616,-58374964,4,-11836912,4574711,-4,-2756829,-1291282,0,-1662154,-4447878,281197612767569,256797090435737 -27274186107937,-15820371961790,-4960872880731,11209860,22419720,5399188,704068,1408136,-100099244,8,5650921,-91675,-4,9686945,720736,0,176017,-2802465,281197612767569,156038071999169 -9202779498735,11067094990785,-70368744177664,25036732,6675204,0,-9512868,42433636,0,0,10608409,-1668801,0,2378217,6259183,-4,1761390,766155,281197612767569,257753712608041 --7248915001626,31559914588019,2997591733386,-23993448,-11996724,-13735384,-6746216,-3373108,89988648,-4,-10125750,-1412297,8,-2245662,-609252,0,-843277,2999181,281197612767569,140410657285585 -28384851933992,-41983892243672,23073028027485,13061280,13061280,40549748,-13763168,-13763168,43472532,4,5356029,-7118926,-4,5512104,-3018511,0,3440792,3265320,281197612767569,166200313064633 --9215982276465,-51936779624734,-16651079256148,-7821764,15643528,71282352,6536188,-13072376,84378032,-8,-16342456,12227354,-4,2376026,-2796617,0,1634047,1955441,281197612767569,200266949890529 -29548635902985,-40820108274679,4211989922005,-18019292,-18019292,14290772,4218116,4218116,59137716,4,-8639399,1802838,-4,-6145030,1769855,0,1054529,4504823,281197612767569,110632736563017 -4088725475694,-33140009350985,6505572839395,21024184,10512092,45732748,-9697096,-4848548,86011660,4,10014690,-5627395,-8,1473535,-178397,0,1212137,2628023,281197612767569,132608302264049 -4302230500191,-70368744177664,-30184396486363,-3640964,0,-47452012,23077212,0,-8470220,0,-2117555,11863003,-4,2345256,1115729,0,-5769303,-910241,281197612767569,29302767266521 --6180705916765,70368744177664,-20275747553551,-17779060,0,-34138172,12830412,0,-38691196,0,-9672799,8534543,4,-1773817,-531080,0,-3207603,-4444765,281197612767569,80977793289473 -24935019449320,-45433724728344,-16662649136187,17010592,17010592,-25707756,8230560,8230560,53749492,4,8188638,5156553,-4,5248735,1270386,0,-2057640,4252648,281197612767569,125865514360681 --20857831808602,49510912369062,-636893978195,18034328,18034328,-30330188,-11030376,-11030376,-43880012,-4,7743369,-5294216,4,3226634,-2288331,0,-2757594,-4508582,281197612767569,260223273188369 -14932160753260,25572261917884,-9969604904405,-8287824,24863472,-25699156,-1024720,3074160,132672396,12,-12162294,-1454149,4,7001935,1656880,0,-256180,2071956,281197612767569,13671159287033 -13710526182263,-29237165630875,-5311884792162,7999964,23999892,-42892680,-3067748,-9203244,-124290056,12,12736487,-4908234,-4,6112009,-1938312,0,-766937,-1999991,281197612767569,254398121167905 -2522145930087,-6680189944421,70368744177664,30634396,5253740,0,16464316,-33929204,0,0,8482301,1313435,0,4116079,-7658599,4,86723,-774116,281197612767569,69794979185545 --6719645462569,-13687231404003,70368744177664,-2227364,-32404364,0,-33497124,18159092,0,0,-4539773,-8101091,0,-8374281,556841,4,-2062370,-665279,281197612767569,42108335279409 -15470320802227,-54898423375437,14264291990200,-18793780,-18793780,30444256,-12515284,-12515284,-39634464,4,-8364478,-4985387,-4,-1544138,-2625677,0,3128821,-4698445,281197612767569,201101959566105 --10923653753562,-59445090424102,9851592247941,-17630056,17630056,-26839532,-6210792,6210792,54407380,-4,-11707747,-5051228,-4,1894098,1658655,0,-1552698,4407514,281197612767569,55047468339009 --19331363303530,51037380874134,33014778337513,-12507560,-12507560,-44130396,16781464,16781464,-30807548,-4,-7554394,6534739,4,-147493,4497860,0,-4195366,-3126890,281197612767569,190785971588009 -130687491331,-70368744177664,-34957489140152,-1701876,0,-54388448,-20335604,0,11680032,0,-2920008,-13597112,-4,2520136,-236615,0,-5083901,425469,281197612767569,189347955335761 -15760380347139,-54608363830525,7080038374099,12034060,12034060,-48119988,12757228,12757228,42547756,4,8575487,9032960,-4,2061452,2997037,0,-3189307,3008515,281197612767569,230539465915705 --25710061817143,18948620543378,3245259027833,2656036,5312072,86757860,-12215964,-24431928,24875044,-8,1956251,-5779209,4,2131255,-7955128,0,3053991,664009,281197612767569,202178059048545 -12948699209929,31522646547877,735425021948,-7323868,21971604,44675056,2869764,-8609292,136224880,12,-15278446,4945795,4,6259258,-2074323,0,717441,1830967,281197612767569,4679388690377 -20261145807337,-50107598370327,-8158558567798,-7838812,-7838812,45457960,-23939036,-23939036,-4806872,4,-161836,-8319541,-4,-1039882,-3044949,0,5984759,-1959703,281197612767569,199154573736817 --28575960243905,-41792783933759,8345667049520,3123452,-3123452,-48389952,22360796,-22360796,14042816,-4,1422054,7277443,-4,-2088650,-4820045,0,-5590199,780863,281197612767569,87141323115353 --21055549418495,49313194759169,-6478549614825,-24105980,-24105980,-13385636,-634684,-634684,46353820,-4,-8106380,-2899939,4,-3482075,-446470,0,-158671,6026495,281197612767569,156189989151105 --21659128719380,-21107306045623,48709615458284,15544240,-35374812,15544240,-25692112,-13963132,-25692112,-4,4342944,-4956023,0,-6423028,-3886060,4,-852161,-3887680,281197612767569,78400867715049 --27573709169047,42795035008617,-1144939853299,16692644,16692644,30430260,7137956,7137956,-54436556,-4,8247418,4694471,4,5361721,2913094,0,1784489,-4173161,281197612767569,22559610312849 --17514842463694,-36406851748965,-33961892428699,-2064184,35660396,-35660396,-31130616,-7639732,7639732,0,-1909933,-8915099,-4,4231507,1969918,-4,-3551147,2485964,281197612767569,220033137950073 --5677811290039,-64690932887625,-26133337611613,-4752092,4752092,-55599476,-18968476,18968476,14996044,-4,-1685402,-13219541,-4,2063609,680328,0,-4742119,1188023,281197612767569,271512339378337 --7494782964250,-31436980606707,3540273745193,-4694120,2347060,163868836,11641048,-5820524,73324676,-4,-8116175,18331472,-8,2098819,-4304265,0,1455131,586765,281197612767569,112983771347977 --26374266624622,2166342075869,-43994477553042,32837192,18416500,-32837192,981320,-33736972,-981320,-4,5280634,2625767,0,245330,-8209298,-4,-3153609,-1978358,281197612767569,21128012183985 --15544260443242,4112920120167,-54824483734422,27260504,-21843556,-27260504,8745752,34293628,-8745752,-4,6551772,4652925,0,-2186438,6815126,-4,-2021635,-807964,281197612767569,113575293719449 --24845129164040,45523615013624,11289039690817,-9925664,-9925664,-39760636,22339040,22339040,-23946556,-4,-4768879,6032496,4,-1217760,3907663,0,-5584760,-2481416,281197612767569,256930179285953 -19466592986211,31435558205242,-10975857609991,14263692,-28527384,-23476252,5513644,-11027288,69859908,8,7372063,3734263,4,-5046457,-1067400,0,-1378411,3565923,281197612767569,112776357123113 -23430883168103,-28575414275672,-18362446733889,-26230372,14755488,-40985860,-16024676,-33909088,17884412,4,-4027741,-5123492,-4,-443362,-5122973,-4,-4449531,1434620,281197612767569,61278802042577 -1755679830008,34306532173828,-3393282512823,-7741472,3870736,133324068,12215008,-6107504,80507332,4,-9738709,16296372,8,649415,-738273,0,1526876,967684,281197612767569,199505509420473 --4139397376504,22076448933720,-362730000107,1128480,376160,219664468,15288864,5096288,-17084524,-4,1333394,17229055,12,270949,3228952,0,1274072,-94040,281197612767569,268057582492385 --31960387896955,-38408356280709,-5857579242840,-1756652,1756652,-36697440,29515636,-29515636,-24336992,-4,-2706648,5044065,-4,3377600,-4130295,0,-7378909,-439163,281197612767569,178499549237321 -24779749567936,-45588994609728,-17363846996853,-16795904,-16795904,-36641236,9836288,9836288,-45575764,4,-7988451,4898466,-4,-3405490,4261843,0,-2459072,-4198976,281197612767569,196782527023089 --8278916924921,-34769184575421,35599559602243,18213916,-24619764,-24619764,26029308,26631532,26631532,0,6657883,6154941,-4,-4075361,1579474,4,-2431966,2974005,281197612767569,62121969298393 -23974987981978,46393756195686,-5935859992267,20834920,-20834920,-2658092,399848,-399848,-54090092,4,8923763,-877492,4,-4598760,-212969,0,99962,-5208730,281197612767569,191338426267137 -2502448814142,-70368744177664,-19880258257655,-16275208,0,-26038236,-9829320,0,53453188,0,-13363297,-6509559,-4,219009,-1380992,0,-2457330,4068802,281197612767569,136401242157161 --22019020325499,-4288567875401,48349723852165,-15711724,-36772132,-15711724,-22905580,18051036,-22905580,-4,-2751685,-6555834,0,-5726395,3927931,4,-1761074,-2637199,281197612767569,271779881006353 -21098031395207,49270712782457,5744083542208,-15807972,15807972,23167744,-5579140,5579140,-63046912,4,-11149884,-3732797,4,4611844,2059139,0,1394785,-3951993,281197612767569,165830335131129 -14060703118813,-28042214806764,-42326529370900,-16661644,-34415536,34415536,-24307276,17366352,-17366352,0,-4341588,-8603884,-4,-4522696,786297,-4,1554123,-3379114,281197612767569,244696259253537 -3721626327789,20797109365613,70368744177664,-6547532,-47097420,0,23180564,-5216492,0,0,-1304123,11774355,0,-5795141,-1636883,4,1781695,-138944,281197612767569,14542437495945 --5853520331531,-30992356773231,-33522867072902,22970324,-32086460,9116136,-15969964,-26707516,42677480,-4,7879877,-4825156,-4,-2789493,-2546122,-4,1202998,3196459,281197612767569,263772726158897 -86781310617,-70368744177664,16173738586565,14571108,0,-12119276,2790020,0,74948788,0,18737197,3029819,-4,-137209,841002,0,-697505,3642777,281197612767569,217748164596761 -25920879860760,18526984456144,449740833651,10293344,-20586688,-59973172,-7370144,14740288,-66439924,8,4396699,-3914605,4,-6106641,5539344,0,-1842536,-2573336,281197612767569,110079521814593 --32100061032054,-6168622113556,-15535003417593,10083880,-20167760,-52882404,-8394776,16789552,-67629124,-8,2408755,-45849,-4,-7249263,6587376,0,-2098694,-2520970,281197612767569,240899422870697 -7489473893822,-31439635141921,-11651731437044,-11493640,-5746820,49379376,-3436808,-1718404,-181151696,4,-20162790,-5753371,-8,-4962344,-838102,0,429601,-1436705,281197612767569,108505693363025 -12907560723657,-57461183454007,-16681926060886,13782820,13782820,-39949656,-17898044,-17898044,-29810968,4,5024957,-8972302,-4,2427785,-1015112,0,-4474511,-3445705,281197612767569,218212606369337 -7435725464015,-27859659331614,-42509084846050,-27563204,-25569400,25569400,-18752772,23451656,-23451656,0,-5862914,-6392350,-4,-3451615,3487200,-4,1236578,-3403601,281197612767569,41881774841697 --24947439125139,1119845342613,45421305052525,-9920076,30900820,-9920076,-25863148,-32933964,-25863148,-4,-5211621,-5025898,0,6465787,-2480019,4,-3021870,-2699307,281197612767569,25649341032649 --7877965743555,-62490778434109,-4211986316931,-16624396,16624396,-19369484,-7411852,7411852,59090036,-4,-13007777,-4549022,-4,1764732,293349,0,-1852963,4156099,281197612767569,54332424639601 --1478021935545,70368744177664,-14188502546326,20266268,0,9779624,-4869124,0,53205736,0,13301434,-2444906,4,524824,970223,0,1217281,5066567,281197612767569,146425871699033 --6751681540771,-16355291851496,-6335060910912,401780,-3214240,377254656,2920244,-23361952,-60292352,-32,2977528,21992976,-4,-1511945,-9040086,0,730061,-100445,281197612767569,148335454194305 -25831763664706,10434200840781,34102779672177,5780744,-36907724,31126980,-33280568,17715732,15564836,4,-1569408,-5625513,4,-5460617,2156232,4,2859525,3601418,281197612767569,175648333846761 -3016302861945,-70368744177664,-33262932517075,16807396,0,4925620,851684,0,-66738764,0,16684691,1231405,-4,614530,2038975,0,212921,-4201849,281197612767569,149446172119441 --29931709128136,-40437035049528,5245104425037,7907552,-7907552,-40481484,25852896,-25852896,10032980,-4,959598,5962971,-4,-1548647,-4157400,0,-6463224,1976888,281197612767569,202119655939705 --7381506371926,318322113379,70368744177664,5198504,34931084,0,-29507800,18305356,0,0,4576339,-8732771,0,7376950,1299626,4,446676,-921925,281197612767569,60604806756769 --5376327069379,26332592985339,70368744177664,15315188,-38598676,0,-18780588,-26182772,0,0,6545693,-9649669,0,-4695147,-3828797,4,2257070,695513,281197612767569,203089656950025 -22835730924994,-47533013252670,24674689937765,9424648,9424648,-47017580,-21444088,-21444088,-12483308,4,3987905,-7113730,-4,-867078,-4640665,0,-5361022,-2356162,281197612767569,122874072453809 -19225861851669,20618305769754,-51142882325995,-19909548,-32203672,-19909548,27665908,-11801176,27665908,4,-117673,7309672,0,-6916477,-4977387,-4,-2832621,741246,281197612767569,244276497831065 -30109598437486,40259145740178,7049316945745,15976888,-15976888,-23668412,-2618824,2618824,-66590972,4,9590041,-2985146,4,-7057702,2931957,0,-654706,-3994222,281197612767569,220240757238977 -35239287060089,-35129457117575,-31878004975331,12309988,12309988,-37072780,-26297276,-26297276,-12265388,4,-1447476,-6021013,-4,4513823,-3247182,0,-6574319,-3077497,281197612767569,112713693357353 --32944491836857,373983434840,-37424252340807,28978460,10813792,-28978460,9675548,42463584,-9675548,-4,5633003,-1399274,0,-2418887,7244615,-4,-4982893,1304174,281197612767569,235138671450065 -34187605230855,-36181138946809,-17585597824095,-9889764,-9889764,48982660,-13835908,-13835908,-45317596,4,-4960759,-6914170,-4,-6368640,-5331495,0,3458977,-2472441,281197612767569,15736738410169 --34668771283143,-35699972894521,11448445992601,-7292700,7292700,-55478684,18156836,-18156836,-16260444,-4,-2800835,6739844,-4,1264276,-7129827,0,-4539209,-1823175,281197612767569,232339284961 --17080659121117,8852001115908,-53288085056547,-6830964,-39932912,6830964,28171820,-134256,-28171820,-4,-911382,7345167,0,-7042955,-1707741,-4,-877818,-2638061,281197612767569,91863819583817 --27564405678039,-18606441460673,42804338499625,27245732,-6007556,27245732,6444836,39902844,6444836,-4,6494113,-887456,0,-1611209,6811433,4,3481598,2389345,281197612767569,209929134596337 -17215130937405,53153613240259,-16150029024670,-16839436,16839436,28000648,17090708,-17090708,38442440,4,-6278850,6253817,4,3331760,-746345,0,4272677,4209859,281197612767569,221895160212697 -3216511777391,12027877114372,70368744177664,-15315524,38434832,0,21645052,19194640,0,0,-4798660,9608708,0,5411263,3828881,4,-705584,-1093665,281197612767569,190519067172609 -14886605852625,40595532472414,-6119746340098,-11674812,23349624,-10472456,-29788,59576,-96465096,8,-13911316,1002722,4,5102479,-807696,0,7447,-2918703,281197612767569,98486332621161 --15246405929960,-39875932317744,13434238816295,7630944,-15261888,-61422436,11647072,-23294144,53795228,-8,6509267,9429999,-4,-3469770,-2962805,0,-2911768,1907736,281197612767569,61846973689361 -9103921595057,26663688672517,-34601133910090,2696900,-40853484,-38156584,-28526236,14645044,-13881192,4,-485341,-8636548,4,-3955639,902598,-4,-3175920,-1576823,281197612767569,231501411192569 -23630588975601,46738155202063,-8502479701745,25789380,-25789380,1820732,3727108,-3727108,43920636,4,7180318,476689,4,-3799841,931872,0,-931777,6447345,281197612767569,174770184576545 -30083000811773,4268671479055,40285743365891,8679412,-41707460,-8679412,-27971756,4692828,27971756,4,-247453,-5837700,0,-6992939,-2169853,4,925754,4589165,281197612767569,15062111380873 -1737728370379,19473010215938,-50895733961726,-15397076,30861320,30861320,-30283348,-12425464,-12425464,0,-3106366,-7715330,4,5552484,-2593541,-4,2018353,-1255728,281197612767569,144873981017905 -6421464089362,63947280088302,-13311363918101,13861960,-13861960,-21147732,-3514232,3514232,-75860980,4,17068388,-5460029,4,-1896857,-173096,0,-878558,-3465490,281197612767569,228121362863385 -33494805587373,36873938590291,12781674187798,15811252,-15811252,-33286056,-18728076,18728076,-31782184,4,5013982,-3642575,4,-2931564,4678939,0,-4682019,-3952813,281197612767569,111059584950593 -419989169850,34974377503907,-16829874239925,3699432,-1849716,230198572,-8116568,4058284,103631436,4,13119267,-28492484,8,330675,564675,0,1014571,462429,281197612767569,26006500289961 --2907590091415,-70368744177664,-29584222777540,20099492,0,25939184,8371620,0,-45212432,0,11303108,6484796,-4,-1346930,1844595,0,2092905,-5024873,281197612767569,16701573911633 --32494677499792,19033510592785,37874066677872,21610944,29597764,21610944,21444544,-22728732,21444544,-4,4508374,2521203,0,5361136,-5402736,4,1173809,4878238,281197612767569,151996251684665 --15347146082163,55021598095501,-14298244565130,-17691084,-17691084,17450456,3357044,3357044,60330840,-4,-11963760,2512481,4,-3118950,1850133,0,839261,4422771,281197612767569,169475595610209 --14969153806447,33308487417710,-37060256759954,-32826812,-1538632,-1538632,14119972,-33636360,-33636360,0,-8409090,384658,4,-3647918,-4240299,-4,117925,-3966404,281197612767569,182282065598921 --7534247495083,-5876337237361,1992161785172,521556,-1216964,1327891792,-2431020,5672380,286773072,-28,6027092,-27713709,-12,-7658856,35547403,0,202585,43463,281197612767569,271536449596785 -24787817320121,-45580926857543,19561941551887,16922340,16922340,-16510916,5309444,5309444,61352988,4,10304252,1497643,-4,5033995,2630086,0,-1327361,4230585,281197612767569,184423218679129 --11407063162503,58961681015161,27249106017547,2458084,2458084,52226092,-21157724,-21157724,8508524,-4,3830557,-10702044,4,-1703426,-2354479,0,5289431,614521,281197612767569,210172141826945 --28303622235092,-42065121942572,-14867662997999,14696624,-14696624,28079172,-9633488,9633488,58203812,-4,8189442,-4972585,-4,-6361511,2047208,0,2408372,3674156,281197612767569,273111177030121 -4626682639186,-70368744177664,-4546733341931,-15973048,0,-26339244,-11649208,0,51278164,0,-12819541,-6584811,-4,-654701,-690962,0,-2912302,3993262,281197612767569,42583847013009 -8144220592714,54080302992236,3573046459947,9437480,-18874960,60419244,7646056,-15292112,-70350452,8,13322443,11848059,4,-2132585,-1628376,0,1911514,-2359370,281197612767569,271103630573433 -7584788211295,-55199167755074,-7386317742017,5979516,11959032,-87513860,7894076,15788152,72758204,8,13854077,17475889,-4,2167737,2201288,0,-1973519,1494879,281197612767569,14320714613409 --3592167365133,22733891626177,70368744177664,17853388,-29004028,0,16958572,35513316,0,0,8878329,7251007,0,-4239643,4463347,4,1822912,-1071817,281197612767569,219777297735177 --16090603206159,-12443879073790,54278140971505,9847748,-37611512,9847748,-24576700,-20464888,-24576700,-4,5032865,-6817440,0,-6144175,-2461937,4,83357,-2585438,281197612767569,169628105534385 --22293923143279,-10478043932700,48074821034385,-5627324,-35696752,-5627324,-32064668,-3323888,-32064668,-4,1761330,-6306345,0,-8016167,1406831,4,-930358,-2617843,281197612767569,219411774576025 -3786698891875,-70368744177664,-15813837967761,-15753844,0,30678460,-9423156,0,-53117956,0,-13279489,-7669615,-4,-1244011,472364,0,2355789,-3938461,281197612767569,40784589149633 -17820005060231,-34728734057202,3512620233754,-6734308,-13468616,82520168,-9874500,-19749000,-46189528,8,-5945376,-10013362,-4,-2801003,-5308340,0,2468625,-1683577,281197612767569,55315191248425 -16103356952051,13927430990608,-54265387225613,-19100724,34630720,-19100724,21439948,20073536,21439948,4,-4930817,5731328,0,5359987,4775181,-4,-87567,2926352,281197612767569,231511213134033 -4718575542367,13054865196862,-70368744177664,-19323524,25847032,0,22137308,28655032,0,0,-7163758,6461758,0,5534327,4830881,-4,546367,1329522,281197612767569,67252588892089 --12231286533265,58137457644399,-28619746055243,-26037828,-26037828,5978836,-240772,-240772,-43185644,-4,-8944292,1412565,4,-1852119,-2907274,0,60193,-6509457,281197612767569,43608345767137 --32312229776259,38056514401405,8156850364156,26099188,26099188,18680816,10273876,10273876,-35785616,-4,5136081,1769392,4,3810323,2900812,0,2568469,-6524797,281197612767569,252635719037513 -20813264697890,11469930223213,38085549256561,-7593848,-27720268,35314116,-33364600,26471988,6892612,4,-3300977,-5189776,4,-5024130,3638753,4,3317020,1740291,281197612767569,74446754789873 --24149680392955,-46219063784709,1905653258723,-19914732,19914732,-7898228,-5347148,5347148,54415340,-4,-8971369,-1162086,-4,4632466,812471,0,-1336787,4978683,281197612767569,26452416703961 --13782148963211,-11508067486439,-70368744177664,15801812,36982884,0,-29643884,1872164,0,0,468041,-9245721,0,7410971,3950453,-4,-1303655,1164776,281197612767569,134495907334145 -15412003143015,-39544737891634,-8970175199496,-231012,-462024,-97502240,-11548100,-23096200,-284448,8,-696078,-13683476,-4,383595,-5346042,0,-2887025,57753,281197612767569,112486135173737 -6775615618585,63593128559079,28956240539096,11498596,-11498596,37705568,15475556,-15475556,-47169696,4,9064943,9701648,4,-2727481,275256,0,3868889,-2874649,281197612767569,89880976205585 -6183382082423,64185362095241,-15996436703799,-4599332,4599332,82776868,-11774916,11774916,-32876348,4,-6827689,-19137176,4,1391398,1557041,0,2943729,-1149833,281197612767569,69986375905273 --1319281971370,-70368744177664,26047102269229,6333784,0,52660404,-20341544,0,8637172,0,2159293,-13165101,-4,1841881,832936,0,5085386,1583446,281197612767569,114641168394017 -11306108909,70368744177664,-18279123288907,117684,0,160267988,7024916,0,-261324,0,65331,40066997,4,456191,-14080,0,1756229,-29421,281197612767569,165685458081417 -19384889019955,-22769679583670,-50983855157709,30018764,7893288,30018764,3366732,-36621272,3366732,4,6905598,-998623,0,841683,-7504691,-4,2249720,2971945,281197612767569,108619537717297 -28689481180055,-6737726304259,41679262997609,-25144740,16231412,25144740,-15875012,-34529132,15875012,4,-4732880,-3005353,0,3968753,-6286185,4,3899403,1052500,281197612767569,33889913525785 --24158802628932,36059756749023,-34308987428641,26495728,19605372,19605372,-21283856,26744764,26744764,0,6686191,-4901343,4,4889774,1546849,-4,431190,5077083,281197612767569,219724197513793 -6204990287485,33929195420499,36439548757165,4662772,32457036,-32457036,34766804,542060,-542060,0,-135515,8114259,4,4512835,-1319140,4,-4178866,-153447,281197612767569,22824431287977 --33339097489373,37029646688291,2334164620207,25269388,25269388,13939388,9831564,9831564,-39132484,-4,5229632,1624257,4,4553489,1860590,0,2457891,-6317347,281197612767569,174329951456593 --2663049396398,29141955459945,-41226788717719,-3246776,-32036444,-32036444,-36271480,-11121596,-11121596,0,2780399,-8009111,4,-5207352,172447,-4,-3860518,639247,281197612767569,252580602257465 --20176780095719,30015183986226,-9414219217139,-9979804,-19959608,57034804,-6182236,-12364472,-77486220,-8,-8676313,-5414357,4,-5347621,-4422172,0,1545559,-2494951,281197612767569,265720390381921 -2511748700076,62833498077436,16212385366681,-643408,1930224,197756516,5634352,-16903056,18137924,12,-5022500,44033897,4,-162673,-1801744,0,1408588,160852,281197612767569,143751280741065 -25958801620752,44409942556912,-5247595329987,-7685056,7685056,-41974540,23790656,-23790656,-16564364,4,-3056990,6479293,4,1084101,-4014342,0,-5947664,-1921264,281197612767569,39481300256369 -29810091599209,40558652578455,-3777695222737,21025188,-21025188,-19778372,15530180,-15530180,38940828,4,5402680,3132111,4,-4332527,-1812482,0,-3882545,5256297,281197612767569,240529236790873 -22085650080722,4111793935498,4443653297283,-1046712,3140136,-138025460,-8092472,24277416,8534092,12,258602,-2065853,4,797375,10813504,0,-2023118,261678,281197612767569,165612717923457 --31452151754135,-38916592423529,11284459646190,-18250332,18250332,10107832,2020612,-2020612,60572920,-4,-8293775,2129168,-4,6849455,-397790,0,505153,4562583,281197612767569,140908268845801 --19719420541721,-22439695660865,-50649323635943,-28272740,10307324,28272740,3499676,38546940,-3499676,-4,-7215235,-399228,0,874919,7068185,-4,2421500,-2976059,281197612767569,226817789559697 -28868275763229,41500468414435,10570046390035,-27341708,27341708,34164812,-8093548,8093548,-31065556,4,-4884215,-4010490,4,2882174,4530713,0,2023387,-6835427,281197612767569,32765868220537 -17766351764282,17069688884818,-4968476780179,-670488,2011464,-213315148,5174632,-15523896,-32920076,12,-2270417,12900718,4,1986534,-13476023,0,-1293658,-167622,281197612767569,108675237514145 --10543452369396,10891064496979,59825291808268,-21788624,18784588,-21788624,9540272,43448812,9540272,-4,-8865563,4835580,0,2385068,5447156,4,-1996640,-139433,281197612767569,243859741380361 -17296696508915,35775351159834,-15256542993915,6216652,-12433304,78304276,-12164020,24328040,27893652,8,4863903,-9278529,4,-1054755,5148770,0,3041005,1554163,281197612767569,23883126342833 -8393517179778,-33726845893009,-70368744177664,804360,42892732,0,-26235832,712860,0,0,178215,-10723183,0,6558958,201090,-4,-3122368,-1375431,281197612767569,168838671619737 --24418846738913,-349370401658,-45949897438751,28867708,-18474472,-28867708,-7918916,-33934184,7918916,-4,5549477,-2980068,0,-1979729,-7216927,-4,-2934069,1638550,281197612767569,243207918911169 --21134390556451,6875477535019,49234353621213,18616180,24811692,18616180,-19978412,33852364,-19978412,-4,6409310,-3885221,0,4994603,4654045,4,2053781,-2317702,281197612767569,142164620740393 --31679161180769,-38689582996895,-6678652581191,-19916164,19916164,25634532,8140924,-8140924,46053604,-4,-6523369,3050986,-4,4990032,-3357647,0,2035231,4979041,281197612767569,40965903649233 --7332406082549,-63036338095115,-26597958783507,10912812,-10912812,42558388,14439436,-14439436,-46860588,-4,9129978,10562159,-4,-2585169,-77438,0,3609859,-2728203,281197612767569,97059146084537 -21235342606814,-49133401570850,-1388201548605,20500344,20500344,-30333172,9997048,9997048,40128972,4,6955485,5395970,-4,3076758,2187323,0,-2499262,5125086,281197612767569,162099185300961 -8971894218360,1332263838255,70368744177664,18127328,-24646468,0,18823904,36517084,0,0,9129271,6161617,0,-4705976,4531832,4,-1074870,-871395,281197612767569,129691018617673 -2451450053407,-22639098041419,6887106097573,-2117508,-705836,351441556,9150972,3050324,76348180,4,-6215337,28249256,-12,-441034,3112621,0,762581,176459,281197612767569,268951124808433 --19353416935356,51015327242308,-18779788578673,-18886384,-18886384,-26433988,-13694576,-13694576,40447004,-4,-6417039,-6051056,4,-3694712,-557441,0,-3423644,4721596,281197612767569,10642006388441 --3750456494933,-4308746468850,70368744177664,21284524,-30011336,0,-9986836,-38816072,0,0,9704018,-7502834,0,-2496709,-5321131,4,364321,-725698,281197612767569,110173197578497 --29219320120326,41149424057338,-14344018574073,24758248,24758248,10426396,14633384,14633384,-39313220,-4,5001563,2785942,4,4826742,-179343,0,3658346,-6189562,281197612767569,229876386505577 -20218705288976,-21076828961095,-29073209927593,-26330048,-27912476,1582428,17689664,-24008220,41697884,4,-5602115,3001538,-4,-4822356,-2605931,-4,-399940,3976581,281197612767569,3009673994257 -9604626941240,12048650344553,70368744177664,-23186208,-25256540,0,18552800,-28349628,0,0,-7087407,6314135,0,-4638200,-5796552,4,1761520,130679,281197612767569,71758708101369 --27807809373165,-14753125431334,826100211676,10372172,-20744344,39096176,5209612,-10419224,-88913296,-8,4690848,1988290,-4,-8768738,-3892877,0,1302403,-2593043,281197612767569,168694515298337 --2461759359708,-70368744177664,-22785132928201,3130512,0,72536284,14601232,0,-21332228,0,5333057,18134071,-4,-1368526,-380985,0,3650308,-782628,281197612767569,98575389017993 --24923296754239,-45445447423425,-6291565107553,20853508,-20853508,2178684,7363204,-7363204,-53221636,-4,8428298,817879,-4,-4877111,273208,0,1840801,-5213377,281197612767569,70590354436401 -353941433600,-19932288069201,-50436456108463,-18697216,35236540,-35236540,28398592,6697884,-6697884,0,-1674471,8809135,-4,5080216,3394593,-4,-2019432,-1279711,281197612767569,225316825995033 --15734784931645,54633959246019,5243478737494,1750796,1750796,63566168,-17352116,-17352116,13075416,-4,2861168,-12305503,4,407686,-3586039,0,4338029,437699,281197612767569,147426743710529 --3671944019439,15120569464534,70368744177664,-26893244,30917464,0,17802660,21398936,0,0,-5349734,7729366,0,4450665,6723311,4,-1235499,-1041350,281197612767569,83311615528873 -26402268626430,8614211720691,-43966475551234,26034168,-2151476,26034168,-12036104,-42252340,-12036104,4,6968179,460684,0,-3009026,-6508542,-4,3594906,-998553,281197612767569,221046442083921 --19250810757461,22779214800745,-51117933420203,32272044,-11478620,-32272044,915596,34562116,-915596,-4,6202638,4696315,0,-228899,8068011,-4,-2437891,1826660,281197612767569,137406226923833 -31427994962939,-38940749214725,-17917904014578,7791596,7791596,38851640,30487212,30487212,7518136,4,900631,4878952,-4,-2780165,4833958,0,7621803,-1947899,281197612767569,136175892904545 --12295913670587,-26333587985410,58072830507077,-19714796,34928632,-19714796,-19003276,-23441352,-19003276,-4,-6614194,-5361909,0,4750819,-4928699,4,753856,-3370249,281197612767569,27732664695753 -24872825936367,-767814998130,45495918241297,30329788,-11950536,-30329788,-7482564,-34173640,7482564,4,5503210,-2014347,0,-1870641,-7582447,4,-3040200,973287,281197612767569,69228491366257 --884109036333,-70368744177664,17036248430521,12855116,0,-46933276,-12735572,0,-41086972,0,10271743,-11733319,-4,-899873,-630638,0,-3183893,-3213779,281197612767569,228215652618073 --4336811559453,-8028812000428,-70368744177664,-5236,-36094640,0,31191500,-10302384,0,0,-2575596,9023660,0,-7797875,-1309,-4,1048442,-555977,281197612767569,50367570625921 -10050649743200,60318094434464,-1304496766985,1572224,-1572224,-53984292,-20954752,20954752,3388540,4,-823255,-11575738,4,23880,1920335,0,-5238688,-393056,281197612767569,195709972712425 --21351431957005,-24810347021840,49017312220659,28257228,22751168,28257228,18666188,-24815680,18666188,-4,2676200,6452697,0,4666547,-7064307,4,3527720,-764905,281197612767569,252486549699729 -22038426632259,26291890913146,20223516659067,3839244,-7678488,66382316,15771884,-31543768,-20557620,8,-346131,6752297,4,-2742768,-4921641,0,3942971,-959811,281197612767569,46820886528377 -10294721578472,60074022599192,-27291916656721,14120864,-14120864,-17767748,4331936,-4331936,74282364,4,15433747,5161260,4,-3136844,719323,0,-1082984,3530216,281197612767569,271034455463073 -14649727138843,55719017038821,30295120887479,-7592852,7592852,61226716,-14968820,14968820,-27579652,4,-7070587,-11302838,4,-175674,4003841,0,3742205,-1898213,281197612767569,184802315288585 --23645792568695,23077159040274,5550660575368,-678364,-1356728,-135241184,8211364,16422728,-22680032,-8,-2183312,11061202,4,-1743348,11374547,0,-2052841,-169591,281197612767569,21819797904817 --30791066736541,39577677441123,5600778897194,-25709172,-25709172,-2149208,-5349652,-5349652,-44240920,-4,-6114187,-209364,4,-4946043,746666,0,1337413,-6427293,281197612767569,184726398605209 -14119214650815,-11463457114839,70368744177664,3963644,-34402140,0,34151740,-12360604,0,0,-3090151,8600535,0,-8537935,990911,4,-770850,-1564239,281197612767569,273402939582401 --14322167827722,-56046576349942,-14625814691473,-9686056,9686056,49965500,15322648,-15322648,37197404,-4,-8202837,9445702,-4,1096514,-3045673,0,3830662,2421514,281197612767569,117762447235113 -7768148418800,20336974907025,-50031769270639,-25771072,-23480764,-23480764,22045632,-23602108,-23602108,0,-5900527,5870191,4,-3267208,-5228793,-4,-2244200,-1213975,281197612767569,32239794995921 --13781480823065,56587263354599,-7132578103138,11476892,11476892,46975608,20302076,20302076,-15003848,-4,2501894,9734723,4,1249068,2009179,0,5075519,-2869223,281197612767569,265809410036153 --8825913407688,-61542830769976,3268798149919,-15188768,15188768,30439548,8223456,-8223456,57646652,-4,-12508598,6831815,-4,1903065,-778072,0,2055864,3797192,281197612767569,196588550160097 -24577125053491,-45791619124173,8434283742700,-17062708,-17062708,35186608,-9289620,-9289620,-46829008,4,-7896714,-5213039,-4,-3810538,-3583613,0,2322405,-4265677,281197612767569,247887623574601 --32940023148921,-37428721028743,-4391025243931,-20169188,20169188,14741396,-2551908,2551908,-53957612,-4,-7214744,-1645575,-4,6274659,2039774,0,637977,-5042297,281197612767569,151728647597041 --2524033586223,2210147715114,-70368744177664,-25998524,-12371800,0,-9906844,38591976,0,0,-9647994,-3092950,0,-2476711,6499631,-4,268272,315081,281197612767569,73764411256793 -26736378154413,43632366023251,2374008284538,-5840204,5840204,-56922648,17830516,-17830516,-18995864,4,-2794226,8873025,4,1954740,-5357637,0,-4457629,-1460051,281197612767569,104541364525569 --10628162966309,59740581211355,6194717031924,13428588,13428588,-45111344,-14281844,-14281844,-35865776,-4,7297879,-9870022,4,1668565,-1407814,0,-3570461,-3357147,281197612767569,225644303627369 -15573499986410,54795244191254,7711741848705,5906344,-5906344,-44855804,-23636568,23636568,-11117308,4,2811812,-8570341,4,32485,2643610,0,-5909142,-1476586,281197612767569,70894887213329 -14803583631447,-40761576914770,26603052350701,-12663460,-25326920,-35086412,-8746052,-17492104,64676820,8,-7712891,-7474735,-4,-4228157,-648434,0,-2186513,3165865,281197612767569,104031725974009 -16775839607338,-8302982187333,53592904570326,770216,34967276,-770216,32012584,-8448340,-32012584,4,2552877,6635058,0,8003146,-192554,4,440792,-2106761,281197612767569,98547074890017 -15361812719709,24939904723428,-30067026734527,-31748748,5609360,-26139388,-6202156,36558608,30356452,4,-6594887,-1716874,4,994226,4817973,-4,-2544765,3119214,281197612767569,198686618482825 -858470359951,-33194756385937,-37173987791727,34304572,-4148804,4148804,16662204,30805564,-30805564,0,7701391,1037201,-4,-2106599,4543208,-4,2058952,-4032935,281197612767569,64363025877553 -12814446501949,-11683153050607,70368744177664,19983604,-32854972,0,-22933100,-18636956,0,0,4659239,-8213743,0,-5733275,-4995901,4,-1800349,666300,281197612767569,36112574142489 -26274158561825,17820427054014,-14456661274454,-11697020,23394040,44456616,-9331644,18663288,-60788696,8,-2890032,-4016114,4,6153571,3549020,0,2332911,-2924255,281197612767569,220564219501633 -28397068724336,-41971675453328,-753292162941,-20520512,-20520512,-14961140,-10708032,-10708032,47060012,4,-7045933,-2175988,-4,-4719070,-1564297,0,-2677008,5130128,281197612767569,121862392258729 --27686315818688,-24048467775933,-42682428358976,-64256,-35566324,64256,-31652608,2069772,31652608,-4,2390457,-5398712,0,-7913152,16064,-4,2907900,3492869,281197612767569,118049388494673 --18246416867419,-15629493575407,1262530515980,-5944684,17834052,-8019920,-158028,474084,189182896,-12,-10506907,-365330,-4,12262939,546550,0,-39507,1486171,281197612767569,88400969785913 -21366269034360,-15135248719839,49002475143304,-5497376,36297860,5497376,-30712864,-2017084,30712864,4,1300310,-6614759,0,7678216,-1374344,4,1804581,2459706,281197612767569,248861887628129 -23938639635956,-46430104541708,4925372127349,8406992,8406992,37350868,23488848,23488848,-29567180,4,4466173,6308242,-4,2925622,3029475,0,5872212,-2101748,281197612767569,278358064901321 -2841630278875,-6826197793148,-70368744177664,-10205332,40405520,0,-24456980,-13493232,0,0,-3373308,-10101380,0,6114245,-2551333,-4,-729340,-160419,281197612767569,193952517339249 -145548001667,-10229024135128,70368744177664,-11953652,33292448,0,-23814036,-27863648,0,0,-6965912,-8323112,0,5953509,-2988413,4,879829,-417190,281197612767569,112051418665049 -13592612264731,8647461907272,56776131912933,-27484052,2526496,27484052,-10584916,-39992544,10584916,4,-8392059,334746,0,2646229,-6871013,4,1606077,966370,281197612767569,121840414994049 --17655295095630,52713449082034,8063883549879,14822088,14822088,-26626340,19418504,19418504,41077628,-4,7136531,5411102,4,3132876,1245483,0,-4854626,3705522,281197612767569,6501841738985 --5233442615611,59901858946442,-5320822168034,7964436,15928872,55402616,-4068332,-8136664,113065592,-8,23908148,-12091570,4,2179125,-879542,0,1017083,1991109,281197612767569,271022235350417 --27975822185219,-10677836261974,42392921992445,-29417484,34172584,-29417484,-11335660,-25105176,-11335660,-4,-4211110,-4030769,0,2833915,-7354371,4,-2065184,-4512377,281197612767569,68797821608569 -26764953162509,-43603791015155,9258665336115,26572852,26572852,-3061556,8635508,8635508,-43365236,4,6433735,399800,-4,4407574,-1165189,0,2158877,-6643213,281197612767569,143720353930657 --19619458083818,-11510369926210,6060135260879,-444328,1332984,133459772,-8430696,25292088,-1668004,-12,476327,-5486276,-4,297776,9292889,0,2107674,-111082,281197612767569,10520556794121 -4321387055514,70368744177664,35467084996245,24018536,0,-3766700,5832040,0,45961684,0,11490421,941675,4,29229,-3084270,0,-1458010,6004634,281197612767569,50816175650481 --13827675023254,8011561126611,56541069154410,-28214872,-21594292,-28214872,8602856,-33320276,8602856,-4,-6938046,3534663,0,-2150714,-7053718,4,-1392023,1863910,281197612767569,5995989981337 -6336888282121,-26013861095333,70368744177664,15346724,-35285652,0,-21394460,-24173396,0,0,6043349,-8821413,0,-5348615,-3836681,4,-2521491,-623950,281197612767569,267622002479297 -12480574107644,7911228547895,-70368744177664,30101488,3526876,0,-6485392,-38163332,0,0,9540833,881719,0,-1621348,-7525372,-4,1509878,-689661,281197612767569,97458087307561 -30115171679647,40253572498017,4207586125401,-27682180,27682180,-27978396,6779004,-6779004,-33820828,4,-4735362,4414977,4,3719845,-2579622,0,-1694751,-6920545,281197612767569,64931631004625 -24330051995173,46038692182491,13816812538572,-17767276,17767276,27753264,9579188,-9579188,48406192,4,-8387643,3667242,4,3713905,-3271074,0,2394797,4441819,281197612767569,27002900411065 --18540276960121,-51828467217543,19641150607516,8050204,-8050204,47075952,-23141924,23141924,4530544,-4,2449046,-8106437,-4,1316410,3662551,0,5785481,2012551,281197612767569,180378962446305 --4952796115861,-33222365234554,37146378943110,26420652,7737880,7737880,-9259444,39902552,39902552,0,9975638,-1934470,-4,519853,3622900,4,1795008,2982263,281197612767569,236432434087241 --16025313336302,-27674479964379,-42694264213285,6817864,34539668,-34539668,-30687928,9672980,-9672980,0,2418245,-8634917,-4,4104045,3000596,-4,-3567937,1296130,281197612767569,204839624131825 --26510121186561,-43858622991103,-15340064317364,-25538564,25538564,-339664,5364700,-5364700,44157616,-4,-7172883,-1444748,-4,3866521,-1359832,0,1341175,6384641,281197612767569,78806164811993 --29867074780666,-40501669396998,-7035296817901,-8572904,8572904,-51918772,18575512,-18575512,-18836340,-4,-2246093,7684910,-4,2462992,-5294783,0,-4643878,-2143226,281197612767569,155310103593729 --10964474392594,15343512769711,-70368744177664,24168376,-16927044,0,21445880,31565404,0,0,7891351,4231761,0,-5361470,6042094,-4,-2398626,658075,281197612767569,215114607052137 -13543948389433,-1233617832737,70368744177664,-23384860,33191804,0,-20953116,-18406276,0,0,-4601569,-8297951,0,5238279,-5846215,4,977500,1494627,281197612767569,87320354591249 --4392580632531,-9305791848183,70368744177664,19754164,27541540,0,-19223340,30194116,0,0,7548529,-6885385,0,4805835,4938541,4,1106736,223287,281197612767569,145176796304121 --11737702607695,58631041569969,3656025820840,-13406524,-13406524,-34366816,18434564,18434564,-36725600,-4,-7889360,6984449,4,-1292040,1607255,0,-4608641,-3351631,281197612767569,71814660293153 -31638286866230,38730457311434,23053018471911,-18823976,18823976,-34669668,17338392,-17338392,-27878468,4,-2416000,6312183,4,4553617,-2355234,0,-4334598,-4705994,281197612767569,3976245225865 --23833236923027,4424408417647,46535507254637,6955444,-41256516,6955444,-28411084,6648380,-28411084,-4,-1545743,-6930160,0,-7102771,-1738861,4,-116352,-3383969,281197612767569,22706969338673 -644000978512,-70368744177664,-15430321118383,12130624,0,40446276,-9080000,0,62539876,0,15634969,-10111569,-4,-354673,-757534,0,2270000,3032656,281197612767569,264837491300633 --21410370890401,27548002396862,-14727625149698,-14878340,-29756680,-29092872,6233532,12467064,-63484808,-8,-5560954,4404284,4,-5155124,1434467,0,-1558383,-3719585,281197612767569,194204186232129 --4765441487776,-12252945209363,-70368744177664,-10964608,35802036,0,-28805760,-8627308,0,0,-2156827,-8950509,0,7201440,-2741152,-4,-1107887,1083440,281197612767569,239551854244265 -12181651090877,-58187093086787,-18210551801438,-6544652,-6544652,62693000,14937844,14937844,28939912,4,-5016087,13383446,-4,-2218891,2289804,0,3734461,1636163,281197612767569,245936394877009 --9512850802361,-19019102719361,-70368744177664,28174620,-26808836,0,9533564,30890076,0,0,7722519,6702209,0,-2383391,7043655,-4,-399797,-2809786,281197612767569,67917043352377 --7809137695104,62559606482560,-7048122665273,-7169536,-7169536,58908444,-16238080,-16238080,-23619364,-4,-5656155,-12913252,4,-248686,-1813859,0,4059520,-1792384,281197612767569,20119582002273 -220250916686,70368744177664,3015184288027,-2611912,0,-125085588,-8076424,0,44280076,0,-11070019,-31271397,4,121164,69899,0,-2019106,652978,281197612767569,136794823761353 -25512415908127,19343912361410,4775714743337,10348668,-20697336,60738724,-11649028,23298056,40425764,8,2382903,-4525337,4,-3861769,5329672,0,2912257,2587167,281197612767569,64931712635249 -1960407503823,-70368744177664,22992755475379,-3394756,0,69788364,15193884,0,19307308,0,-4826827,17447091,-4,1106667,763366,0,3798471,848689,281197612767569,84724085428569 -18103006273325,25854720767819,26411017136520,-26269516,-11382484,37652000,23156340,-32826004,9669664,4,-3968291,4526530,4,-1550875,-4886470,4,4238210,1680909,281197612767569,24598967523201 --5534819084654,-18893119247107,70368744177664,-7744952,39854068,0,24768776,17916628,0,0,-4479157,9963517,0,6192194,1936238,4,1310220,1303531,281197612767569,178048037105129 -16400852159742,37567039858180,-14070276189165,-1016840,2033680,73573452,-15076872,30153744,-16366772,8,-677075,-9921135,4,1707309,4236114,0,3769218,-254210,281197612767569,77275884613265 --33974881505732,-36393862671932,4364032261887,-7190288,7190288,66461692,-16034192,16034192,-8378020,-4,-834656,-8704775,-4,1259849,7910648,0,4008548,-1797572,281197612767569,106671102329721 -26681959781923,-43686784395741,9840241075607,-15045492,-15045492,36526684,13830220,13830220,41256732,4,-6886817,5143200,-4,-3427366,3988471,0,3457555,3761373,281197612767569,254990707435169 -4038651816690,33165046180487,12305980435599,-18832440,9416220,48076348,9383816,-4691908,95614812,4,-11471031,5252966,8,961641,-1513155,0,1172977,2354055,281197612767569,258653120078345 -10342616772155,-27405182433823,60026127405509,-168724,-42896508,168724,-26221204,6530308,26221204,4,-3945594,-9131495,0,-6555301,42181,4,-2313017,1592632,281197612767569,34332335263665 -9729541910009,16092059855827,70368744177664,-12799004,-31915188,0,23970308,-28196180,0,0,-7049045,7978797,0,-5992577,-3199751,4,2345031,-371464,281197612767569,110135351384473 -14634983392809,-26463793999237,-15987989417513,-5679964,-17039892,-105870500,5861476,17584428,-88969316,12,-9363551,8985884,-4,-4292926,5827247,0,-1465369,-1419991,281197612767569,6842059160001 -25130237141578,16783180136259,-45238507036086,-10608344,-34107124,-10608344,-28897560,13224236,-28897560,4,-402351,-6114210,0,-7224390,2652086,-4,-2903708,-2412571,281197612767569,269482257578537 --20294377968548,-931553395641,-50074366209116,-22232720,16643356,22232720,21088624,34854684,-21088624,-4,-6270438,2887271,0,5272156,5558180,-4,2443233,-1273568,281197612767569,9570847274193 -4111023451346,2557441995457,70368744177664,-4510904,-36067580,0,-29922168,10348196,0,0,-2587049,-9016895,0,-7480542,1127726,4,423007,485792,281197612767569,98410005091257 --26461705260163,43907038917501,-25707033556042,7354868,7354868,-47278376,22780724,22780724,6643800,-4,3116918,6703195,4,-1455968,5116399,0,-5695181,1838717,281197612767569,173165518295265 --20097091365123,50271652812541,3379479690750,2476020,2476020,-51560456,21286484,21286484,11453496,-4,1790031,9238466,4,1073343,3651648,0,-5321621,619005,281197612767569,254947926488649 --19169514364692,31750218165577,38618526012087,-33926224,12415268,-12415268,12124592,28749732,-28749732,0,-7187433,3103817,4,-294465,5500224,4,-3325613,-2981332,281197612767569,56096835050993 -5723033923138,-64645710254526,-22229138183907,7762184,7762184,78024820,-8165048,-8165048,62974996,4,15108147,-17306772,-4,635602,-2199433,0,2041262,1940546,281197612767569,170198712496601 -2685431690686,-33841656243489,-7073039125399,15081208,7540604,25562532,2920824,1460412,-144360860,4,17393163,2883892,-8,1303889,622849,0,365103,-1885151,281197612767569,220066495294465 --6073773050754,21841671576771,48527072600893,28121592,11077388,-11077388,-22454984,31191596,-31191596,0,7797899,-2769347,4,4544366,4609209,4,-1069380,-2421189,281197612767569,144875637134953 --3044130818870,23697859832915,-70368744177664,-8557784,42796364,0,-24604376,-8521140,0,0,-2130285,-10699091,0,6151094,-2139446,-4,2163640,-257655,281197612767569,242104454253329 -9168893617674,20154189508345,-50214554669319,-21024728,-20727836,-20727836,26584680,-27341948,-27341948,0,-6835487,5181959,4,-3852003,-4425966,-4,-2794167,-830216,281197612767569,74716613555193 -7020924995217,63347819182447,-15638389492928,-1657276,1657276,57724160,-19247740,19247740,-8954624,4,-945918,-13083283,4,1292738,1347757,0,4811935,-414319,281197612767569,3504583117601 --33024622389143,37344121788521,14093750419919,14327204,14327204,-38474948,17811332,17811332,30753372,-4,3188309,5821964,4,4500034,3796773,0,-4452833,3581801,281197612767569,264789031279241 --14125186453778,8317715118145,56243557723886,-23444552,-21644028,-23444552,14329016,-34795388,14329016,-4,-7376148,3632053,0,-3582254,-5861138,4,-1322699,1778954,281197612767569,121731564207153 -28547031337829,13376249819545,41821712839835,-5441132,-37404060,5441132,-30780620,-4671868,30780620,4,2156905,-5816090,0,-7695155,1360283,4,988938,3534925,281197612767569,3854677629465 -16686170232903,-53682573944761,-27915171443107,-5216996,-5216996,-55499404,-18732196,-18732196,16537140,4,-5011702,-10067387,-4,877417,-3807464,0,-4683049,1304249,281197612767569,36036561235521 --12287628612631,12382368121279,70368744177664,20179876,26290940,0,22073860,-27034724,0,0,6758681,6572735,0,5518465,-5044969,4,209134,2035449,281197612767569,3955731579561 --20535267325743,49833476851921,7505837519185,10338116,10338116,46883140,15933252,15933252,-36650684,-4,6913664,8024705,4,2249007,3696080,0,3983313,-2584529,281197612767569,95185978224977 -16319694161719,-29602039447497,40766704730167,26370268,-15448868,-15448868,21033532,30373436,30373436,0,7593359,3862217,-4,-1285310,4714983,4,-3973073,1877584,281197612767569,142043005232185 -12027588107724,-58341156069940,-16611002063213,-22886608,-22886608,-16257460,166448,166448,-49076468,4,-10181874,2019041,-4,-2087243,2045324,0,-41612,-5721652,281197612767569,41122652722529 -5904368079761,70368744177664,31575335486884,19458628,0,-30931312,11835428,0,39047696,0,9761924,7732828,4,508591,-2831664,0,-2958857,4864657,281197612767569,52474778357449 --24535654299683,21297435578298,-10427595145875,-3667084,-7334168,100311476,9725428,19450856,40993844,-8,-3822327,7318233,4,-3213067,8879818,0,2431357,916771,281197612767569,129014088854129 --6970924839627,56426894498410,15908696043248,-11091756,-22183512,4914112,-1791628,-3583256,-100714048,-8,-19987482,-2238916,4,-2595515,505194,0,447907,-2772939,281197612767569,181111220048473 --10456455555545,18086466399939,8675328718805,1498268,7491340,251849556,3971548,19857740,-83875052,-20,6001513,15951964,4,2993450,9402085,0,992887,-374567,281197612767569,207645434347649 --17475184060071,23014092699163,-52893560117593,31908196,-7664532,-31908196,1956548,34815628,-1956548,-4,6382430,4049179,0,-489137,7977049,-4,-2321477,2133046,281197612767569,12230095781609 -6569433097639,17724667309777,70368744177664,26679964,8804164,0,-11888228,38277188,0,0,9569297,-2201041,0,2972057,6669991,4,-1641973,-1474572,281197612767569,122167674955665 -27123772660069,16121198857526,17354619212399,6631828,-13263656,-80564804,-9448780,18897560,-54986468,8,4314443,-3796485,4,-4716087,8172358,0,-2362195,-1657957,281197612767569,70116241056889 --15973084244355,24026424959329,-30369234973980,-22886924,13951364,36838288,28526132,31805124,3278992,-4,-3711448,4649737,4,2891700,4559835,-4,4239833,1161896,281197612767569,93794219306913 -17110053281864,-16360927781849,53258690895800,-21667552,-27396964,21667552,-22503392,23508668,22503392,4,-5756168,-3924417,0,-5625848,5416888,4,120999,2924824,281197612767569,14559892689673 --26236358973746,44132385203918,-4113311470821,9675576,9675576,-51453844,-16773064,-16773064,-27167508,-4,4504698,-7926041,4,2287179,-4937420,0,-4193266,-2418894,281197612767569,135320023820465 --33165619186775,37203124990889,-328123304724,17042084,17042084,31040432,-10747196,-10747196,46490928,-4,6132273,-4122544,4,5490459,-3637564,0,2686799,4260521,281197612767569,271739515624089 --4359210076574,14089599579223,70368744177664,11014536,31364444,0,-27431672,24106396,0,0,6026599,-7841111,0,6857918,2753634,4,-999792,-1037089,281197612767569,122928917095105 -17983261980238,-52385482197426,8830008369737,18342200,18342200,24069412,14277752,14277752,-42647164,4,7489190,5054977,-4,3172601,962376,0,3569438,-4585550,281197612767569,34029370166057 -6055126412924,-64313617764740,4635695321009,6638064,6638064,-64202044,13861360,13861360,35548356,4,8350655,14560064,-4,536434,1490447,0,-3465340,1659516,281197612767569,267686571109841 -28816050276356,41552693901308,13720801240361,-2715632,2715632,55234724,19512976,-19512976,17714500,4,-3566281,8021640,4,862344,-5787041,0,4878244,678908,281197612767569,211371678119097 --27662690575429,42706053602235,6640612254360,-21552404,-21552404,3222112,6572972,6572972,51257440,-4,-7621830,997335,4,-5192530,-191807,0,1643243,5388101,281197612767569,95009632082401 -10145319353508,50078105470648,-12989228639173,-9641328,19282656,-48814868,4331024,-8662048,-94850164,8,-17274821,7794971,4,3218860,-2204373,0,-1082756,-2410332,281197612767569,167738920806217 -27093956505539,-16180831166586,25569018153549,5001996,10003992,66082100,14974604,29949208,-27258444,8,-1153593,4707543,-4,3984102,5906491,0,3743651,-1250499,281197612767569,160218819524337 -21691128746842,-18751344755175,29926270675647,32613736,34632804,2019068,-13735768,19936132,33671900,4,4362759,-3816648,-4,4055216,3311881,4,-621274,4841553,281197612767569,247152341988057 --22010936350481,-30920637055888,-48357807827183,-4847684,-36294208,4847684,-31061764,-301632,31061764,-4,3464023,-6767926,0,-7765441,1211921,-4,3388615,2305626,281197612767569,45433121527041 -5351144634983,70368744177664,-24639383057173,13725084,0,-34920532,17476156,0,37567948,0,9391987,8730133,4,-2244012,537571,0,-4369039,3431271,281197612767569,128130400544617 -26374257611937,43994486565727,-4122448127094,-20140412,20140412,15271464,-15283836,15283836,-44313560,4,-6702356,-2681901,4,4376034,1135965,0,3820959,-5035103,281197612767569,22688087573521 --587590803343,26416504257508,-70368744177664,1875396,-40837232,0,27517028,1162768,0,0,290692,10209308,0,-6879257,468849,-4,-2584908,90757,281197612767569,26268432389369 -16216502359777,54152241817887,-21504952576999,19445636,-19445636,28626020,-8407356,8407356,45523364,4,9400452,-4021621,4,-1980389,3134884,0,2101839,4861409,281197612767569,23308095263777 -11642154761618,29363294708023,-728855377782,12611144,-6305572,69515816,-7228920,3614460,138708712,4,14479366,-7235519,8,-5718446,2907916,0,903615,1576393,281197612767569,218168076700553 -27271881865629,43096862312035,-14368064008578,-21900684,21900684,-753160,4799476,-4799476,-51244296,4,-8091048,-1002617,4,4720026,-1190907,0,-1199869,-5475171,281197612767569,280608361321777 -23478736903435,46890007274229,6881677458975,17885228,-17885228,35232892,17561740,-17561740,-28355748,4,4294332,6306603,4,-2794605,-2501620,0,4390435,-4471307,281197612767569,123682348538649 -30357582177239,-40011162000425,-19149337573780,-17018020,-17018020,-38147664,-21843556,-21843556,17194672,4,-3930255,-4264850,-4,-368413,-5272066,0,-5460889,4254505,281197612767569,147375455016769 -694216637336,-70368744177664,-15760340691325,8097376,0,-67899892,-8982688,0,-63721428,0,15930357,-16974973,-4,660118,285923,0,-2245672,-2024344,281197612767569,262245065888681 -5668383824581,21715953678184,-70368744177664,12695316,38747552,0,26069780,-9118304,0,0,2279576,9686888,0,6517445,-3173829,-4,2194924,-199147,281197612767569,52863963474513 -25181647080874,-16501712681321,28685384415469,20598440,-10887588,-31486028,-30819608,-38369348,-7549740,4,4352867,-2955460,-4,-2465432,-4916047,4,-5239470,-233563,281197612767569,59490804696377 -22886167494663,-24596409188338,1803829782136,6489116,12978232,87538144,8029660,16059320,-65185824,8,5593282,7732604,-4,5351587,7075966,0,2007415,-1622279,281197612767569,82263641316961 -9577431073721,-30211026557742,-40157717619922,31525604,-9041080,9041080,5707716,34076936,-34076936,0,8519234,2260270,-4,345184,4805353,-4,1772113,-3076048,281197612767569,153673586212809 -10700746499125,-59667997678539,20596560972483,14687444,14687444,-5193972,-542892,-542892,76849292,4,16251042,26301,-4,2961281,1272192,0,135723,3671861,281197612767569,72808381432689 -17699824353065,31672514027512,38696230150152,28063908,14917600,-14917600,-15594556,31829728,-31829728,0,7957432,-3729400,4,142357,4796186,4,-3756282,-2219791,281197612767569,173826801668953 -23917239723980,-46451504453684,-30755305817103,18018096,18018096,33491908,-16058320,-16058320,32638084,4,7140836,-3558389,-4,1018685,-4814588,0,4014580,4504524,281197612767569,245462255626625 --25043432397980,-45325311779684,1131142438837,-7832176,7832176,43715284,19739408,-19739408,33577652,-4,-5327612,7070853,-4,3066801,-3857968,0,4934852,1958044,281197612767569,235935279042537 --9757788255643,-60610955922021,-7302223412280,-14158444,14158444,-35328224,9967252,-9967252,-54651104,-4,-11509629,7974654,-4,2153147,-857402,0,-2491813,-3539611,281197612767569,273537318707345 --5879557568715,-58609629040234,-21157706965155,6990036,-13980072,73492852,5251060,-10502120,-105862764,-8,21253671,16353763,-4,-2606010,-1009725,0,1312765,-1747509,281197612767569,264190554523001 --25282001290034,14880150769621,30206592118009,34995000,25054036,9940964,1920184,-30798444,32718628,-4,5034814,2163155,4,3144843,-4648396,4,2664797,4100354,281197612767569,125175335401633 -5355248609717,-25888498897263,-44480245280401,9908948,-30321084,30321084,-30251724,-21055196,21055196,0,5263799,-7580271,-4,-4379957,-2142746,-4,3182974,334491,281197612767569,237344669565961 -4585231713285,11299232232816,70368744177664,-23176172,-32434752,0,-16602220,25345472,0,0,-6336368,-8108688,0,-4150555,5794043,4,1079340,-401997,281197612767569,115207380795825 --23984736899750,4693641056871,-46384007277914,-28504728,-27275876,28504728,-14352728,25764732,14352728,-4,-4485081,-4019446,0,-3588182,7126182,-4,1956102,2799523,281197612767569,91375735643033 -3859287832302,62650168513060,29024413465763,4744120,-9488240,-123009396,5557304,-11114608,93231052,8,21897279,26400815,4,-705242,-2175767,0,-1389326,1186030,281197612767569,208576751520705 -2158604788683,-12138111425902,-70368744177664,-12385492,38142536,0,-24613300,-15105272,0,0,-3776318,-9535634,0,6153325,-3096373,-4,-1177246,241591,281197612767569,238564671953961 --29622103079181,-26078976920307,-40746641098483,-14487604,34865204,14487604,26972620,12803636,-26972620,-4,-4352513,3704834,0,6743155,3621901,-4,-1151604,-5011467,281197612767569,40076807775953 -5750323121978,-27070803727099,37547617328587,-22276888,14483476,36760364,-21004504,-36884940,-15880436,4,-6447599,-5467458,-4,2477490,-3722633,4,2773636,-1846589,281197612767569,237798858167737 -9012800978565,-61355943199099,-29469624325220,11159060,11159060,47496816,-16604844,-16604844,30219632,4,8325758,-9185039,-4,-770850,-2689165,0,4151211,2789765,281197612767569,123262734050017 -17807032206031,-859384646460,3285999954634,-1118404,4473616,313410344,-3207332,12829328,-107911704,16,179698,1009114,4,6789406,19840425,0,801833,-279601,281197612767569,125434231855177 --34739733134093,-35629011043571,-17719733562,22341580,-22341580,-21794024,-10193076,10193076,-40451560,-4,5120987,-2757274,-4,-4991903,2691232,0,-2548269,-5585395,281197612767569,102283433594865 -31582063353703,-38786680823961,1358302877976,16515484,16515484,-11205536,446076,446076,-68475040,4,9433569,-1464402,-4,7685191,-1336982,0,111519,-4128871,281197612767569,281415043625945 -24964643533597,-45404100644067,-26411022544131,-23086988,-23086988,-30033932,15526964,15526964,-28568652,4,-6065253,2678436,-4,-1076910,4830047,0,-3881741,-5771747,281197612767569,162126088715777 --34745703134519,35623041043145,-14282327768465,321316,321316,-75469380,-14901116,-14901116,-4114084,-4,1276770,-9534985,4,-248249,-9332360,0,-3725279,-80329,281197612767569,217097663314025 -15349931801975,8969016969764,-8972805300398,-2868772,11475088,172291400,4580060,-18320240,117400392,16,-3156878,5855754,4,6548305,-9304274,0,1145015,717193,281197612767569,211947306843409 --16230242093055,-54138502084609,-37138729579634,-26559484,26559484,-9226696,3259556,-3259556,-41259272,-4,-7505674,5278995,-4,2809144,2972321,0,-814889,-6639871,281197612767569,177537346762233 -34266395897775,36102348279889,31349279601970,18490044,-18490044,29478088,-15821956,15821956,35667784,4,2812626,-5840227,4,-6104320,1529295,0,3955489,4622511,281197612767569,98467900595489 -19064892951137,32238958275390,-1381933528846,10978692,-21957384,40311752,6652004,-13304008,-78128248,8,9013798,4509336,4,-5259132,-2784301,0,1663001,-2744673,281197612767569,210190051818633 -22419080653337,25530582870990,10513837297804,-13360028,26720056,49189424,9270244,-18540488,50142256,8,-5240582,3463556,4,3647491,-4416900,0,2317561,3340007,281197612767569,224243245755953 --21128935881129,-28110872415406,5922878125382,-14164644,28329288,20970776,-8384708,16769416,-67073064,-8,-6345712,-2690462,-4,5211277,1276116,0,2096177,-3541161,281197612767569,1946742053913 -15094194552203,55274549625461,32025354511961,22178348,-22178348,-14346908,-5957780,5957780,-46911708,4,9890128,-293985,4,-1837799,3292742,0,-1489445,-5544587,281197612767569,176786124881985 --13692335786419,-10934726333867,70368744177664,-24640204,-34425516,0,-24103660,12017716,0,0,-3004429,-8606379,0,-6025915,6160051,4,-1520979,-717406,281197612767569,169206280447145 -22263336504597,-48105407673067,30886826480778,-3653548,-3653548,40299048,27002964,27002964,10320424,4,-4726900,6486387,-4,2146794,3588375,0,6750741,913387,281197612767569,93105134822225 --4885940042182,-31281223840208,8891787099055,3141864,-25134912,-29535556,-299224,2393792,-355541220,-32,39436825,-4076393,-4,-6181060,413437,0,-74806,-785466,281197612767569,237857712793145 -14287807679305,-27505321139749,-1653526289025,7137572,21412716,71940604,-3915932,-11747796,118273468,12,11626522,-6904141,-4,5980615,-3693670,0,978983,1784393,281197612767569,193765093549921 --19797717513981,-36563903337405,50571026663683,28620812,13387020,28620812,6229932,-36424532,6229932,-4,5734916,6123045,0,1557483,-7155203,4,3371217,-2776290,281197612767569,125464934609097 --11547600113075,-58821144064589,-20781541059317,-18025164,18025164,-23345108,-9146444,9146444,50616748,-4,-9902329,-6209350,-4,2751858,-373073,0,-2286611,4506291,281197612767569,81624863448177 -15775808456152,-54592935721512,-8229369406243,-17057952,-17057952,18505588,12591712,12591712,52344084,4,-9784157,4087932,-4,-3301864,538465,0,3147928,4264488,281197612767569,31717570221145 --16156092356417,-54212651821247,-11076874551686,-18692356,18692356,28824040,-7557572,7557572,-48579224,-4,-9653870,-4815969,-4,2490936,2390041,0,1889393,-4673089,281197612767569,255282593747585 --6504274412380,57360195352904,20560387071947,-1056112,-2112224,-107220180,10461200,20922400,-4022452,-8,-2347993,21695507,4,671190,2554769,0,-2615300,-264028,281197612767569,99445386764521 -2618378139143,-17191480458628,70368744177664,4250652,-40199696,0,26522396,14046704,0,0,3511676,10049924,0,-6630599,1062663,4,-1750560,-114337,281197612767569,265844318820753 -28308146401072,-13752451375520,-9064480497205,14154944,28309888,25099052,-2499904,-4999808,75108364,8,3830695,-314625,-4,7473198,-2980069,0,624976,3538736,281197612767569,194164024436345 --4228957196785,2003448066527,70368744177664,-3040196,-49452164,0,22409980,-5814724,0,0,-1453681,12363041,0,-5602495,-760049,4,72145,764622,281197612767569,146504360575393 --14870094819831,32097815872864,55498649357833,18543652,29726080,18543652,-21470204,26298752,-21470204,-4,7633687,-3746502,0,5367551,4635913,4,-1058999,-3685018,281197612767569,49003409290505 --33249090439791,-37119653737873,5551675002743,24015428,-24015428,-2784804,-5744700,5744700,47548508,-4,6383789,840916,-4,-5503338,144715,0,1436175,6003857,281197612767569,100258542623409 --19284605109738,18759209621885,51084139067926,13422680,-27405836,13422680,-27249384,-28243820,-27249384,-4,3309830,-5868381,0,-6812346,-3355670,4,3751125,-983078,281197612767569,87398530899097 --21501285016344,12751144829697,-48867459161320,14996384,32892932,-14996384,23488928,-23557692,-23488928,-4,5153976,5031257,0,5872232,-3749096,-4,-735447,-3191976,281197612767569,23472361108673 -4250682166149,-9757156166237,-70368744177664,3963412,32303756,0,-32706316,17500844,0,0,4375211,-8075939,0,8176579,990853,-4,-869456,-625223,281197612767569,65106826358057 -20625163018634,49743581159030,15507698396523,-10871256,10871256,-50943572,-15539672,15539672,30746540,4,-4577524,-9601933,4,3109111,3133960,0,-3884918,2717814,281197612767569,98677254119377 -2419541554729,2701051869952,-70368744177664,-23063388,27716608,0,19855684,24955904,0,0,-6238976,6929152,0,4963921,5765847,-4,-23983,459568,281197612767569,191271980168889 --3885100553567,10327977172664,70368744177664,-24705404,11180768,0,18433220,37230816,0,0,-9307704,2795192,0,4608305,6176351,4,-1190242,-752175,281197612767569,245065037802465 -15274569759495,-55094174418169,12051933364099,-20582372,-20582372,34378252,13038908,13038908,32923564,4,-7002543,5847710,-4,-1228348,2746853,0,3259727,5145593,281197612767569,20728413489481 -23280466115161,5169675688688,47088278062503,-25729692,35761088,25729692,-22325276,-12729408,22325276,4,-2539552,-5509953,0,5581319,-6432423,4,642800,3430319,281197612767569,278881129048305 -11304440761775,12156240535488,-46908062880401,-30762308,31555328,793020,-18076516,-18057472,-36133988,4,-4569836,-5292973,4,4463661,-5094718,-4,55468,-2595859,281197612767569,72081417417945 --357916026273,70368744177664,15803140915880,-3601028,0,-108041568,9059004,0,-40863584,0,-10215896,27010392,4,456648,339559,0,-2264751,-900257,281197612767569,65263283840769 -16595286750089,-53773457427575,25212273375370,-18511324,-18511324,-25986520,14954372,14954372,-39829016,4,-6269510,6622605,-4,-3687744,-125975,0,-3738593,-4627831,281197612767569,175413043890537 -31467340926933,-38901403250731,16591258081306,13454164,13454164,35371112,-12760492,-12760492,50136680,4,6177013,-5681526,-4,6357157,-3161252,0,3190123,3363541,281197612767569,100931338860049 -33057754008885,37310990168779,-13623443247239,1229012,-1229012,50117092,22287860,-22287860,-7239292,4,2038343,6583800,4,228520,-5945473,0,5571965,-307253,281197612767569,258834592306937 -9597721023861,-24136086264571,-36634936889232,24043988,36167700,-12123712,24803860,-9515948,34319808,4,4181409,5746942,-4,4398543,-2716014,-4,-1802422,3294983,281197612767569,219595620034081 --12261347031621,9062009019559,-863289340793,4246252,21231260,39859740,818316,4091580,-257469892,-20,8276623,1348390,4,11218170,1723309,0,204579,-1061563,281197612767569,96175778819465 -26835906000774,-43532838176890,7191818660941,9635352,9635352,39705908,20087576,20087576,-34072908,4,4756459,6387092,-4,3761768,3539385,0,5021894,-2408838,281197612767569,108898553022257 --15158160759527,55210583418137,-11656724462769,-10022812,-10022812,56422716,17490052,17490052,13874716,-4,-3445805,10652094,4,-22874,3453585,0,4372513,2505703,281197612767569,163309537107225 -21323819503314,-3277604341193,49044924674350,-11291832,39202012,11291832,29845192,-3904740,-29845192,4,1027901,6962146,0,7461298,2822958,4,51716,-2838357,281197612767569,85511742253377 --10784246592733,-18140451963424,-70368744177664,32915596,-1804416,0,767660,34163584,0,0,8540896,451104,0,-191915,8228899,-4,-1259447,-2190472,281197612767569,126235761227177 --6715085245849,-14162127633995,-70368744177664,-24162916,18518740,0,21094812,30428884,0,0,-7607221,4629685,0,5273703,6040729,-4,-335429,-1657530,281197612767569,156444747308113 --12794844519862,-19189366098216,2750951484073,4792616,-19170464,452260,-204440,817760,-234943164,-16,16009099,-156527,-4,-10681673,-67398,0,-51110,-1198154,281197612767569,216613462067001 -6582422174672,-8561702634781,-70368744177664,-1790144,46464908,0,-23715008,-13397940,0,0,-3349485,-11616227,0,5928752,-447536,-4,-1034663,-1032152,281197612767569,117440838561889 --11902554572116,-58466189605548,25293045029747,22395568,-22395568,22430156,10351920,-10351920,-39905428,-4,9219114,2646607,-4,-757243,-2960932,0,2587980,-5598892,281197612767569,213574656745929 -1389785777797,70368744177664,-33973415843379,-15309292,0,-41954508,17076372,0,-26746444,0,-6686611,10488627,4,-1929020,-2054949,0,-4269093,-3827323,281197612767569,128091322447217 --2442895416107,32081868833673,70368744177664,-25452716,9095716,0,-3147788,-43110076,0,0,-10777519,-2273929,0,786947,-6363179,4,-732926,2822101,281197612767569,96884398495065 -12042198866623,-18823730810127,70368744177664,6393596,40626116,0,27759164,288900,0,0,-72225,10156529,0,6939791,-1598399,4,1868763,-2165660,281197612767569,62561007844225 --27596730762889,-23986865294638,42772013414775,-31446564,2966344,-31446564,-8629636,-34989560,-8629636,-4,-6052303,2229072,0,2157409,-7861641,4,-2695087,-2970658,281197612767569,104325105938921 --17597767748477,52770976429187,19205347385610,16541196,16541196,-8446936,1434892,1434892,67333672,-4,12525824,2712257,4,4307594,-600523,0,-358723,4135299,281197612767569,149868224631441 -12235500062153,-3984086036769,58133244115511,24040228,-23470212,-24040228,-13334844,-33815332,13334844,4,6795161,-5187594,0,-3333711,-6010057,4,-1658672,679959,281197612767569,185099925194617 --26270404879997,17514851476379,44098339297667,32897548,-10632596,32897548,1801676,-34806740,1801676,-4,5565239,-3712854,0,450419,-8224387,4,3136446,1054705,281197612767569,176982365555361 -21857401310191,-15322423494827,48511342867473,25531324,-23533228,-25531324,-14296868,-30920780,14296868,4,4550834,-5445707,0,-3574217,-6382831,4,-3179361,437600,281197612767569,60446908114441 -16134476941207,54234267236457,-18210727648858,19587676,-19587676,-1888616,-2960164,2960164,-57194600,4,10828673,-1631170,4,-3469977,-1159016,0,-740041,-4896919,281197612767569,222033340412849 -31953316947378,28827363595413,38415427230286,-30830904,-12755372,30830904,-7191800,33543156,7191800,4,-3841386,-4898399,0,-1797950,7707726,4,4544403,-1709556,281197612767569,254489943350681 --16182032657206,-54186711520458,-9250888393115,-15078616,15078616,-22002284,-9636696,9636696,60607060,-4,-11350740,-4731227,-4,3801025,769344,0,-2409174,3769654,281197612767569,137509470215617 --34898675983743,-35470068193921,4966038148802,9782788,-9782788,57217800,-14034076,14034076,33007048,-4,4406985,-7037704,-4,-3844777,7266746,0,3508519,2445697,281197612767569,109959982726697 --30190515696757,-40178228480907,14666265209692,-15424980,15424980,-38814352,-17273812,17273812,29525360,-4,-5114554,-4736709,-4,2266786,4966879,0,-4318453,3856245,281197612767569,210405554690257 -14791264497097,40786215183470,10947233933396,8942372,-17884744,59625808,-5873724,11747448,86741456,8,12112102,-9335464,4,-4786631,2785494,0,1468431,2235593,281197612767569,228140486940601 --9190052790898,33608533014072,-5861937976019,3800632,15202528,-142450508,-5468744,-21874976,-91267596,-16,11353051,-16692199,4,2865962,-4730107,0,-1367186,-950158,281197612767569,91319284511969 --2397451872163,-70368744177664,33638372601583,-21344908,0,-16179268,-12961836,0,42922972,0,-10730743,-4044817,-4,-1183442,2688683,0,-3240459,5336227,281197612767569,70023409695305 --29399217455188,40969526722476,6519019960951,18927280,18927280,-3396132,-3990352,-3990352,-58769572,-4,8461670,-932677,4,6230723,83644,0,-997588,-4731820,281197612767569,201568511754737 -5249522641937,70368744177664,-34021422393753,-18527164,0,-26944100,11335268,0,-44285316,0,-11071329,6736025,4,-544152,-2741857,0,-2833817,-4631791,281197612767569,126301486888409 --28887100051016,-41481644126648,-5972504555085,59104,-59104,-66250036,-16989984,16989984,-5293300,-4,1140590,-9762173,-4,-182735,6800336,0,-4247496,-14776,281197612767569,53847327707137 -31496178304225,38872565873439,-10111478135269,-11440252,11440252,-37532564,25283044,-25283044,-15468404,4,-3044482,4772393,4,822619,-4610748,0,-6320761,-2860063,281197612767569,94955036318313 -29893464113293,10581815951078,-13614482438386,-3002828,6005656,-81189832,13281588,-26563176,-15841736,8,-1880374,2761780,4,1040030,-8767839,0,-3320397,-750707,281197612767569,49625166016273 --34350097074321,36018647103343,-12739714746338,82364,82364,-51271560,-21962980,-21962980,2140984,-4,720088,-6557183,4,-1255334,-6260707,0,-5490745,-20591,281197612767569,187495755560953 -8548699137452,36173947627856,-8698126998537,2320048,-9280192,166187996,-5925456,23701824,60843676,16,8551799,-21070987,4,-1664780,5119003,0,1481364,580012,281197612767569,23539303231265 --10758399623265,-48851944931134,-4305163627434,4629116,-9258232,75708760,13066140,-26132280,-29525864,-8,4724726,13281388,-4,-1328370,-2822901,0,3266535,-1157279,281197612767569,174175603728009 -34531007434624,35837736743040,18005419758607,-15974912,15974912,34157628,8551936,-8551936,52193468,4,-7192387,3327106,4,5855980,-5212301,0,2137984,3993728,281197612767569,21915278434353 -25068174813223,-45300569364441,-30631033752962,-25942884,-25942884,12653048,6756476,6756476,40103864,4,-5719052,4859571,-4,-4306914,-1696309,0,1689119,6485721,281197612767569,134320667745817 --1544497073189,-27556641352798,70368744177664,-24640660,19957384,0,-12766036,-35353080,0,0,-8838270,-4989346,0,3191509,-6160165,4,1055818,-2521851,281197612767569,87000253141569 --1830041464806,70368744177664,17427692834801,-13920152,0,37903300,10917928,0,51154212,0,-12788553,9475825,4,-1008575,-615442,0,2729482,3480038,281197612767569,216734810572457 -34680425882421,-35688318295243,-7617952276703,-15066924,-15066924,24172676,-10172204,-10172204,-58406780,4,-7130113,-3472640,-4,-7471582,-2570529,0,2543051,-3766731,281197612767569,247675061687633 -17654501178497,-35059741820670,-974629608482,10538500,21077000,-43231368,-7858268,-15716536,-74600392,8,9237598,-5457760,-4,4706250,-2675041,0,-1964567,-2634625,281197612767569,206312130095161 -84229119409,70368744177664,-11275705728489,18453188,0,-6108068,2321156,0,60245532,0,15061383,1527017,4,-111012,737395,0,-580289,4613297,281197612767569,105832151562593 --4476895873113,-8802995960389,-70368744177664,-33529188,23513836,0,6471100,29041548,0,0,-7260387,5878459,0,1617775,8382297,-4,259529,-1422600,281197612767569,257910010925769 -25908011153103,-44460733024561,-11698811083150,25345852,25345852,7836104,785084,785084,-44178744,4,7010939,184324,-4,4033747,1774702,0,196271,-6336463,281197612767569,105193967406705 -30693523482711,39675220694953,-8651580302302,25191772,-25191772,21604488,5002812,-5002812,-40402744,4,5848726,2270945,4,-4251960,-3130177,0,1250703,-6297943,281197612767569,135803757368921 --19800682686287,30767378805090,15881841455950,-10322236,-20644472,47306040,10580868,21161736,60583864,-8,-5428260,6335750,4,-4858853,2745380,0,2645217,2580559,281197612767569,55293988578433 -32521603787967,5325536601730,713021097216,-8857860,17715720,63312896,11622044,-23244088,44037120,8,-892068,1153010,4,5058606,-7337607,0,2905511,2214465,281197612767569,227710731813609 -5641902963170,-30875423435474,6833168601859,-2941048,-20587336,-179052532,-2100856,-14705992,254921484,28,-27605723,-20140332,-4,-5160664,-3517543,0,-525214,735262,281197612767569,179458934197137 --23147670056849,-47221074120815,-33992491685140,20489660,-20489660,-27165776,18063644,-18063644,31000368,-4,7382180,2082965,-4,-367912,-4708479,0,-4515911,5122415,281197612767569,186685684492409 -18656111151264,19700795534335,51712633026400,-9657728,32560124,9657728,-29234560,-18018628,29234560,4,-5356550,-5305995,0,7308640,-2414432,4,-851893,2834036,281197612767569,221246186967969 --30651544613947,-39717199563717,-2403556662261,19036948,-19036948,-9632724,9271156,-9271156,54451660,-4,7762506,1196655,-4,-5850409,-1211526,0,-2317789,4759237,281197612767569,68023939766025 -10964032570904,27388809795775,-59404711606760,-26363808,-2783492,-26363808,572512,42766716,572512,4,-9081535,-3152770,0,143128,6590952,-4,-1610144,2456897,281197612767569,257846997666993 -29436993610286,11494756957092,7836110849241,12062904,-24125808,-46100636,9875576,-19751152,55594372,8,2820201,1210989,4,-5539196,-5157085,0,-2468894,3015726,281197612767569,29574676995737 --2674808142219,-67693936035445,-9444692696593,9676244,-9676244,44493756,5061268,-5061268,-93084164,-4,22216651,11025302,-4,-1054390,-98137,0,1265317,-2419061,281197612767569,40728240735937 --1657691149414,67053361878836,-22026283345329,5375592,10751184,-90026692,-2749912,-5499824,-163393060,-8,39354101,-20604971,4,747082,-950851,0,-687478,-1343898,281197612767569,115421288238889 -27953474139134,-3081276687099,42415270038530,-30664712,9453588,30664712,-9202696,39553556,9202696,4,-6061039,1760238,0,-2300674,7666178,4,3827350,-603159,281197612767569,220180255101393 --18197853533590,52170890644074,3215285051253,-24559192,-24559192,-4847148,3011048,3011048,-45250060,-4,-8421414,617871,4,-2891101,593916,0,-752762,-6139798,281197612767569,85672387393721 --5918237195100,-11555782827025,-70368744177664,-458096,-45943876,0,-24419440,8679804,0,0,-2169951,-11485969,0,-6104860,114524,-4,1185025,947200,281197612767569,178039370677729 --7685864236108,28526281540629,-41842462637035,-26599728,25238612,25238612,-22884272,-20614220,-20614220,0,-5153555,-6309653,4,2838960,-4643321,-4,2882108,-2006611,281197612767569,269170298841929 -30937412260415,-39431331917249,7066600265228,-16683780,-16683780,-11687888,3772028,3772028,-64842192,4,-8988929,2056192,-4,-7221619,865780,0,-943007,-4170945,281197612767569,178021620538097 --13339087728483,-43690568720698,-23858226886567,-3461516,6923032,-78996124,13205012,-26410024,-23907196,-8,-1472325,12848591,-4,2252237,-3450220,0,-3301253,-865379,281197612767569,6714722531033 --15266036752639,-4951578402408,55102707425025,23484420,28649056,23484420,-15418684,29132896,-15418684,-4,5431938,-6021585,0,3854671,5871105,4,1851286,-1140679,281197612767569,255498761107713 --21660231471068,2378596941247,-48708512706596,7516304,37231356,-7516304,-26794480,17070236,26794480,-4,3180386,-6379273,0,6698620,1879076,-4,-1087173,2928566,281197612767569,168246103288681 -28087002828321,42281741349343,-842884428888,25072772,-25072772,26578592,3522436,-3522436,-41171296,4,6195091,3917420,4,-4097733,-2727228,0,880609,-6268193,281197612767569,107062433441809 -4224851419514,-70368744177664,7971383392207,9395688,0,51430204,18055720,0,-20997988,0,5249497,12857551,-4,826512,505865,0,4513930,-2348922,281197612767569,139349029771513 --6375016532662,31996863822501,-3295158641954,-18780888,-9390444,-59493512,-16341592,-8170796,68132088,-4,-7649309,-6872898,8,-1734404,-1127582,0,-2042699,2347611,281197612767569,105100800505889 --1590281897354,34389231140155,10660649878886,-16428584,-8214292,-26559080,-3570408,-1785204,131293912,-4,-16108459,-2933748,8,-606560,-772274,0,-446301,2053573,281197612767569,148129931415433 --24898128740139,45470615437525,-4024261968636,12128084,12128084,47014928,-20845356,-20845356,12026384,-4,1644764,-7768379,4,1361832,-3985353,0,5211339,3032021,281197612767569,44385239890225 --3028408295598,70368744177664,-24243225621131,16053576,0,-31145516,13658504,0,43635060,0,10908765,7786379,4,-706924,1717779,0,-3414626,4013394,281197612767569,238920811290393 --631373009607,70368744177664,32276113156304,-347932,0,-52665536,21356196,0,-3346624,0,-836656,13166384,4,2441361,158030,0,-5339049,-86983,281197612767569,23481285196609 -18595798084299,51772946093365,-21625388042610,9183020,-9183020,-46144968,17810508,-17810508,33108344,4,4721405,9193170,4,-3555681,-2343072,0,-4452627,2295755,281197612767569,48879484426153 --3113743771769,67255000405895,-25558256610939,-5348836,-5348836,76583444,-13275620,-13275620,-20417004,-4,-6083835,-17812996,4,979584,-1332865,0,3318905,-1337209,281197612767569,252226902593105 -19880287098247,50488457079417,10726724653191,-14591460,14591460,-42252772,19331452,-19331452,-21183108,4,-3062934,8134989,4,2232843,-2428204,0,-4832863,-3647865,281197612767569,104529232628025 -5634271625064,-36605023798307,33763720379357,-26845792,9100148,9100148,833440,41657012,41657012,0,-10414253,2275037,-4,-733873,3402386,4,942233,3309062,281197612767569,52494056260193 -18064533137489,34239677902686,8462363253599,-12305084,24610168,-15134340,3548964,-7097928,-87133796,8,-10385889,2580887,4,5698780,-601349,0,-887241,-3076271,281197612767569,133463843292105 --5420876154721,-12855331631710,70368744177664,362108,-43487608,0,25937404,-5677176,0,0,-1419294,10871902,0,-6484351,90527,4,-1293931,854058,281197612767569,240793312405361 --26324692067889,-44044052109775,18367215243695,-4961476,4961476,37923516,26711836,-26711836,22753948,-4,-1817405,6257870,-4,3871082,-3223009,0,6677959,1240369,281197612767569,79299041302361 -26897332634649,-43471411543015,-1599141764135,-16413596,-16413596,-27325596,-2600156,-2600156,64266788,4,-9940230,-4126955,-4,-6126467,-2704444,0,-650039,4103399,281197612767569,68015655947649 -23968121720413,46400622457251,-7093447642378,12199284,-12199284,43922392,16393300,-16393300,-33269736,4,5897581,6933090,4,-2419853,-4047508,0,4098325,-3049821,281197612767569,116923726009321 -4572910776398,32897916700633,-3790241076146,969016,-484508,165067064,-13590728,6795364,8687416,4,1106862,-19285999,8,41870,2694768,0,1698841,121127,281197612767569,135337043215505 --2872231337853,34663546531351,35705197646313,21239308,28474460,-28474460,-22007316,23506108,-23506108,0,5876527,-7118615,4,3031497,2403654,4,-2470332,-2906173,281197612767569,266913604192633 -31468450888769,7566308808803,38900293288895,11324676,-38701684,-11324676,-27670972,-4855476,27670972,4,1414856,-5044217,0,-6917743,-2831169,4,200987,4631204,281197612767569,32973427367073 -11554475387325,-58814268790339,17992224191025,13964020,13964020,41215172,11353172,11353172,-47119452,4,9119913,9504518,-4,2659950,799275,0,2838293,-3491005,281197612767569,127744115787785 -6382989150989,18010220714079,-70368744177664,30365748,-14613124,0,-80972,37116924,0,0,9279231,3653281,0,20243,7591437,-4,846879,2274338,281197612767569,115654758131121 --19030962006651,-15648316060657,51337782171013,-28401132,-11987908,-28401132,-16224844,32794396,-16224844,-4,-5079315,-3765388,0,-4056211,7100283,4,-3119284,768411,281197612767569,228060074385305 --28410923419379,-41957820758285,-5407671574454,19206196,-19206196,-19392216,16319220,-16319220,42144424,-4,6595745,2521696,-4,-3940361,-2326358,0,-4079805,4801549,281197612767569,193904457904065 --1166188752770,70368744177664,23290992727233,-16545288,0,-20566268,-6561992,0,59892836,0,-14973209,-5141567,4,294836,-1454269,0,-1640498,4136322,281197612767569,79188120330281 --19325826112109,-12391265841337,-2635194802021,-5379508,16138524,107132524,-5964724,17894172,-90507156,-12,-4151889,-4565164,-4,6158300,7405989,0,1491181,-1344877,281197612767569,8039848544977 --17931291652413,2866589999889,52437452525251,4181772,-37803964,4181772,-28121620,-15015452,-28121620,-4,2510912,-7085287,0,-7030405,-1045443,4,1242951,-2365704,281197612767569,209053675002297 -9099138664955,7476510052307,-70368744177664,26074092,-18574516,0,-14495572,-32854516,0,0,8213629,-4643629,0,-3623893,-6518523,-4,677046,-1293029,281197612767569,51474232067809 --93762533947,-70368744177664,19604033579879,-17407212,0,24457628,8288372,0,53034684,0,-13258671,6114407,-4,594931,1204222,0,2072093,4351803,281197612767569,130686014643273 -34085852053211,-36282892124453,20987807898899,-13488276,-13488276,45533260,14955244,14955244,32987084,4,-5367243,4863626,-4,-2879528,6519689,0,3738811,3372069,281197612767569,178439438939121 -22430386762246,47938357415418,-27134777144571,-13242344,13242344,36796436,16994520,-16994520,37800116,4,-4799478,7543437,4,4650551,-1655672,0,4248630,3310586,281197612767569,56583785789401 -27807920729856,42560823447808,-7046666015605,-11092992,11092992,36841004,24378368,-24378368,20533356,4,-2494468,5848307,4,2638871,-3361944,0,6094592,2773248,281197612767569,214139184407041 -24838835908763,-1206215474669,-45529908268901,-25168276,-107444,-25168276,-10327412,44690796,-10327412,4,-7273204,90475,0,-2581853,6292069,-4,-3899495,-117336,281197612767569,179378792479849 -34744368656764,-35624375520900,-3032214250999,5789168,5789168,68494372,-14870032,-14870032,18549540,4,2507878,-8606503,-4,2129507,-8517090,0,3717508,1447292,281197612767569,38813239697681 --3334901764816,-115395974527,70368744177664,25883840,8881668,0,-17681728,37430948,0,0,9357737,-2220417,0,4420432,6470960,4,450729,-94618,281197612767569,57233517279737 -14054143889266,-56314600288398,-4648986022449,10630600,10630600,49126204,12458056,12458056,-48339972,4,9877125,9653082,-4,2207868,2628469,0,3114514,-2657650,281197612767569,232528390963489 --14043624487342,-14194246228296,7945419658437,4690248,-18760992,88055572,-1874680,7498720,204855668,-16,10542153,-3910893,-4,-10167941,4525750,0,468670,1172562,281197612767569,61354597580937 --23294629644759,32994709298218,-47074114532905,-8973148,-35551064,8973148,27864100,-15078488,-27864100,-4,-5787990,4893751,0,-6966025,-2243287,-4,-2018368,-3994015,281197612767569,32348263944753 -29268860428856,-3064171017573,-41099883748808,-14309152,-40608148,-14309152,28321760,1690828,28321760,4,-61426,5773673,0,-7080440,-3577288,-4,484133,4378364,281197612767569,16244155965465 -16109659220013,-5930107297612,2987061916843,3296436,13185744,-170539348,-3997324,-15989296,-134751252,16,3008617,-3452989,-4,7669799,-9795462,0,-999331,-824109,281197612767569,149917938312257 --2976967713173,-70368744177664,28628649182912,4091308,0,-56026368,19593932,0,6873856,0,1718464,14006592,-4,-2065587,-176428,0,-4898483,1022827,281197612767569,5765313112233 --28870587215685,-41498156961979,-22085285367520,4388588,-4388588,-44284800,-24977684,24977684,-4504448,-4,2623912,-6184615,-4,1497800,4886585,0,-6244421,-1097147,281197612767569,34026193405777 --27730096222415,-20596029424546,42638647955249,-4826940,37140856,-4826940,28084324,17158712,28084324,-4,-4654232,5273009,0,7021081,1206735,4,364554,4012205,281197612767569,200648676993593 --18103753324496,-52264990853168,-17952486876377,-14393152,14393152,37744796,-13357888,13357888,-43194788,-4,-8872485,-6090554,-4,1926212,3345645,0,3339472,-3598288,281197612767569,29656510843745 -25525940138171,-19316863901322,6451245995689,8746732,17493464,63739556,-13547636,-27095272,29997444,8,1437635,-4775213,-4,3030863,-5579838,0,3386909,2186683,281197612767569,191218750567625 -32973501456495,-913899955345,37395242721169,15787452,-24325700,-15787452,-25319108,-32303812,25319108,4,4209503,-3283040,0,-6329777,-3946863,4,-3866450,2798385,281197612767569,104765176742001 --2208802422137,32558758668881,-37809985508783,-8974820,-39566012,-39566012,28237052,-966300,-966300,0,-241575,9891503,4,-3800611,-895086,-4,-3258652,-1348619,281197612767569,199561940408409 -11947320963229,10632139361519,1971163238219,-1266060,6330300,303608108,-3179468,15897340,-126840468,20,-4902467,-11423842,4,5361530,12895637,0,794867,-316515,281197612767569,236118294066817 --13591394551278,-14288256711143,-42489092915243,29712456,824420,-30536876,-17774840,37400004,-19625164,-4,6641804,-1674563,-4,1735513,5959656,-4,-2708197,-1468458,281197612767569,128509204767977 -22504078454361,-47864665723303,20003894627316,15283556,15283556,-36184112,-13644188,-13644188,-41364528,4,8003682,-5066915,-4,2337450,-3979113,0,-3411047,-3820889,281197612767569,56269077495185 -24002614855965,22363514465734,-1197567506048,-16445324,32890648,-3004928,2780308,-5560616,-67955200,8,-5422778,98808,4,5783011,-326212,0,-695077,-4111331,281197612767569,261336651065977 -25391840245233,30921312406182,44976903932431,-23071804,21811864,23071804,18558212,31255064,-18558212,4,-7032953,950776,0,4639553,5767951,4,780813,-4502190,281197612767569,4387362104737 --3736043213898,33121030445619,-37247713732045,16455384,23870668,23870668,31696408,-22441620,-22441620,0,5610405,5967667,4,4492270,-1860711,-4,3431832,-2253135,281197612767569,222125862320393 --17152599749305,-53216144428359,3315522496111,-3720932,3720932,-52101700,-20338788,20338788,17795132,-4,-3603951,-9806608,-4,844832,3218817,0,-5084697,930233,281197612767569,37461536931505 -21778610643271,21942853550664,-26647279983729,-2848484,38594848,35746364,-30038276,11733536,-18304740,4,-316161,-6440448,4,4260024,2496143,-4,3249545,-3208264,281197612767569,195001489055897 -21228145880250,27912452417164,-10814549231775,8948456,-17896912,-64145020,11087976,-22175952,46338884,8,3743171,7048555,4,-3920775,-4493850,0,-2771994,2237114,281197612767569,138489042147521 -8407939473498,61960804704166,-5682674933703,-16721560,16721560,-23823132,-5884632,5884632,58948420,4,-13095061,-4906572,4,1642044,1049211,0,-1471158,4180390,281197612767569,237865412276521 --10210070465280,24737064705749,-45631679471915,34460672,-3373228,-3373228,2085888,-32876204,-32876204,0,8219051,-843307,4,1530690,-5708995,-4,-1009218,-2906173,281197612767569,9211775730641 --21368814015420,48999930162244,-10217653134887,-777968,-777968,-58006684,19470224,19470224,4503044,-4,1490679,10126202,4,-364918,4375469,0,-4867556,-194492,281197612767569,63637979167417 -6763548038209,-63605196139455,-13251480055067,-8966908,-8966908,-59959404,-13425852,-13425852,35786452,4,-8718774,-13126939,-4,-227839,-1862912,0,-3356463,2241727,281197612767569,92406424899553 --22944923370491,-47423820807173,20900679900450,4799508,-4799508,50900104,-22241932,22241932,-1295288,-4,1433321,-8219432,-4,1757143,4505594,0,5560483,1199877,281197612767569,109819927383369 -4590862236027,-70368744177664,-31783409269040,8624620,0,55827264,18184556,0,-12836032,0,3209008,13956816,-4,-1843996,1884413,0,4546139,-2156155,281197612767569,109322290531569 -29229598783498,-41139145394166,25622245850641,17397800,17397800,34968644,-19398296,-19398296,25725540,4,1994134,-6694559,-4,4437251,-2047602,0,4849574,4349450,281197612767569,28703529220313 --4504966371327,-61358811435010,11435461922576,4094980,-8189960,122092608,-6920508,13841016,68610112,-8,15518656,-26282270,-4,-816936,2120441,0,1730127,1023745,281197612767569,166524257389313 --21391772921070,-48976971256594,-8658753595885,18924616,-18924616,-22959028,-15225080,15225080,-41023124,-4,7606426,-3412737,-4,-2649355,2327020,0,-3806270,-4731154,281197612767569,120841759739241 --4328962915576,26828375204137,-43540368973527,30075936,245924,245924,-3374048,37407652,37407652,0,9351913,-61481,4,1097233,4648558,-4,-253721,2870426,281197612767569,198896857602577 -7843711544218,24903861606887,-45464882570777,20973160,31648668,31648668,24235688,-17111044,-17111044,0,4277761,7912167,4,3437814,-4269599,-4,2621108,-973691,281197612767569,3942462036729 --13633251248129,15793858654713,70368744177664,-30473220,7652324,0,-10844996,-34223836,0,0,-8555959,-1913081,0,2711249,-7618305,4,-2266157,1339244,281197612767569,96284201011745 -11148017657667,-3480638231662,-4819627332993,-1494772,-8968632,-347746820,-1001044,-6006264,520340252,24,-6537221,-4146569,-4,-20591307,-13798356,0,-250261,373693,281197612767569,104126333890953 -6295449973979,-57777844229706,-24601924749315,-9631892,-19263784,-24622092,1862124,3724248,-112132748,8,-23342793,3370407,-4,-2345197,1392558,0,-465531,-2407973,281197612767569,242414302014257 -19313946996912,13707305850909,-51054797180752,31720128,16206964,31720128,-1472320,34742548,-1472320,4,6230011,-4484380,0,368080,7930032,-4,2455626,432639,281197612767569,16120889057561 --23588906323633,-29334135878417,-41034608299247,-32724676,-2975812,2975812,3567996,-34080772,34080772,0,-8520193,743953,-4,2335969,-5020128,-4,3227968,3161041,281197612767569,229108714966337 -18038352097948,-52330392079716,-22774424660495,18143856,18143856,-22055996,-8197904,-8197904,-52088540,4,9020735,-5568576,-4,4001400,54577,0,-2049476,-4535964,281197612767569,243752208431529 --1816851304835,-11702482248879,-70368744177664,-13359628,26544452,0,-31354380,-21977788,0,0,-5494447,-6636113,0,7838595,-3339907,-4,-1161715,726772,281197612767569,96300444549201 --19609470229831,-50759273947833,-22498133689453,-17070364,17070364,42287692,-21588092,21588092,-12477140,-4,-3975566,-6261449,-4,-856281,4310474,0,5397023,-4267591,281197612767569,191799855237945 -15715942618488,-18333568298849,-52035175878815,-3639840,32433788,-32433788,33756128,8533564,-8533564,0,-2133391,8108447,-4,5763898,2483799,-4,-2675134,1573839,281197612767569,262935640544353 --2418417172597,15779201029852,70368744177664,619052,44395376,0,-25389876,-2088976,0,0,-522244,-11098844,0,6347469,154763,4,-1441279,-416146,281197612767569,10201382528457 --11390977728566,58977766449098,25904067203559,-15722712,-15722712,-40121444,-12751832,-12751832,39069468,-4,-9359817,-6959734,4,-407550,-3070627,0,-3187958,3930678,281197612767569,149416475449713 --15339410597514,-55029333580150,-14887697789091,15650264,-15650264,-11589260,-3235688,3235688,-69545196,-4,13767468,-1437971,-4,-3618831,1459344,0,-808922,-3912566,281197612767569,161273905682777 --31299518382595,39069225795069,6774825306526,-17931276,-17931276,31780472,18550196,18550196,29912312,-4,-3705397,4842774,4,-3772681,3102344,0,4637549,4482819,281197612767569,161323025686401 -3811857893290,-23741254293599,-46627489884065,-11782488,33356420,-33356420,-31662488,-5920028,5920028,0,-1480007,-8339105,-4,5164850,-2403545,-4,-2750772,542077,281197612767569,115474613515753 --18165612767376,16432193059743,52203131410288,-3236416,38769276,-3236416,-28979776,-733828,-28979776,-4,1555709,-7379196,0,7244944,-809104,4,-1739166,-2313123,281197612767569,125817795294865 --12059836084086,-29154454046789,6447562212201,11721256,-5860628,100223396,10931304,-5465652,-98643644,-4,10342453,10246636,-8,-3976005,-4562577,0,1366413,-1465157,281197612767569,266749177662329 -842956129765,-21794907975368,48573836202296,28566420,7234784,7234784,-21990956,33843936,33843936,0,8460984,-1808696,-4,3896311,4908010,4,1601428,2233595,281197612767569,85437009227425 --25545226075555,19278292026554,-3751923959823,-10291852,-20583704,58588100,-8449324,-16898648,-61298012,-8,-4423567,-3738343,4,-5450468,-5454341,0,2112331,-2572963,281197612767569,208519373597193 -19219315239881,-31930113697902,6791004071784,-10392796,-20785592,38272416,-2778972,-5557944,-98100832,8,-11262510,-3840084,-4,-6631349,-2864010,0,694743,-2598199,281197612767569,239781618292657 -5216822028663,70368744177664,22091503316846,-16651812,0,29312440,15776188,0,39843192,0,-9960798,7328110,4,-499742,-1850187,0,3944047,4162953,281197612767569,22817238753689 --14670767745228,-22146627682759,70368744177664,-20509488,19133668,0,25999312,30641316,0,0,-7660329,4783417,0,6499828,5127372,4,448585,2610966,281197612767569,265722258178497 -1769739213063,70368744177664,-19798263482214,17524764,0,16988776,-5947972,0,58480168,0,14620042,-4247194,4,50679,1339464,0,1486993,4381191,281197612767569,206048048644649 -19856333192526,30656077792612,-3781091401511,1441080,-2882160,-76152988,-14417608,28835216,-19399324,8,1725477,-8332711,4,-1562177,5352768,0,-3604402,-360270,281197612767569,45331564559569 -30753964129200,5686588640721,39614780048464,-17224000,-24259772,17224000,-25539392,29396196,25539392,4,-3621252,-3762293,0,-6384848,4306000,4,3727797,2302650,281197612767569,106370913819577 --10276120004067,2203849052226,70368744177664,14603380,-39847672,0,26787252,4005256,0,0,1001314,9961918,0,-6696813,3650845,4,355959,1340424,281197612767569,224225963202785 --32443797305896,-37924946871768,24037163469561,18331488,-18331488,32909284,-16823200,16823200,31217348,-4,5642769,-2868624,-4,-2161568,5358697,0,4205800,4582872,281197612767569,215870658035273 -3099775917498,-33634484130083,-2570919359539,7294696,3647348,-28353740,667624,333812,306095028,4,36573376,3421407,-8,3377005,245621,0,-83453,911837,281197612767569,87250234238449 -32695726797730,-37673017379934,-13124569678545,11601544,11601544,-49850180,-15734072,-15734072,-29440356,4,3206694,-7212975,-4,4153395,-5249570,0,-3933518,-2900386,281197612767569,247584787053017 -22820126968561,10423871706573,47548617209103,-26064956,-7961804,26064956,-6821244,41112308,6821244,4,-6692352,-2310225,0,-1705311,6516239,4,3585725,-319774,281197612767569,66976885421057 --24111553944951,-46257190232713,-15453439648620,-13941212,13941212,-27286960,9387908,-9387908,-62385712,-4,-9736966,5249695,-4,5859462,-1572045,0,-2346977,-3485303,281197612767569,247395838844521 --11230941139913,59137803037751,24731275960354,17560796,17560796,31570056,4605404,4605404,-55835000,-4,12135561,5089912,4,1823189,2802602,0,1151351,-4390199,281197612767569,149894641373969 -24005495709635,46363248468029,-20547142835866,-14871796,14871796,31600024,-23218964,23218964,-26370728,4,-2648723,-6290622,4,3943959,1609384,0,5804741,-3717949,281197612767569,233691505409017 -27888480486073,42480263691591,1083628181189,23529188,-23529188,-10180844,-1163228,1163228,-47347884,4,7150231,-1445912,4,-4686740,1099299,0,-290807,-5882297,281197612767569,57811622875937 --30152053376143,40216690801521,-3884094738274,-14153276,-14153276,-36271496,22866596,22866596,-20948808,-4,-2677594,5377715,4,-2559608,3690159,0,-5716649,-3538319,281197612767569,139793256407689 --14890799553606,-6287373209109,55477944624058,-14260504,30653356,-14260504,23204328,29073964,23204328,-4,-6248719,5723152,0,5801082,3565126,4,-1019772,1940187,281197612767569,268535686317105 --20554556868201,-2727594017621,49814187309463,13871708,42985132,13871708,24194108,-6193396,24194108,-4,861630,7741739,0,6048527,-3467927,4,686719,3004544,281197612767569,216879964545561 --14723869665333,55644874512331,28244343824012,-10431700,-10431700,-48051664,-19482516,-19482516,18188080,-4,-5550562,-8452589,4,1003542,-3560327,0,-4870629,2607925,281197612767569,34164334114369 --32022148600903,531169812952,38346595576761,26454756,-645280,26454756,13848388,42221664,13848388,-4,5725913,137832,0,-3462097,6613689,4,4829503,23488,281197612767569,253759324179113 -10309145674729,-60059598502935,-11538007615419,-5944412,-5944412,53849364,19778468,19778468,10235156,4,-1373178,11733753,-4,-1185611,1728588,0,4944617,1486103,281197612767569,272060404808017 --14224279688597,-11504288569093,56144464489067,-26567252,22632428,-26567252,-13573236,-30816308,-13573236,-4,-6701539,-3428540,0,3393309,-6641813,4,-1002538,-2229567,281197612767569,169119574240313 --285442047611,-4714135695023,-70368744177664,22696468,10805572,0,-2924716,48214404,0,0,12053601,-2701393,0,731179,5674117,-4,-97877,-369162,281197612767569,261620040064353 -31252178169830,-5049200567263,39116566007834,31156120,-16855932,-31156120,2550488,-37517212,-2550488,4,5259517,-2901358,0,637622,-7789030,4,-4119786,1312625,281197612767569,245761488295625 -6177295317695,-2593639328974,-70368744177664,-18280708,-32947000,0,-23006596,20125128,0,0,-5031282,-8236750,0,-5751649,4570177,-4,-229676,-891507,281197612767569,153676265992817 --22843834727919,24681074721826,-8295598397524,7644228,15288456,-60854608,12460132,24920264,48094256,-8,4951582,4885444,4,3535991,5164104,0,-3115033,1911057,281197612767569,43052451207769 --1651155352848,70368744177664,33341478840169,11094976,0,55368100,11239360,0,-45389724,0,11347431,13842025,4,-1065073,1639024,0,2809840,-2773744,281197612767569,47475323684993 -9563910448751,746334372592,-70368744177664,28048828,-20886592,0,16158556,28108224,0,0,7027056,5221648,0,-4039639,7012207,-4,912212,784053,281197612767569,184853238400745 -10828005366016,-9018907571200,-3018842235269,2319360,3092480,593636844,4482048,5976064,-309133076,16,9969211,18987905,-12,11843909,22861374,0,373504,-193280,281197612767569,277617512951697 --8907170144643,-16953279884850,70368744177664,-4856332,-32616648,0,-32127468,16063480,0,0,-4015870,-8154162,0,-8031867,1214083,4,-2443365,-739644,281197612767569,8967736339577 -21512041551946,-7960023607791,48856702625718,-21432024,29226052,21432024,-19161688,-26403452,19161688,4,-4041063,-5678970,0,4790422,-5358006,4,2559800,1627543,281197612767569,110352082925473 --17875847636723,13546936994720,52492896540941,-26111948,-17453440,-26111948,4881300,-39855488,4881300,-4,-7667668,1998205,0,-1220325,-6527987,4,-2296204,2365155,281197612767569,48904542149385 --9548320912614,-19315525818493,41504897446557,27755624,6304268,34059892,-22097048,35545740,13448692,-4,6164281,-3266872,-4,2802108,5248101,4,2722154,1690805,281197612767569,272623376543921 --30226309061861,-40142435115803,-29403865595618,-28917652,28917652,8572024,5663948,-5663948,37255736,-4,-5904887,-1798344,-4,3409047,-3941350,0,1415987,7229413,281197612767569,235728768262809 --26826834235833,5236786921415,-43541909941831,15056156,-34667748,-15056156,-26689188,-13326500,26689188,-4,1564955,-5642938,0,-6672297,-3764039,-4,-1766670,3023999,281197612767569,208048203557569 --24354092022067,24808470180926,21206181974671,-1030348,-33351432,32321084,-34178796,-13599176,-20579620,-4,-789279,-5361376,4,-4355626,-2718895,4,4189073,-2976482,281197612767569,85728097719081 --26641722964401,-17085298248862,13189231064070,14941500,-29883000,-4720616,-1389764,2779528,-74914792,-8,4417024,-1686782,-4,-7155837,-253314,0,-347441,-3735375,281197612767569,125986806773201 -2174575260855,-290860672193,-70368744177664,-24766756,4690172,0,6571580,44215644,0,0,-11053911,1172543,0,1642895,6191689,-4,-348385,10642,281197612767569,98039728782521 --30039224013120,-40329520164544,-11615528295313,1161984,-1161984,-45943364,-24909056,24909056,15926140,-4,-1253972,-6534779,-4,2727563,4951062,0,-6227264,-290496,281197612767569,28379039736289 -994828029838,-70368744177664,18497407237829,8537656,0,-46512364,20934776,0,17823860,0,4455965,11628091,-4,-1312754,725451,0,-5233694,2134414,281197612767569,30877775933257 --16995537345643,7601552600600,-70368744177664,3316308,-31762336,0,-33584428,-17845152,0,0,4461288,-7940584,0,-8396107,-829077,-4,-1984481,1828258,281197612767569,149711506226929 --4936705274313,-55558628354725,25321533516067,621788,-1865364,176732300,6350780,-19052340,-5648148,-12,2828805,34716302,-4,472256,-3155591,0,1587695,-155447,281197612767569,238363375352537 --28896845363714,12575053450236,6600968271033,-12689416,-25378832,-51065116,7961208,15922416,-56689756,-8,-2906049,1686195,4,-5633195,5540042,0,-1990302,-3172354,281197612767569,19495289167105 -10341179950394,-20143177813695,50225566363969,-6034200,-32857852,-32857852,-32749912,8254308,8254308,0,-2063577,-8214463,-4,-6147055,-130448,4,-2040423,1638998,281197612767569,4050204421993 --19238258094507,16029103068870,35101383014287,-6011564,-36404456,30392892,32668756,10544408,22124348,-4,55031,6270602,4,-5586118,1327621,4,2581071,2830512,281197612767569,97812700875793 --19148150503456,-51220593674208,29700619159749,7249792,-7249792,-38768876,25693056,-25693056,17905204,-4,547173,7819836,-4,-3929128,-1872383,0,-6423264,1812448,281197612767569,137687035141369 --13745545458141,23612786725940,-56623198719523,-18920308,-35913520,18920308,19040844,-23365168,-19040844,-4,-6297604,5637365,0,-4760211,-4730077,-4,-456312,-3341015,281197612767569,209452872850465 -14907892605373,-55460851572291,-31259051641543,-18025740,-18025740,-29634332,14955092,14955092,-37874492,4,-9123488,3837207,-4,-345135,3571376,0,-3738773,-4506435,281197612767569,75310284149641 -9575805786781,11441962069005,60792938390883,-21145996,21879860,21145996,-12263436,-40555084,12263436,4,-9257592,-3866025,0,3065859,-5286499,4,881179,1603940,281197612767569,230579199499569 -22154251810717,10937052206619,48214492366947,14928500,37063788,-14928500,-30247148,323276,30247148,4,-1119915,-6928806,0,7561787,3732125,4,-1200734,2337141,281197612767569,132001730994969 --12154469643654,5409801771879,-70368744177664,-27852312,-14618212,0,14343016,-32896036,0,0,-8224009,3654553,0,-3585754,-6963078,-4,1144830,-1166541,281197612767569,132459521793857 --15198307850802,-55170436326862,5490710018465,19832632,-19832632,-2473340,4081272,-4081272,56261092,-4,10947829,871660,-4,-3117444,253325,0,-1020318,4958158,281197612767569,111409776925609 -9619699349736,-60749044827928,-27037070260477,-19643488,-19643488,-37048308,15000480,15000480,-29025268,4,-7705219,6109058,-4,448902,3153019,0,-3750120,-4910872,281197612767569,103431572910673 --34747470421279,-35621273756385,-7025731358300,-8460412,8460412,58046096,16539940,-16539940,19599632,-4,-2893220,7134685,-4,2006688,-7376839,0,4134985,2115103,281197612767569,196639102274873 -30866125352077,39502618825587,-5295880472390,2416180,-2416180,53197544,21438836,-21438836,6039912,4,-444284,7420363,4,1065694,-5879023,0,5359709,-604045,281197612767569,200756889691745 -13376675418402,-56992068759262,14661494897349,-12354424,-12354424,-33212652,-16818104,-16818104,45920884,4,-8421877,-7368300,-4,-3058344,-934863,0,-4204526,3088606,281197612767569,255726311966665 -9360524462839,-61008219714825,-7014649765310,7434204,7434204,62144776,13716316,13716316,-36789752,4,8315810,13284285,-4,881628,2251909,0,3429079,-1858551,281197612767569,200561585359729 --18482528702123,-51886215475541,7028870575489,10867028,-10867028,48017924,12661236,-12661236,-47661020,-4,9101854,8580107,-4,-2813401,-3424374,0,3165309,-2716757,281197612767569,232997549513561 --1082852289426,70368744177664,-18232716789955,10213816,0,57034996,9184312,0,-58946892,0,14736723,14258749,4,821692,-442189,0,2296078,-2553454,281197612767569,147490662297985 -11478452414847,58890291762817,-26409346786155,-9582084,9582084,-48464300,-19399268,19399268,19382836,4,-5875417,-9240680,4,-1029708,2875395,0,-4849817,2395521,281197612767569,47892834277353 -29660367921931,-20317758867981,-40708376255733,-18350036,-32658484,-18350036,-24187092,18309836,-24187092,4,-4393965,-3398676,0,-6046773,4587509,-4,-183494,-4765945,281197612767569,82124407220369 -22391038995715,11860886340444,47977705181949,-16365556,-35775120,16365556,26239980,-11436304,-26239980,4,-843621,6787524,0,-6559995,-4091389,4,2015455,-2156256,281197612767569,180936730267001 -25812247803792,44556496373872,219135547239,15834688,-15834688,7135644,6197824,-6197824,-68310436,4,10808476,1141875,4,-6269133,-642036,0,1549456,-3958672,281197612767569,124197946982561 --21684623593405,-48684120584259,-130892179343,16274700,-16274700,-22250044,-10150996,10150996,-55303004,-4,9569969,-3840816,-4,-4255782,1721695,0,-2537749,-4068675,281197612767569,39688889011209 -29809339140427,40559405037237,-19555861997307,-12019412,12019412,40349716,-13557332,13557332,-48160876,4,-5997873,-6649296,4,6042346,3438133,0,3389333,-3004853,281197612767569,67323857390001 -21823274690378,26722194796908,-117233159627,6305064,-12610128,-57584428,15316072,-30632144,38688372,8,3660173,5472105,4,-3005960,-4462001,0,-3829018,1576266,281197612767569,66825928680345 --21503948564243,-48864795613421,1305542238092,19599284,-19599284,-13447632,11770484,-11770484,49369904,-4,8516151,2425450,-4,-3826325,-936458,0,-2942621,4899821,281197612767569,45279064363969 -6991638586087,-25193727279009,-45175016898655,31199132,-23288452,23288452,-14405316,-25334756,25334756,0,6333689,-5822113,-4,-1682668,-5585739,-4,1918661,2214044,281197612767569,168327160374313 -16610454292443,-8721861395347,-70368744177664,7164780,29138356,0,32916844,-23274572,0,0,5818643,7284589,0,8229211,-1791195,-4,353513,1941528,281197612767569,124361227759313 -20014737284091,50354006893573,27793651251178,-7789588,7789588,-52693080,17495500,-17495500,-26189848,4,-2957634,10195609,4,3589828,-2977661,0,-4373875,-1947397,281197612767569,230272728243641 --34326488053895,36042256123769,18058236277138,1448420,1448420,-42320312,26835492,26835492,-6756664,-4,-2586827,5511948,4,897661,5068130,0,-6708873,362105,281197612767569,267191630457569 -5640135676410,32364304250627,-6845738889580,-11722776,5861388,86010448,-20464472,10232236,-41938992,4,-4573334,-10032131,8,1338080,1438350,0,2558059,-1465347,281197612767569,135688379998281 -25009973918313,45358770259351,-28664104872869,-15719004,15719004,35292524,13294628,-13294628,41777388,4,-5378426,7288025,4,5065921,-1535106,0,3323657,3929751,281197612767569,247405938513905 --694879369871,-70368744177664,-8150512045454,-11390524,0,-47070776,-13951004,0,41193480,0,-10298370,-11767694,-4,505666,-213625,0,-3487751,2847631,281197612767569,170458859289561 -16732741764053,30943615789445,-39425128388219,-28632236,-11341292,-11341292,-13154028,34112468,34112468,0,-8528117,-2835323,4,185437,4684610,-4,-3473944,2473449,281197612767569,146911120885249 -4268297753168,70368744177664,-4635743588905,16320832,0,-23954596,-7780544,0,-57565700,0,14391425,-5988649,4,-1001070,94453,0,-1945136,-4080208,281197612767569,50263278682217 -1277813020099,-16183900485435,-70368744177664,11856652,-38375660,0,-23844852,-17782252,0,0,4445563,-9593915,0,-5961213,-2964163,-4,1451728,507505,281197612767569,75144762180881 --3367144333567,25085420279429,70368744177664,7100420,39364116,0,-27404124,6641972,0,0,1660493,-9841029,0,6851031,1775105,4,-2362837,-1103692,281197612767569,4444301426169 From 48bf868cda3336a64958bfeee8a96ceb0f572bd4 Mon Sep 17 00:00:00 2001 From: Gaider10 <72764892+Gaider10@users.noreply.github.com> Date: Thu, 20 Jun 2024 02:41:37 +0300 Subject: [PATCH 12/78] Fix two pitch cracking and add three pitch cracking --- .../features/VillagerRngSimulator.java | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index b90920210..bb3825118 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -45,6 +45,7 @@ public class VillagerRngSimulator { private float firstPitch = Float.NaN; private int ticksBetweenSounds = 0; private float secondPitch = Float.NaN; + private long[] seedsFromTwoPitches = null; @Nullable private ItemStack activeGoalResult = null; @@ -233,6 +234,7 @@ public void reset() { firstPitch = Float.NaN; ticksBetweenSounds = 0; secondPitch = Float.NaN; + seedsFromTwoPitches = null; activeGoalResult = null; } @@ -258,6 +260,37 @@ public void onAmbientSoundPlayed(float pitch) { secondPitch = pitch; ambientSoundTime = -80; madeSound = true; + + if (seedsFromTwoPitches != null) { + int matchingSeeds = 0; + long matchingSeed = 0; + nextSeed: for (long seed : seedsFromTwoPitches) { + JRand rand = JRand.ofInternalSeed(seed); + rand.nextInt(100); + for (int i = -80; i < ticksBetweenSounds - 80 - 1; i++) { + if (rand.nextInt(1000) < i) { + continue nextSeed; + } + rand.nextInt(100); + } + if (rand.nextInt(1000) >= ticksBetweenSounds - 80 - 1) { + continue; + } + float simulatedThirdPitch = (rand.nextFloat() - rand.nextFloat()) * 0.2f + 1.0f; + if (simulatedThirdPitch == pitch) { + matchingSeeds++; + matchingSeed = rand.getSeed(); + } + } + seedsFromTwoPitches = null; + if (matchingSeeds == 1) { + random = new LegacyRandomSource(matchingSeed ^ 0x5deece66dL); + random.nextInt(100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.crack.success", Long.toHexString(matchingSeed)).withStyle(ChatFormatting.GREEN), 100); + return; + } + } + long[] seeds = crackSeed(); if (seeds.length == 1) { random = new LegacyRandomSource(seeds[0] ^ 0x5deece66dL); @@ -267,6 +300,7 @@ public void onAmbientSoundPlayed(float pitch) { totalAmbientSounds = 1; firstPitch = pitch; secondPitch = Float.NaN; + seedsFromTwoPitches = seeds.length > 0 ? seeds : null; ambientSoundTime = -80; ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.crack.failed", seeds.length).withStyle(ChatFormatting.RED), 100); } @@ -333,7 +367,7 @@ public long[] crackSeed() { } rand.nextInt(100); } - if (rand.nextInt(1000) >= ticksBetweenSounds) { + if (rand.nextInt(1000) >= ticksBetweenSounds - 80 - 1) { return LongStream.empty(); } float simulatedSecondPitch = (rand.nextFloat() - rand.nextFloat()) * 0.2f + 1.0f; From 2734f6438397561a14253ebcc26572cd659111ca Mon Sep 17 00:00:00 2001 From: Gaider10 <72764892+Gaider10@users.noreply.github.com> Date: Thu, 20 Jun 2024 20:40:40 +0300 Subject: [PATCH 13/78] Add simulation for unhappy no and water splashing sounds --- .../features/VillagerCracker.java | 6 +- .../features/VillagerRngSimulator.java | 66 ++++++++++++++++--- .../clientcommands/interfaces/IVillager.java | 4 ++ .../commands/villager/VillagerMixin.java | 13 +++- 4 files changed, 75 insertions(+), 14 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 780386485..4890806af 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -73,8 +73,10 @@ public static void onSoundEventPlayed(ClientboundSoundPacket packet) { return; } - if (packet.getSound().value().getLocation().toString().equals("minecraft:entity.villager.ambient")) { - ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(packet.getPitch()); + switch (packet.getSound().value().getLocation().toString()) { + case "minecraft:entity.villager.ambient" -> ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(packet.getPitch()); + case "minecraft:entity.villager.no" -> ((IVillager) targetVillager).clientcommands_onNoSoundPlayed(packet.getPitch()); + case "minecraft:entity.generic.splash" -> ((IVillager) targetVillager).clientcommands_onSplashSoundPlayed(packet.getPitch()); } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index bb3825118..97e8bd356 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -14,7 +14,9 @@ import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; +import net.minecraft.util.Mth; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.trading.MerchantOffer; @@ -36,15 +38,19 @@ public class VillagerRngSimulator { @Nullable private LegacyRandomSource random; + private long prevRandomSeed; private int ambientSoundTime; + private int prevAmbientSoundTime; private boolean madeSound = false; private int totalAmbientSounds = 0; private int callsAtStartOfBruteForce = 0; private int callsInBruteForce = 0; private int totalCalls = 0; + private int prevTotalCalls; private float firstPitch = Float.NaN; private int ticksBetweenSounds = 0; private float secondPitch = Float.NaN; + @Nullable private long[] seedsFromTwoPitches = null; @Nullable private ItemStack activeGoalResult = null; @@ -115,11 +121,17 @@ public VillagerRngSimulator copy() { } public void simulateTick() { + // called on receiving clock packet at the beginning of the tick, simulates the rest of the tick + if (random == null) { ambientSoundTime++; return; } + prevRandomSeed = random.seed.get(); + prevAmbientSoundTime = ambientSoundTime; + prevTotalCalls = totalCalls; + simulateBaseTick(); simulateServerAiStep(); @@ -128,6 +140,12 @@ public void simulateTick() { } } + private void revertSimulatedTick() { + random.seed.set(prevRandomSeed); + ambientSoundTime = prevAmbientSoundTime; + totalCalls = prevTotalCalls; + } + public boolean shouldInteractWithVillager() { boolean shouldInteractWithVillager = totalCalls - callsAtStartOfBruteForce >= callsInBruteForce && callsInBruteForce > 0; if (shouldInteractWithVillager) { @@ -136,11 +154,7 @@ public boolean shouldInteractWithVillager() { return shouldInteractWithVillager; } - public void simulateBaseTick() { - if (random == null) { - return; - } - + private void simulateBaseTick() { // we have the server receiving ambient noise tell us if we have to do this to increment the random, this is so that our ambient sound time is synced up. totalCalls += 1; if (random.nextInt(1000) < ambientSoundTime++ && totalAmbientSounds > 0) { @@ -154,11 +168,7 @@ public void simulateBaseTick() { } } - public void simulateServerAiStep() { - if (random == null) { - return; - } - + private void simulateServerAiStep() { random.nextInt(100); totalCalls += 1; } @@ -313,6 +323,42 @@ public void onAmbientSoundPlayed(float pitch) { } } + public void onNoSoundPlayed(float pitch) { + // the last received action before the next tick's clock + + if (random != null) { + totalCalls += 2; + float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; + if (pitch != simulatedPitch) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); + reset(); + } + } + } + + public void onSplashSoundPlayed(float pitch) { + // the first received action after this tick's clock + + if (random != null) { + // simulateTick() was already called for this tick assuming no splash happened, so revert it and rerun it with the splash + revertSimulatedTick(); + + totalCalls += 2; + float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.4f + 1.0f; + if (pitch != simulatedPitch) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); + reset(); + return; + } + + int iters = Mth.ceil(1.0f + EntityType.VILLAGER.getDimensions().width() * 20.0f); + totalCalls += iters * 10; + random.consumeCount(iters * 10); + + simulateTick(); + } + } + public long[] crackSeed() { if (!(80 <= ticksBetweenSounds && ticksBetweenSounds - 80 < LATTICES.length)) { return new long[0]; diff --git a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java index 61c5ca551..a04042fe0 100644 --- a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java +++ b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java @@ -17,6 +17,10 @@ public interface IVillager { void clientcommands_onAmbientSoundPlayed(float pitch); + void clientcommands_onNoSoundPlayed(float pitch); + + void clientcommands_onSplashSoundPlayed(float pitch); + void clientcommands_onServerTick(); Pair clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int maxCalls, Predicate predicate); diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index 1dfc8b481..5751f3ae6 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -51,6 +51,16 @@ public void clientcommands_onAmbientSoundPlayed(float pitch) { rng.onAmbientSoundPlayed(pitch); } + @Override + public void clientcommands_onNoSoundPlayed(float pitch) { + rng.onNoSoundPlayed(pitch); + } + + @Override + public void clientcommands_onSplashSoundPlayed(float pitch) { + rng.onSplashSoundPlayed(pitch); + } + @Override public void clientcommands_onServerTick() { rng.simulateTick(); @@ -74,8 +84,7 @@ public Pair clientcommands_bruteForceOffers(Vill int startingCalls = rng.getTotalCalls(); while (rng.getTotalCalls() < maxCalls + startingCalls) { VillagerRngSimulator randomBranch = rng.copy(); - randomBranch.simulateBaseTick(); - randomBranch.simulateServerAiStep(); + randomBranch.simulateTick(); VillagerCommand.Offer offer = randomBranch.anyOffersMatch(listings, (Villager) (Object) this, predicate); if (offer != null) { setVillagerData(getVillagerData().setProfession(oldProfession)); From 47e53f20919b5800b4a3e5d870044a4324c3493d Mon Sep 17 00:00:00 2001 From: Gaider10 <72764892+Gaider10@users.noreply.github.com> Date: Fri, 21 Jun 2024 01:17:52 +0300 Subject: [PATCH 14/78] Add simulation for more actions and add trade cracking for levels above 1 --- .../command/VillagerCommand.java | 29 +++++++++----- .../features/VillagerCracker.java | 11 ++++++ .../features/VillagerRngSimulator.java | 39 ++++++++++++++++++- .../clientcommands/interfaces/IVillager.java | 6 ++- .../commands/villager/VillagerMixin.java | 37 +++++++++++++----- .../rngevents/ClientPacketListenerMixin.java | 9 +++++ .../assets/clientcommands/lang/en_us.json | 1 + 7 files changed, 110 insertions(+), 22 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 79f4cc4d5..171451927 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -47,6 +47,7 @@ public class VillagerCommand { private static final SimpleCommandExceptionType NOT_A_VILLAGER_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notAVillager")); private static final SimpleCommandExceptionType NO_CRACKED_VILLAGER_PRESENT = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noCrackedVillagerPresent")); private static final SimpleCommandExceptionType NO_PROFESSION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noProfession")); + private static final SimpleCommandExceptionType NOT_LEVEL_1 = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notLevel1")); private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); public static final List goals = new ArrayList<>(); @@ -79,7 +80,10 @@ public static void register(CommandDispatcher dispatc .then(argument("pos", blockPos()) .executes(ctx -> setClockPos(getBlockPos(ctx, "pos"))))) .then(literal("brute-force") - .executes(ctx -> bruteForce()))); + .then(literal("first-level") + .executes(ctx -> bruteForce(false))) + .then(literal("next-level") + .executes(ctx -> bruteForce(true))))); } private static int addGoal(WithStringArgument.Result firstPredicate, WithStringArgument.Result firstItemQuantityRange, @Nullable WithStringArgument.Result secondPredicate, @Nullable WithStringArgument.Result secondItemQuantityRange, WithStringArgument.Result resultPredicate, WithStringArgument.Result resultItemQuantityRange) { @@ -146,7 +150,7 @@ private static int setClockPos(BlockPos pos) { return Command.SINGLE_SUCCESS; } - private static int bruteForce() throws CommandSyntaxException { + private static int bruteForce(boolean levelUp) throws CommandSyntaxException { Villager targetVillager = VillagerCracker.getVillager(); if (!(targetVillager instanceof IVillager iVillager) || iVillager.clientcommands_getCrackedRandom() == null) { @@ -157,12 +161,19 @@ private static int bruteForce() throws CommandSyntaxException { throw NO_PROFESSION.create(); } - VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(1, new VillagerTrades.ItemListing[0]); - int adjustment = 2 + Configs.villagerAdjustment; - Pair pair = iVillager.clientcommands_bruteForceOffers(listings, profession, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))).mapFirst(x -> x + adjustment); - int ticks = pair.getFirst(); + int currentLevel = targetVillager.getVillagerData().getLevel(); + if (!levelUp && currentLevel != 1) { + throw NOT_LEVEL_1.create(); + } + + int crackedLevel = levelUp ? currentLevel + 1 : currentLevel; + + VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(crackedLevel, new VillagerTrades.ItemListing[0]); + int adjustment = 2 + Configs.villagerAdjustment + (levelUp ? -80 : 0); + Pair pair = iVillager.clientcommands_bruteForceOffers(listings, profession, levelUp ? 240 : 0, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))).mapFirst(x -> x + adjustment); + int calls = pair.getFirst(); Offer offer = pair.getSecond(); - if (ticks < 0) { + if (calls < 0) { VillagerRngSimulator.CrackedState state = iVillager.clientcommands_getCrackedRandom().getCrackedState(); Component message = state.getMessage(true); if (state.isCracked()) { @@ -176,10 +187,10 @@ private static int bruteForce() throws CommandSyntaxException { } else { price = VillagerCommand.displayText(offer.first()) + " + " + VillagerCommand.displayText(offer.second()); } - ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", VillagerCommand.displayText(offer.result()), price, ticks).withStyle(ChatFormatting.GREEN)); + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", VillagerCommand.displayText(offer.result()), price, calls).withStyle(ChatFormatting.GREEN)); VillagerCracker.targetOffer = offer; System.out.println(offer); - iVillager.clientcommands_getCrackedRandom().setCallsUntilOpenGui(ticks, offer.result()); + iVillager.clientcommands_getCrackedRandom().setCallsUntilToggleGui(calls, offer.result()); } return Command.SINGLE_SUCCESS; diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 4890806af..c3d517670 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -4,6 +4,7 @@ import net.earthcomputer.clientcommands.interfaces.IVillager; import net.minecraft.client.Minecraft; import net.minecraft.core.GlobalPos; +import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; @@ -76,10 +77,20 @@ public static void onSoundEventPlayed(ClientboundSoundPacket packet) { switch (packet.getSound().value().getLocation().toString()) { case "minecraft:entity.villager.ambient" -> ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(packet.getPitch()); case "minecraft:entity.villager.no" -> ((IVillager) targetVillager).clientcommands_onNoSoundPlayed(packet.getPitch()); + case "minecraft:entity.villager.yes" -> ((IVillager) targetVillager).clientcommands_onYesSoundPlayed(packet.getPitch()); case "minecraft:entity.generic.splash" -> ((IVillager) targetVillager).clientcommands_onSplashSoundPlayed(packet.getPitch()); } } + public static void onXpOrbSpawned(ClientboundAddExperienceOrbPacket packet) { + Villager targetVillager = getVillager(); + if (targetVillager == null) { + return; + } + + ((IVillager) targetVillager).clientcommands_onXpOrbSpawned(packet.getValue()); + } + public static void onServerTick() { Villager targetVillager = getVillager(); if (targetVillager == null) { diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 97e8bd356..aca162fe1 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -205,7 +205,7 @@ public LegacyRandomSource getRandom() { return random; } - public void setCallsUntilOpenGui(int calls, ItemStack resultStack) { + public void setCallsUntilToggleGui(int calls, ItemStack resultStack) { callsAtStartOfBruteForce = totalCalls; callsInBruteForce = calls; activeGoalResult = resultStack; @@ -323,11 +323,30 @@ public void onAmbientSoundPlayed(float pitch) { } } - public void onNoSoundPlayed(float pitch) { + public void onNoSoundPlayed(float pitch, boolean fromGuiInteract) { // the last received action before the next tick's clock + // played both when interacting with a villager without a profession and when using the villager gui if (random != null) { totalCalls += 2; + if (fromGuiInteract) { + ambientSoundTime = -80; + } + float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; + if (pitch != simulatedPitch) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); + reset(); + } + } + } + + public void onYesSoundPlayed(float pitch) { + // the last received action before the next tick's clock + // played when using the villager gui + + if (random != null) { + totalCalls += 2; + ambientSoundTime = -80; float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; if (pitch != simulatedPitch) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); @@ -359,6 +378,22 @@ public void onSplashSoundPlayed(float pitch) { } } + public void onXpOrbSpawned(int value) { + // the last received action before the next tick's clock + + if (random != null) { + totalCalls += 1; + ambientSoundTime = -80; + int simulatedValue = 3 + this.random.nextInt(4); + boolean leveledUp = value > 3 + 3; + if (leveledUp) simulatedValue += 5; + if (value != simulatedValue) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); + reset(); + } + } + } + public long[] crackSeed() { if (!(80 <= ticksBetweenSounds && ticksBetweenSounds - 80 < LATTICES.length)) { return new long[0]; diff --git a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java index a04042fe0..384eb321e 100644 --- a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java +++ b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java @@ -19,9 +19,13 @@ public interface IVillager { void clientcommands_onNoSoundPlayed(float pitch); + void clientcommands_onYesSoundPlayed(float pitch); + void clientcommands_onSplashSoundPlayed(float pitch); + void clientcommands_onXpOrbSpawned(int value); + void clientcommands_onServerTick(); - Pair clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int maxCalls, Predicate predicate); + Pair clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int minTicks, int maxCalls, Predicate predicate); } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index 5751f3ae6..c09230847 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -1,15 +1,11 @@ package net.earthcomputer.clientcommands.mixin.commands.villager; import com.mojang.datafixers.util.Pair; -import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; -import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; -import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; +import net.minecraft.client.gui.screens.inventory.MerchantScreen; import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; @@ -53,7 +49,13 @@ public void clientcommands_onAmbientSoundPlayed(float pitch) { @Override public void clientcommands_onNoSoundPlayed(float pitch) { - rng.onNoSoundPlayed(pitch); + VillagerProfession profession = this.getVillagerData().getProfession(); + rng.onNoSoundPlayed(pitch, profession != VillagerProfession.NONE && profession != VillagerProfession.NITWIT); + } + + @Override + public void clientcommands_onYesSoundPlayed(float pitch) { + rng.onYesSoundPlayed(pitch); } @Override @@ -61,27 +63,42 @@ public void clientcommands_onSplashSoundPlayed(float pitch) { rng.onSplashSoundPlayed(pitch); } + @Override + public void clientcommands_onXpOrbSpawned(int value) { + rng.onXpOrbSpawned(value); + } + @Override public void clientcommands_onServerTick() { rng.simulateTick(); if (rng.shouldInteractWithVillager()) { Minecraft minecraft = Minecraft.getInstance(); - InteractionResult result = minecraft.gameMode.interact(minecraft.player, this, InteractionHand.MAIN_HAND); - if (result.consumesAction() && result.shouldSwing()) { - minecraft.player.swing(InteractionHand.MAIN_HAND); + if (minecraft.screen instanceof MerchantScreen) { + minecraft.screen.onClose(); + } else { + InteractionResult result = minecraft.gameMode.interact(minecraft.player, this, InteractionHand.MAIN_HAND); + if (result.consumesAction() && result.shouldSwing()) { + minecraft.player.swing(InteractionHand.MAIN_HAND); + } } } } @Override - public Pair clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int maxCalls, Predicate predicate) { + public Pair clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int minTicks, int maxCalls, Predicate predicate) { if (this instanceof IVillager iVillager && iVillager.clientcommands_getCrackedRandom().getCrackedState().isCracked()) { VillagerProfession oldProfession = getVillagerData().getProfession(); setVillagerData(getVillagerData().setProfession(profession)); VillagerRngSimulator rng = this.rng.copy(); + int startingCalls = rng.getTotalCalls(); + + for (int i = 0; i < minTicks; i++) { + rng.simulateTick(); + } + while (rng.getTotalCalls() < maxCalls + startingCalls) { VillagerRngSimulator randomBranch = rng.copy(); randomBranch.simulateTick(); diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java index d8a369a77..4ec29c5d0 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java @@ -7,6 +7,7 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.core.GlobalPos; +import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; @@ -54,6 +55,14 @@ private void onHandleChunkBlocksUpdate(ClientboundSectionBlocksUpdatePacket pack } } + @Inject(method = "handleAddExperienceOrb", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void onHandleAddExperienceOrb(ClientboundAddExperienceOrbPacket packet, CallbackInfo ci) { + Villager targetVillager = VillagerCracker.getVillager(); + if (targetVillager != null && new Vec3(packet.getX(), packet.getY() - 0.5, packet.getZ()).distanceToSqr(targetVillager.position()) <= 0.1f) { + VillagerCracker.onXpOrbSpawned(packet); + } + } + @Inject(method = "handleBlockUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackInfo ci) { if (Minecraft.getInstance().level != null && new GlobalPos(Minecraft.getInstance().level.dimension(), packet.getPos()).equals(VillagerCracker.getClockPos())) { diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index b555b2c28..913666080 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -254,6 +254,7 @@ "commands.cvillager.listGoals.success": "There are %d villager goals:", "commands.cvillager.noCrackedVillagerPresent": "There was no cracked villager available to use", "commands.cvillager.noProfession": "The targeted villager has no profession.", + "commands.cvillager.notLevel1": "The targeted villager has level above 1.", "commands.cvillager.notAVillager": "Target was not a villager", "commands.cvillager.outOfSync": "Your Villager's RNG was out of sync, re-cracking.", "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals.", From 49105188d19e4b8078835ffc8b3448341bea7c69 Mon Sep 17 00:00:00 2001 From: Gaider10 <72764892+Gaider10@users.noreply.github.com> Date: Fri, 21 Jun 2024 01:37:50 +0300 Subject: [PATCH 15/78] Handle ambient sound inside trading gui correctly --- .../earthcomputer/clientcommands/features/VillagerCracker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index c3d517670..a75bf4e25 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -75,7 +75,7 @@ public static void onSoundEventPlayed(ClientboundSoundPacket packet) { } switch (packet.getSound().value().getLocation().toString()) { - case "minecraft:entity.villager.ambient" -> ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(packet.getPitch()); + case "minecraft:entity.villager.ambient", "minecraft:entity.villager.trade" -> ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(packet.getPitch()); case "minecraft:entity.villager.no" -> ((IVillager) targetVillager).clientcommands_onNoSoundPlayed(packet.getPitch()); case "minecraft:entity.villager.yes" -> ((IVillager) targetVillager).clientcommands_onYesSoundPlayed(packet.getPitch()); case "minecraft:entity.generic.splash" -> ((IVillager) targetVillager).clientcommands_onSplashSoundPlayed(packet.getPitch()); From 5e8f1f2b29d69f4d1e599f02cc87f42ec5ab15e6 Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 20 Jun 2024 19:28:47 -0400 Subject: [PATCH 16/78] ok changed some stuff lol i think this might be good --- .../earthcomputer/clientcommands/Configs.java | 2 +- .../command/VillagerCommand.java | 16 ++-- .../event/MoreClientEvents.java | 12 --- .../features/CrackVillagerRngGen.java | 43 ---------- .../features/VillagerCracker.java | 2 +- .../features/VillagerRngSimulator.java | 84 +++++++++++++------ .../clientcommands/interfaces/IVillager.java | 14 +--- .../commands/villager/VillagerMixin.java | 54 ++---------- .../events/ClientPacketListenerMixin.java | 3 - .../mixin/rngevents/EntityMixin.java | 2 +- .../mixin/rngevents/LivingEntityMixin.java | 6 -- .../util/EstimatedServerTick.java | 48 ----------- 12 files changed, 75 insertions(+), 211 deletions(-) delete mode 100644 src/main/java/net/earthcomputer/clientcommands/features/CrackVillagerRngGen.java delete mode 100644 src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java diff --git a/src/main/java/net/earthcomputer/clientcommands/Configs.java b/src/main/java/net/earthcomputer/clientcommands/Configs.java index eeaa318bc..e15b24431 100644 --- a/src/main/java/net/earthcomputer/clientcommands/Configs.java +++ b/src/main/java/net/earthcomputer/clientcommands/Configs.java @@ -177,7 +177,7 @@ public enum PacketDumpMethod { @Config(temporary = true, setter = @Config.Setter("setMaxVillagerBruteForceSimulationCalls")) public static int maxVillagerBruteForceSimulationCalls = 12000; public static void setMaxVillagerBruteForceSimulationCalls(int maxVillagerBruteForceSimulationCalls) { - Configs.maxVillagerBruteForceSimulationCalls = Mth.clamp(maxVillagerBruteForceSimulationCalls, 0, 65536); + Configs.maxVillagerBruteForceSimulationCalls = Mth.clamp(maxVillagerBruteForceSimulationCalls, 0, 1_000_000); } @Config(temporary = true) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 171451927..9e520769d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -31,7 +31,6 @@ import java.util.ArrayList; import java.util.List; -import java.util.Objects; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -153,7 +152,7 @@ private static int setClockPos(BlockPos pos) { private static int bruteForce(boolean levelUp) throws CommandSyntaxException { Villager targetVillager = VillagerCracker.getVillager(); - if (!(targetVillager instanceof IVillager iVillager) || iVillager.clientcommands_getCrackedRandom() == null) { + if (!(targetVillager instanceof IVillager iVillager) || !iVillager.clientcommands_getVillagerRngSimulator().getCrackedState().isCracked()) { throw NO_CRACKED_VILLAGER_PRESENT.create(); } VillagerProfession profession = targetVillager.getVillagerData().getProfession(); @@ -169,17 +168,12 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { int crackedLevel = levelUp ? currentLevel + 1 : currentLevel; VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(crackedLevel, new VillagerTrades.ItemListing[0]); - int adjustment = 2 + Configs.villagerAdjustment + (levelUp ? -80 : 0); - Pair pair = iVillager.clientcommands_bruteForceOffers(listings, profession, levelUp ? 240 : 0, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))).mapFirst(x -> x + adjustment); + int adjustment = 2 + + (levelUp ? -80 : 0); + Pair pair = iVillager.clientcommands_getVillagerRngSimulator().bruteForceOffers(listings, profession, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))).mapFirst(x -> x + adjustment); int calls = pair.getFirst(); Offer offer = pair.getSecond(); if (calls < 0) { - VillagerRngSimulator.CrackedState state = iVillager.clientcommands_getCrackedRandom().getCrackedState(); - Component message = state.getMessage(true); - if (state.isCracked()) { - message = Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationCalls).withStyle(ChatFormatting.RED); - } - ClientCommandHelper.addOverlayMessage(message, 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationCalls).withStyle(ChatFormatting.RED), 100); } else { String price; if (offer.second() == null) { @@ -190,7 +184,7 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", VillagerCommand.displayText(offer.result()), price, calls).withStyle(ChatFormatting.GREEN)); VillagerCracker.targetOffer = offer; System.out.println(offer); - iVillager.clientcommands_getCrackedRandom().setCallsUntilToggleGui(calls, offer.result()); + iVillager.clientcommands_getVillagerRngSimulator().setCallsUntilToggleGui(calls, offer.result()); } return Command.SINGLE_SUCCESS; diff --git a/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java b/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java index 7b901bc3d..067b44e6f 100644 --- a/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java +++ b/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java @@ -16,21 +16,9 @@ public final class MoreClientEvents { listener.onTimeSync(packet); } }); - public static final Event ESTIMATED_SERVER_TICK = EventFactory.createArrayBacked(EstimatedServerTickEvent.class, listeners -> () -> { - Minecraft.getInstance().tell(() -> { - for (EstimatedServerTickEvent listener : listeners) { - listener.onEstimatedServerTick(); - } - }); - }); @FunctionalInterface public interface TimeSync { void onTimeSync(ClientboundSetTimePacket packet); } - - @FunctionalInterface - public interface EstimatedServerTickEvent { - void onEstimatedServerTick(); - } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/CrackVillagerRngGen.java b/src/main/java/net/earthcomputer/clientcommands/features/CrackVillagerRngGen.java deleted file mode 100644 index cfefd00e8..000000000 --- a/src/main/java/net/earthcomputer/clientcommands/features/CrackVillagerRngGen.java +++ /dev/null @@ -1,43 +0,0 @@ -package net.earthcomputer.clientcommands.features; - -import com.seedfinding.latticg.math.component.BigMatrix; -import com.seedfinding.latticg.math.component.BigVector; -import com.seedfinding.latticg.math.lattice.enumerate.EnumerateRt; -import com.seedfinding.latticg.math.optimize.Optimize; -import com.seedfinding.latticg.util.DeserializeRt; -import java.util.stream.LongStream; - -// CLASS GENERATED BY LATTICG, DO NOT EDIT MANUALLY -public final class CrackVillagerRngGen { - private CrackVillagerRngGen() {} - private static final BigMatrix BASIS = DeserializeRt.mat( - "Ȃ苻봇˃\uf1afᄂ\udaf8찄˦鋃ᜂ"); - private static final BigMatrix ROOT_INV = DeserializeRt.mat( - "Ȃ\ue692쌗肀肀肀老싱꼑肀肀肀老\udbf8찄肀肀肀老苻봇肀肀肀老"); - private static final BigVector ORIGIN = DeserializeRt.vec( - "ȀȖȀ"); - private static final BigVector ROOT_ORIGIN = DeserializeRt.vec( - "˖\ue08e뼁肀肀肀老雉ꥒ肀肀肀老"); - - /** - * Finds all values of {@code seed} that could produce the given results in the following code: - *

{@code
-     *    Random rand = new Random(seed ^ 0x5DEECE66DL);
-     *    // Go backwards by 2 random calls
-     *    long nextLong1 = rand.nextLong();
-     * }
- * - *

This code skips 0.000000% of seeds in its search. - */ - public static LongStream getSeeds(long nextLong1) { - Optimize.Builder builder = Optimize.Builder.ofSize(2); - long longFirstSeed1 = nextLong1 >>> 32 << 16; - if (nextLong1 < 0) { - longFirstSeed1 += (1L << 16); - } - builder.withLowerBound(0, longFirstSeed1).withUpperBound(0, longFirstSeed1 + (1L << 16) - 1); - builder.withLowerBound(1, (nextLong1 & 0xffffffffL) << 16).withUpperBound(1, (((nextLong1 & 0xffffffffL) + 1) << 16) - 1); - return EnumerateRt.enumerate(BASIS, ORIGIN, builder.build(), ROOT_INV, ROOT_ORIGIN) - .mapToLong(vec -> (vec.get(0).getNumerator().longValue() * 0x5deece66dL + 0xbL) & ((1L << 48) - 1)); - } -} diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index a75bf4e25..8255884e8 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -57,7 +57,7 @@ public static GlobalPos getClockPos() { public static void setTargetVillager(@Nullable Villager villager) { Villager oldVillager = getVillager(); if (oldVillager != null) { - ((IVillager) oldVillager).clientcommands_setCrackedRandom(null); + ((IVillager) oldVillager).clientcommands_setRandom(null); } VillagerCracker.cachedVillager = new WeakReference<>(villager); diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index aca162fe1..073be5ca2 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -1,22 +1,29 @@ package net.earthcomputer.clientcommands.features; +import com.mojang.datafixers.util.Pair; import com.seedfinding.latticg.math.component.BigFraction; import com.seedfinding.latticg.math.component.BigMatrix; import com.seedfinding.latticg.math.component.BigVector; import com.seedfinding.latticg.math.lattice.enumerate.EnumerateRt; import com.seedfinding.latticg.math.optimize.Optimize; import com.seedfinding.mcseed.rand.JRand; +import net.earthcomputer.clientcommands.Configs; import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; +import net.earthcomputer.clientcommands.interfaces.IVillager; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; import net.minecraft.util.Mth; +import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.VillagerProfession; import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.trading.MerchantOffer; @@ -37,7 +44,7 @@ public class VillagerRngSimulator { private static final BigVector[] OFFSETS; @Nullable - private LegacyRandomSource random; + private JRand random; private long prevRandomSeed; private int ambientSoundTime; private int prevAmbientSoundTime; @@ -101,13 +108,13 @@ public class VillagerRngSimulator { } } - public VillagerRngSimulator(@Nullable LegacyRandomSource random, int ambientSoundTime) { + public VillagerRngSimulator(@Nullable JRand random, int ambientSoundTime) { this.random = random; this.ambientSoundTime = ambientSoundTime; } public VillagerRngSimulator copy() { - VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : new LegacyRandomSource(random.seed.get() ^ 0x5deece66dL), ambientSoundTime); + VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : random.copy(), ambientSoundTime); that.madeSound = this.madeSound; that.totalAmbientSounds = this.totalAmbientSounds; that.callsAtStartOfBruteForce = this.callsAtStartOfBruteForce; @@ -128,7 +135,7 @@ public void simulateTick() { return; } - prevRandomSeed = random.seed.get(); + prevRandomSeed = random.getSeed(); prevAmbientSoundTime = ambientSoundTime; prevTotalCalls = totalCalls; @@ -141,13 +148,13 @@ public void simulateTick() { } private void revertSimulatedTick() { - random.seed.set(prevRandomSeed); + random.setSeed(prevRandomSeed); ambientSoundTime = prevAmbientSoundTime; totalCalls = prevTotalCalls; } public boolean shouldInteractWithVillager() { - boolean shouldInteractWithVillager = totalCalls - callsAtStartOfBruteForce >= callsInBruteForce && callsInBruteForce > 0; + boolean shouldInteractWithVillager = totalCalls - callsAtStartOfBruteForce >= callsInBruteForce - Configs.villagerAdjustment * 2 && callsInBruteForce > 0; if (shouldInteractWithVillager) { reset(); } @@ -174,7 +181,7 @@ private void simulateServerAiStep() { } public void updateProgressBar() { - ClientCommandHelper.updateOverlayProgressBar(Math.min(callsInBruteForce, totalCalls - callsAtStartOfBruteForce), callsInBruteForce, 50, 60); + ClientCommandHelper.updateOverlayProgressBar(Math.min(callsInBruteForce - Configs.villagerAdjustment * 2, totalCalls - callsAtStartOfBruteForce), callsInBruteForce - Configs.villagerAdjustment * 2, 50, 60); } @Nullable @@ -183,11 +190,13 @@ public VillagerCommand.Offer anyOffersMatch(VillagerTrades.ItemListing[] listing return null; } + RandomSource rand = new LegacyRandomSource(random.getSeed() ^ 0x5deece66dL);; + ArrayList newListings = new ArrayList<>(List.of(listings)); int i = 0; while (i < 2 && !newListings.isEmpty()) { - VillagerTrades.ItemListing listing = newListings.remove(random.nextInt(newListings.size())); - MerchantOffer offer = listing.getOffer(trader, random); + VillagerTrades.ItemListing listing = newListings.remove(rand.nextInt(newListings.size())); + MerchantOffer offer = listing.getOffer(trader, rand); if (offer != null) { VillagerCommand.Offer x = new VillagerCommand.Offer(offer.getBaseCostA(), offer.getCostB(), offer.getResult()); if (predicate.test(x)) { @@ -200,11 +209,6 @@ public VillagerCommand.Offer anyOffersMatch(VillagerTrades.ItemListing[] listing return null; } - @Nullable - public LegacyRandomSource getRandom() { - return random; - } - public void setCallsUntilToggleGui(int calls, ItemStack resultStack) { callsAtStartOfBruteForce = totalCalls; callsInBruteForce = calls; @@ -231,7 +235,7 @@ public CrackedState getCrackedState() { return CrackedState.CRACKED; } - public void setRandom(@Nullable LegacyRandomSource random) { + public void setRandom(@Nullable JRand random) { this.random = random; } @@ -250,8 +254,7 @@ public void reset() { @Override public String toString() { - return "VillagerRngSimulator[" + - "seed=" + (random == null ? "null" : random.seed.get()) + ']'; + return "VillagerRngSimulator[seed=" + (random == null ? "null" : random.getSeed()) + ']'; } public void onAmbientSoundPlayed(float pitch) { @@ -260,7 +263,7 @@ public void onAmbientSoundPlayed(float pitch) { firstPitch = pitch; ambientSoundTime = -80; madeSound = true; - ClientCommandHelper.addOverlayMessage(getCrackedState().getMessage(true), 100); + ClientCommandHelper.addOverlayMessage(((MutableComponent) getCrackedState().getMessage(false)).withStyle(ChatFormatting.RED), 100); return; } @@ -294,7 +297,7 @@ public void onAmbientSoundPlayed(float pitch) { } seedsFromTwoPitches = null; if (matchingSeeds == 1) { - random = new LegacyRandomSource(matchingSeed ^ 0x5deece66dL); + random = JRand.ofInternalSeed(matchingSeed); random.nextInt(100); ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.crack.success", Long.toHexString(matchingSeed)).withStyle(ChatFormatting.GREEN), 100); return; @@ -303,7 +306,7 @@ public void onAmbientSoundPlayed(float pitch) { long[] seeds = crackSeed(); if (seeds.length == 1) { - random = new LegacyRandomSource(seeds[0] ^ 0x5deece66dL); + random = JRand.ofInternalSeed(seeds[0]); random.nextInt(100); ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.crack.success", Long.toHexString(seeds[0])).withStyle(ChatFormatting.GREEN), 100); } else { @@ -370,9 +373,9 @@ public void onSplashSoundPlayed(float pitch) { return; } - int iters = Mth.ceil(1.0f + EntityType.VILLAGER.getDimensions().width() * 20.0f); - totalCalls += iters * 10; - random.consumeCount(iters * 10); + int iterations = Mth.ceil(1.0f + EntityType.VILLAGER.getDimensions().width() * 20.0f); + totalCalls += iterations * 10; + random.advance(iterations * 10L); simulateTick(); } @@ -394,6 +397,37 @@ public void onXpOrbSpawned(int value) { } } + public Pair bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int minTicks, int maxCalls, Predicate predicate) { + Villager targetVillager = VillagerCracker.getVillager(); + if (targetVillager != null && getCrackedState().isCracked()) { + VillagerProfession oldProfession = targetVillager.getVillagerData().getProfession(); + targetVillager.setVillagerData(targetVillager.getVillagerData().setProfession(profession)); + + VillagerRngSimulator rng = this.copy(); + int startingCalls = rng.getTotalCalls(); + + for (int i = 0; i < minTicks; i++) { + rng.simulateTick(); + } + + while (rng.getTotalCalls() < maxCalls + startingCalls) { + VillagerRngSimulator randomBranch = rng.copy(); + randomBranch.simulateTick(); + VillagerCommand.Offer offer = randomBranch.anyOffersMatch(listings, targetVillager, predicate); + if (offer != null) { + targetVillager.setVillagerData(targetVillager.getVillagerData().setProfession(oldProfession)); + // we do the calls before this ticks processing so that since with 0ms ping, the server reads it next tick + return Pair.of(rng.getTotalCalls() - startingCalls, offer); + } + rng.simulateTick(); + } + + targetVillager.setVillagerData(targetVillager.getVillagerData().setProfession(oldProfession)); + } + + return Pair.of(-1_000_000, null); + } + public long[] crackSeed() { if (!(80 <= ticksBetweenSounds && ticksBetweenSounds - 80 < LATTICES.length)) { return new long[0]; @@ -473,8 +507,8 @@ public boolean isCracked() { public Component getMessage(boolean addColor) { return switch (this) { case UNCRACKED -> Component.translatable("commands.cvillager.noCrackedVillagerPresent").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); - case PENDING_FIRST_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 0).withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); - case PENDING_SECOND_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 50).withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); + case PENDING_FIRST_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 0).withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); + case PENDING_SECOND_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 50).withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); case CRACKED -> Component.translatable("commands.cvillager.inSync", 100).withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); }; } diff --git a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java index 384eb321e..d782fe587 100644 --- a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java +++ b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java @@ -1,19 +1,13 @@ package net.earthcomputer.clientcommands.interfaces; -import com.mojang.datafixers.util.Pair; -import net.earthcomputer.clientcommands.command.VillagerCommand; +import com.seedfinding.mcseed.rand.JRand; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; -import net.minecraft.util.RandomSource; -import net.minecraft.world.entity.npc.VillagerProfession; -import net.minecraft.world.entity.npc.VillagerTrades; import org.jetbrains.annotations.Nullable; -import java.util.function.Predicate; - public interface IVillager { - void clientcommands_setCrackedRandom(@Nullable RandomSource random); + void clientcommands_setRandom(@Nullable JRand random); - VillagerRngSimulator clientcommands_getCrackedRandom(); + VillagerRngSimulator clientcommands_getVillagerRngSimulator(); void clientcommands_onAmbientSoundPlayed(float pitch); @@ -26,6 +20,4 @@ public interface IVillager { void clientcommands_onXpOrbSpawned(int value); void clientcommands_onServerTick(); - - Pair clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int minTicks, int maxCalls, Predicate predicate); } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index c09230847..50f18e159 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -1,35 +1,23 @@ package net.earthcomputer.clientcommands.mixin.commands.villager; -import com.mojang.datafixers.util.Pair; -import net.earthcomputer.clientcommands.command.VillagerCommand; +import com.seedfinding.mcseed.rand.JRand; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.inventory.MerchantScreen; -import net.minecraft.util.RandomSource; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.npc.AbstractVillager; import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.entity.npc.VillagerData; import net.minecraft.world.entity.npc.VillagerProfession; -import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.level.Level; -import net.minecraft.world.level.levelgen.LegacyRandomSource; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Unique; -import java.util.function.Predicate; - @Mixin(Villager.class) public abstract class VillagerMixin extends AbstractVillager implements IVillager { - @Shadow public abstract VillagerData getVillagerData(); - - @Shadow public abstract void setVillagerData(VillagerData data); - public VillagerMixin(EntityType entityType, Level level) { super(entityType, level); } @@ -38,8 +26,8 @@ public VillagerMixin(EntityType entityType, Level le VillagerRngSimulator rng = new VillagerRngSimulator(null, -80); @Override - public void clientcommands_setCrackedRandom(@Nullable RandomSource random) { - rng.setRandom((LegacyRandomSource) random); + public void clientcommands_setRandom(@Nullable JRand random) { + rng.setRandom(random); } @Override @@ -49,7 +37,7 @@ public void clientcommands_onAmbientSoundPlayed(float pitch) { @Override public void clientcommands_onNoSoundPlayed(float pitch) { - VillagerProfession profession = this.getVillagerData().getProfession(); + VillagerProfession profession = ((Villager) (Object) this).getVillagerData().getProfession(); rng.onNoSoundPlayed(pitch, profession != VillagerProfession.NONE && profession != VillagerProfession.NITWIT); } @@ -86,39 +74,7 @@ public void clientcommands_onServerTick() { } @Override - public Pair clientcommands_bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int minTicks, int maxCalls, Predicate predicate) { - if (this instanceof IVillager iVillager && iVillager.clientcommands_getCrackedRandom().getCrackedState().isCracked()) { - VillagerProfession oldProfession = getVillagerData().getProfession(); - setVillagerData(getVillagerData().setProfession(profession)); - - VillagerRngSimulator rng = this.rng.copy(); - - int startingCalls = rng.getTotalCalls(); - - for (int i = 0; i < minTicks; i++) { - rng.simulateTick(); - } - - while (rng.getTotalCalls() < maxCalls + startingCalls) { - VillagerRngSimulator randomBranch = rng.copy(); - randomBranch.simulateTick(); - VillagerCommand.Offer offer = randomBranch.anyOffersMatch(listings, (Villager) (Object) this, predicate); - if (offer != null) { - setVillagerData(getVillagerData().setProfession(oldProfession)); - // we do the calls before this ticks processing so that since with 0ms ping, the server reads it next tick - return Pair.of(rng.getTotalCalls() - startingCalls, offer); - } - rng.simulateTick(); - } - - setVillagerData(getVillagerData().setProfession(oldProfession)); - } - - return Pair.of(-1_000_000, null); - } - - @Override - public VillagerRngSimulator clientcommands_getCrackedRandom() { + public VillagerRngSimulator clientcommands_getVillagerRngSimulator() { return rng; } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java index d9021af03..41c35bb19 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java @@ -2,14 +2,12 @@ import net.earthcomputer.clientcommands.event.MoreClientEntityEvents; import net.earthcomputer.clientcommands.event.MoreClientEvents; -import net.earthcomputer.clientcommands.util.EstimatedServerTick; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundSetTimePacket; 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; @@ -34,7 +32,6 @@ public void onHandleAddExperienceOrb(ClientboundAddExperienceOrbPacket packet, C @Inject(method = "handleSetTime", at = @At("HEAD")) private void onHandleSetTime(ClientboundSetTimePacket packet, CallbackInfo ci) { if (Minecraft.getInstance().isSameThread()) { - EstimatedServerTick.onSetTime(packet.getGameTime()); MoreClientEvents.TIME_SYNC.invoker().onTimeSync(packet); } else { MoreClientEvents.TIME_SYNC_ON_NETWORK_THREAD.invoker().onTimeSync(packet); diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java index a7d51f9ce..60e43cb18 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/EntityMixin.java @@ -10,7 +10,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(Entity.class) -public abstract class EntityMixin { +public class EntityMixin { @Inject(method = "doWaterSplashEffect", at = @At("HEAD")) public void onDoWaterSplashEffect(CallbackInfo ci) { if (isThePlayer()) { diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java index 003e80f41..a7cd7460a 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/LivingEntityMixin.java @@ -2,25 +2,19 @@ import com.google.common.base.Objects; import net.earthcomputer.clientcommands.features.PlayerRandCracker; -import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.util.CUtil; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; -import net.minecraft.sounds.SoundEvent; import net.minecraft.tags.BlockTags; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; -import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.item.ItemStack; -import net.minecraft.world.item.enchantment.EnchantmentHelper; import net.minecraft.world.item.enchantment.Enchantments; import net.minecraft.world.level.Level; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.FrostedIceBlock; import net.minecraft.world.level.block.state.BlockState; -import net.minecraft.world.level.levelgen.LegacyRandomSource; import net.minecraft.world.phys.shapes.CollisionContext; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; diff --git a/src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java b/src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java deleted file mode 100644 index 56e0743df..000000000 --- a/src/main/java/net/earthcomputer/clientcommands/util/EstimatedServerTick.java +++ /dev/null @@ -1,48 +0,0 @@ -package net.earthcomputer.clientcommands.util; - -import net.earthcomputer.clientcommands.event.MoreClientEvents; -import net.earthcomputer.clientcommands.features.VillagerCracker; - -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; - -public class EstimatedServerTick { - private static long lastServerSetTime = 0; - private static long lastGameTime = 0; - private static final AtomicLong estimatedNsPerTick = new AtomicLong(50_000_000L); - private static final AtomicInteger ticksRemaining = new AtomicInteger(0); - - public static void onSetTime(long gameTime) { - long ns = System.nanoTime(); - long estimatedNsPerTick; - if (lastServerSetTime == 0) { - // assuming 20 tps - estimatedNsPerTick = 50_000_000L; - } else { - estimatedNsPerTick = (ns - lastServerSetTime) / Math.max(1, gameTime - lastGameTime); - } - lastGameTime = gameTime; - lastServerSetTime = ns; - EstimatedServerTick.estimatedNsPerTick.set(0); - // spin loop - while (ticksRemaining.get() > 0); - EstimatedServerTick.estimatedNsPerTick.set(estimatedNsPerTick); - ticksRemaining.set(20); - } - - static { - new Thread(() -> { - long lastTickTimestamp = 0; - - while (true) { - long ns = System.nanoTime(); - if (ns >= lastTickTimestamp + estimatedNsPerTick.get() && EstimatedServerTick.ticksRemaining.getAndDecrement() > 0) { - lastTickTimestamp = ns; - MoreClientEvents.ESTIMATED_SERVER_TICK.invoker().onEstimatedServerTick(); - } - } - }, "Estimated Server Tick Thread").start(); - -// MoreClientEvents.ESTIMATED_SERVER_TICK.register(VillagerCracker::onServerTick); - } -} From 4642e34c846222a625937b4c1626ef33625a5937 Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 20 Jun 2024 19:31:21 -0400 Subject: [PATCH 17/78] removed latticg code --- .../clientcommands/codegen/CodeGenerator.java | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/codeGen/java/net/earthcomputer/clientcommands/codegen/CodeGenerator.java b/src/codeGen/java/net/earthcomputer/clientcommands/codegen/CodeGenerator.java index 2c40de19a..d22be46bd 100644 --- a/src/codeGen/java/net/earthcomputer/clientcommands/codegen/CodeGenerator.java +++ b/src/codeGen/java/net/earthcomputer/clientcommands/codegen/CodeGenerator.java @@ -20,18 +20,7 @@ public static void main(String[] args) throws IOException { Path destDir = Path.of(args[0]); genPlayerLattiCG(destDir); - genVillagerLattiCG(destDir); } - - private static void genVillagerLattiCG(Path destDir) throws IOException { - ProgramBuilder program = Program.builder(LCG.JAVA); - - program.skip(-2); - program.add(JavaCalls.nextLong()); - - writeLattiCGClass(program.build(), "net.earthcomputer.clientcommands.features.CrackVillagerRngGen", destDir); - } - private static void genPlayerLattiCG(Path destDir) throws IOException { ProgramBuilder program = Program.builder(LCG.JAVA); program.skip(-CCrackRng.NUM_THROWS * 4); From 0bc41671d88e4a8c5012dbef2823e5483c7de203 Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 20 Jun 2024 19:38:38 -0400 Subject: [PATCH 18/78] removed unused diff --- .../net/earthcomputer/clientcommands/ClientCommands.java | 4 ---- .../clientcommands/command/VillagerCommand.java | 1 - .../earthcomputer/clientcommands/event/MoreClientEvents.java | 1 - .../clientcommands/features/FishingCracker.java | 4 ---- .../mixin/events/ClientPacketListenerMixin.java | 1 + .../net/earthcomputer/clientcommands/util/DebugRandom.java | 5 +++-- 6 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java index 708287b61..beeb377d4 100644 --- a/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java +++ b/src/main/java/net/earthcomputer/clientcommands/ClientCommands.java @@ -23,10 +23,6 @@ import net.minecraft.Util; import net.minecraft.client.Minecraft; import net.minecraft.commands.CommandBuildContext; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.ListTag; -import net.minecraft.nbt.LongArrayTag; -import net.minecraft.nbt.NbtIo; import org.slf4j.Logger; import java.io.IOException; diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 9e520769d..0ca1a3014 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -10,7 +10,6 @@ import net.earthcomputer.clientcommands.command.arguments.WithStringArgument; import net.earthcomputer.clientcommands.features.FishingCracker; import net.earthcomputer.clientcommands.features.VillagerCracker; -import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.ChatFormatting; diff --git a/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java b/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java index 067b44e6f..803c21b31 100644 --- a/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java +++ b/src/main/java/net/earthcomputer/clientcommands/event/MoreClientEvents.java @@ -2,7 +2,6 @@ import net.fabricmc.fabric.api.event.Event; import net.fabricmc.fabric.api.event.EventFactory; -import net.minecraft.client.Minecraft; import net.minecraft.network.protocol.game.ClientboundSetTimePacket; public final class MoreClientEvents { diff --git a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java index 99eb82f3f..fd7865a32 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java @@ -635,10 +635,6 @@ private static void onTimeSync() { } } - public static int getMagicMillisecondsCorrection() { - return magicMillisecondsCorrection; - } - public static void onThrownFishingRod(ItemStack stack) { if (expectedFishingRodUses > 0) { expectedFishingRodUses--; diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java index 41c35bb19..b948c017a 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/events/ClientPacketListenerMixin.java @@ -14,6 +14,7 @@ @Mixin(ClientPacketListener.class) public class ClientPacketListenerMixin { + @Inject(method = "handleAddEntity", at = @At("HEAD")) public void onHandleAddEntityPre(ClientboundAddEntityPacket packet, CallbackInfo ci) { MoreClientEntityEvents.PRE_ADD_MAYBE_ON_NETWORK_THREAD.invoker().onAddEntity(packet); diff --git a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java index 0fc1f4b4c..41dca4c96 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java @@ -1,6 +1,5 @@ package net.earthcomputer.clientcommands.util; -import com.mojang.blaze3d.platform.ClipboardManager; import com.mojang.logging.LogUtils; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; @@ -32,8 +31,10 @@ import java.io.StringWriter; import java.nio.file.Files; import java.nio.file.Path; -import java.util.*; +import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Vector; import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; From 4e65243b9d4f26068d0894a265e767f02dd8f83c Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 20 Jun 2024 22:05:35 -0400 Subject: [PATCH 19/78] added help dialog for failed clock, no clock set, cracking during the day, and held item in mainhand --- .../command/VillagerCommand.java | 29 +++++++++++-- .../features/VillagerCracker.java | 34 ++++++++++++++- .../features/VillagerRngSimulator.java | 41 ++++++------------- .../clientcommands/interfaces/IVillager.java | 4 -- .../commands/villager/VillagerMixin.java | 7 ---- .../rngevents/ClientPacketListenerMixin.java | 17 ++++++-- .../mixin/rngevents/MerchantScreenMixin.java | 2 +- .../assets/clientcommands/lang/en_us.json | 16 +++++--- 8 files changed, 95 insertions(+), 55 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 0ca1a3014..61a0225aa 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -46,6 +46,7 @@ public class VillagerCommand { private static final SimpleCommandExceptionType NO_CRACKED_VILLAGER_PRESENT = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noCrackedVillagerPresent")); private static final SimpleCommandExceptionType NO_PROFESSION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noProfession")); private static final SimpleCommandExceptionType NOT_LEVEL_1 = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notLevel1")); + private static final SimpleCommandExceptionType NO_GOALS = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.listGoals.noGoals")); private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); public static final List goals = new ArrayList<>(); @@ -77,7 +78,10 @@ public static void register(CommandDispatcher dispatc .then(literal("clock") .then(argument("pos", blockPos()) .executes(ctx -> setClockPos(getBlockPos(ctx, "pos"))))) + .then(literal("reset-cracker") + .executes(ctx -> resetCracker())) .then(literal("brute-force") + .executes(ctx -> bruteForce(false)) .then(literal("first-level") .executes(ctx -> bruteForce(false))) .then(literal("next-level") @@ -103,7 +107,11 @@ private static int listGoals(FabricClientCommandSource source) { if (goals.isEmpty()) { source.sendFeedback(Component.translatable("commands.cvillager.listGoals.noGoals").withStyle(style -> style.withColor(ChatFormatting.RED))); } else { - source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", FishingCracker.goals.size() + 1)); + if (FishingCracker.goals.size() == 1) { + source.sendFeedback(Component.translatable("commands.cvillager.listGoal.success")); + } else { + source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", FishingCracker.goals.size() + 1)); + } for (int i = 0; i < goals.size(); i++) { Goal goal = goals.get(i); source.sendFeedback(Component.literal((i + 1) + ": " + goal.toString())); @@ -148,9 +156,23 @@ private static int setClockPos(BlockPos pos) { return Command.SINGLE_SUCCESS; } + private static int resetCracker() { + Villager targetVillager = VillagerCracker.getVillager(); + if (targetVillager instanceof IVillager iVillager) { + iVillager.clientcommands_getVillagerRngSimulator().reset(); + ClientCommandHelper.sendFeedback("commands.cvillager.resetCracker"); + } + + return Command.SINGLE_SUCCESS; + } + private static int bruteForce(boolean levelUp) throws CommandSyntaxException { Villager targetVillager = VillagerCracker.getVillager(); + if (goals.isEmpty()) { + throw NO_GOALS.create(); + } + if (!(targetVillager instanceof IVillager iVillager) || !iVillager.clientcommands_getVillagerRngSimulator().getCrackedState().isCracked()) { throw NO_CRACKED_VILLAGER_PRESENT.create(); } @@ -167,8 +189,8 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { int crackedLevel = levelUp ? currentLevel + 1 : currentLevel; VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(crackedLevel, new VillagerTrades.ItemListing[0]); - int adjustment = 2 + + (levelUp ? -80 : 0); - Pair pair = iVillager.clientcommands_getVillagerRngSimulator().bruteForceOffers(listings, profession, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))).mapFirst(x -> x + adjustment); + int adjustmentTicks = 1 + (levelUp ? -40 : 0); + Pair pair = iVillager.clientcommands_getVillagerRngSimulator().bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))).mapFirst(x -> x + adjustmentTicks * 2); int calls = pair.getFirst(); Offer offer = pair.getSecond(); if (calls < 0) { @@ -182,7 +204,6 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { } ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", VillagerCommand.displayText(offer.result()), price, calls).withStyle(ChatFormatting.GREEN)); VillagerCracker.targetOffer = offer; - System.out.println(offer); iVillager.clientcommands_getVillagerRngSimulator().setCallsUntilToggleGui(calls, offer.result()); } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 8255884e8..1ab24e127 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -1,13 +1,18 @@ package net.earthcomputer.clientcommands.features; +import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.interfaces.IVillager; import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.GlobalPos; +import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.VillagerProfession; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; @@ -25,6 +30,9 @@ public class VillagerCracker { private static GlobalPos clockPos = null; @Nullable public static VillagerCommand.Offer targetOffer = null; + @Nullable + private static Long lastServerTick = null; + private static boolean receivedClockRateWarning = false; @Nullable public static Villager getVillager() { @@ -57,7 +65,17 @@ public static GlobalPos getClockPos() { public static void setTargetVillager(@Nullable Villager villager) { Villager oldVillager = getVillager(); if (oldVillager != null) { - ((IVillager) oldVillager).clientcommands_setRandom(null); + ((IVillager) oldVillager).clientcommands_getVillagerRngSimulator().reset(); + } + + if (clockPos == null) { + ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.noClock")); + } + + ClientLevel level = Minecraft.getInstance().level; + + if (level.getDayTime() < 12000 || (level.dimensionType().fixedTime().isPresent() && level.dimensionType().fixedTime().getAsLong() < 12000)) { + ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); } VillagerCracker.cachedVillager = new WeakReference<>(villager); @@ -92,11 +110,25 @@ public static void onXpOrbSpawned(ClientboundAddExperienceOrbPacket packet) { } public static void onServerTick() { + long now = System.currentTimeMillis(); + Villager targetVillager = getVillager(); if (targetVillager == null) { + lastServerTick = now; return; } + if (lastServerTick != null && now - lastServerTick > 50L && !receivedClockRateWarning) { + ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.tooSlow")); + receivedClockRateWarning = true; + } + + if (targetVillager.getVillagerData().getProfession() != VillagerProfession.NONE && targetVillager.getVillagerData().getProfession() != VillagerProfession.NITWIT && !Minecraft.getInstance().player.getItemInHand(InteractionHand.MAIN_HAND).isEmpty()) { + ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.heldItem")); + } + ((IVillager) targetVillager).clientcommands_onServerTick(); + + lastServerTick = now; } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 073be5ca2..6658f2df6 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -10,7 +10,6 @@ import net.earthcomputer.clientcommands.Configs; import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; -import net.earthcomputer.clientcommands.interfaces.IVillager; import net.minecraft.ChatFormatting; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; @@ -23,7 +22,6 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.entity.npc.VillagerProfession; import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.trading.MerchantOffer; @@ -148,7 +146,7 @@ public void simulateTick() { } private void revertSimulatedTick() { - random.setSeed(prevRandomSeed); + random.setSeed(prevRandomSeed, false); ambientSoundTime = prevAmbientSoundTime; totalCalls = prevTotalCalls; } @@ -220,15 +218,7 @@ public int getTotalCalls() { } public CrackedState getCrackedState() { - if (totalAmbientSounds == 0) { - return CrackedState.PENDING_FIRST_AMBIENT_SOUND; - } - - if (totalAmbientSounds == 1) { - return CrackedState.PENDING_SECOND_AMBIENT_SOUND; - } - - if (random == null) { + if (random == null || totalAmbientSounds < 2) { return CrackedState.UNCRACKED; } @@ -241,6 +231,9 @@ public void setRandom(@Nullable JRand random) { public void reset() { random = null; + prevRandomSeed = 0; + prevAmbientSoundTime = 0; + prevTotalCalls = 0; totalAmbientSounds = 0; totalCalls = 0; callsAtStartOfBruteForce = 0; @@ -321,7 +314,7 @@ public void onAmbientSoundPlayed(float pitch) { } if (!madeSound) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); reset(); } } @@ -337,7 +330,7 @@ public void onNoSoundPlayed(float pitch, boolean fromGuiInteract) { } float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; if (pitch != simulatedPitch) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); reset(); } } @@ -352,7 +345,7 @@ public void onYesSoundPlayed(float pitch) { ambientSoundTime = -80; float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; if (pitch != simulatedPitch) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); reset(); } } @@ -368,7 +361,7 @@ public void onSplashSoundPlayed(float pitch) { totalCalls += 2; float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.4f + 1.0f; if (pitch != simulatedPitch) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); reset(); return; } @@ -391,18 +384,15 @@ public void onXpOrbSpawned(int value) { boolean leveledUp = value > 3 + 3; if (leveledUp) simulatedValue += 5; if (value != simulatedValue) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync").withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); reset(); } } } - public Pair bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerProfession profession, int minTicks, int maxCalls, Predicate predicate) { + public Pair bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxCalls, Predicate predicate) { Villager targetVillager = VillagerCracker.getVillager(); if (targetVillager != null && getCrackedState().isCracked()) { - VillagerProfession oldProfession = targetVillager.getVillagerData().getProfession(); - targetVillager.setVillagerData(targetVillager.getVillagerData().setProfession(profession)); - VillagerRngSimulator rng = this.copy(); int startingCalls = rng.getTotalCalls(); @@ -415,14 +405,11 @@ public Pair bruteForceOffers(VillagerTrades.Item randomBranch.simulateTick(); VillagerCommand.Offer offer = randomBranch.anyOffersMatch(listings, targetVillager, predicate); if (offer != null) { - targetVillager.setVillagerData(targetVillager.getVillagerData().setProfession(oldProfession)); // we do the calls before this ticks processing so that since with 0ms ping, the server reads it next tick return Pair.of(rng.getTotalCalls() - startingCalls, offer); } rng.simulateTick(); } - - targetVillager.setVillagerData(targetVillager.getVillagerData().setProfession(oldProfession)); } return Pair.of(-1_000_000, null); @@ -496,8 +483,6 @@ public long[] crackSeed() { public enum CrackedState { UNCRACKED, - PENDING_FIRST_AMBIENT_SOUND, - PENDING_SECOND_AMBIENT_SOUND, CRACKED; public boolean isCracked() { @@ -507,9 +492,7 @@ public boolean isCracked() { public Component getMessage(boolean addColor) { return switch (this) { case UNCRACKED -> Component.translatable("commands.cvillager.noCrackedVillagerPresent").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); - case PENDING_FIRST_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 0).withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); - case PENDING_SECOND_AMBIENT_SOUND -> Component.translatable("commands.cvillager.inSync", 50).withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); - case CRACKED -> Component.translatable("commands.cvillager.inSync", 100).withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); + case CRACKED -> Component.translatable("commands.cvillager.inSync").withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); }; } } diff --git a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java index d782fe587..6c10c0f19 100644 --- a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java +++ b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java @@ -1,12 +1,8 @@ package net.earthcomputer.clientcommands.interfaces; -import com.seedfinding.mcseed.rand.JRand; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; -import org.jetbrains.annotations.Nullable; public interface IVillager { - void clientcommands_setRandom(@Nullable JRand random); - VillagerRngSimulator clientcommands_getVillagerRngSimulator(); void clientcommands_onAmbientSoundPlayed(float pitch); diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index 50f18e159..daa400df9 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -1,6 +1,5 @@ package net.earthcomputer.clientcommands.mixin.commands.villager; -import com.seedfinding.mcseed.rand.JRand; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; import net.minecraft.client.Minecraft; @@ -12,7 +11,6 @@ import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.VillagerProfession; import net.minecraft.world.level.Level; -import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; @@ -25,11 +23,6 @@ public VillagerMixin(EntityType entityType, Level le @Unique VillagerRngSimulator rng = new VillagerRngSimulator(null, -80); - @Override - public void clientcommands_setRandom(@Nullable JRand random) { - rng.setRandom(random); - } - @Override public void clientcommands_onAmbientSoundPlayed(float pitch) { rng.onAmbientSoundPlayed(pitch); diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java index 4ec29c5d0..5d11ec83d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java @@ -1,16 +1,15 @@ package net.earthcomputer.clientcommands.mixin.rngevents; import com.mojang.brigadier.StringReader; +import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.features.PlayerRandCracker; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.core.GlobalPos; -import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; -import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; -import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; -import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.*; import net.minecraft.resources.ResourceKey; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.level.Level; @@ -69,4 +68,14 @@ private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackIn VillagerCracker.onServerTick(); } } + + @Inject(method = "handleSetTime", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void handleSetTime(ClientboundSetTimePacket packet, CallbackInfo ci) { + if (level.getDayTime() < 12000 && packet.getDayTime() >= 12000) { + Villager targetVillager = VillagerCracker.getVillager(); + if (targetVillager != null) { + ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); + } + } + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java index 47baba04b..272eb656d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java @@ -27,7 +27,7 @@ public MerchantScreenMixin(MerchantMenu menu, Inventory playerInventory, Compone @Inject(method = "render", at = @At("HEAD")) private void onRender(CallbackInfo ci) { if (VillagerCracker.targetOffer != null) { - if (menu.getOffers().stream().map(offer -> new VillagerCommand.Offer(offer.getBaseCostA(), offer.getItemCostB().map(ItemCost::itemStack).orElse(null), offer.getResult())).peek(offer -> System.out.println("offer: " + offer)).anyMatch(offer -> offer.toString().equals(VillagerCracker.targetOffer.toString()))) { + if (menu.getOffers().stream().map(offer -> new VillagerCommand.Offer(offer.getBaseCostA(), offer.getItemCostB().map(ItemCost::itemStack).orElse(null), offer.getResult())).anyMatch(offer -> offer.equals(VillagerCracker.targetOffer))) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.success", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.GREEN), 100); minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); } else { diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 913666080..c8c4eb5a5 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -246,21 +246,27 @@ "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls.", "commands.cvillager.clock.cleared": "Clock cleared", "commands.cvillager.clock.set": "Clock set", - "commands.cvillager.crack.failed": "Failed to crack villager seed (found %d seeds), re-cracking.", + "commands.cvillager.crack.failed": "Failed to crack villager seed (found %d seeds), re-cracking...", "commands.cvillager.crack.success": "Villager RNG cracked: %d", + "commands.cvillager.failure": "Got the incorrect trade with correction of %dms", "commands.cvillager.goalAdded": "Added goal successfully.", - "commands.cvillager.inSync": "Your villager's RNG is %d%% synced", + "commands.cvillager.help.day": "Help: Villager RNG manipulation is likely to break if it's not night-time", + "commands.cvillager.help.heldItem": "Help: Villager RNG manipulation could break if an item is held in your mainhand while the villager has a profession.", + "commands.cvillager.help.noClock": "Help: Villager RNG manipulation requires a 20 Hz clock.", + "commands.cvillager.help.tooSlow": "Help: Villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running much slower.", + "commands.cvillager.inSync": "Your villager's RNG is cracked", + "commands.cvillager.listGoal.success": "There is 1 villager goal:", "commands.cvillager.listGoals.noGoals": "There are no villager goals.", "commands.cvillager.listGoals.success": "There are %d villager goals:", "commands.cvillager.noCrackedVillagerPresent": "There was no cracked villager available to use", "commands.cvillager.noProfession": "The targeted villager has no profession.", - "commands.cvillager.notLevel1": "The targeted villager has level above 1.", "commands.cvillager.notAVillager": "Target was not a villager", - "commands.cvillager.outOfSync": "Your Villager's RNG was out of sync, re-cracking.", + "commands.cvillager.notLevel1": "The targeted villager has level above 1.", + "commands.cvillager.outOfSync.generic": "Your Villager's RNG was out of sync, re-cracking.", "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals.", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", + "commands.cvillager.resetCracker": "Successfully reset villager cracked RNG.", "commands.cvillager.success": "Got the correct trade with correction of %dms", - "commands.cvillager.failure": "Got the incorrect trade with correction of %dms", "commands.cvillager.target.cleared": "Target entity cleared", "commands.cvillager.target.set": "Target entity set", From a6f6ed546fe7039cfe695f740f2a1d063e3a31db Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 20 Jun 2024 22:31:12 -0400 Subject: [PATCH 20/78] shit --- .../clientcommands/features/VillagerRngSimulator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 6658f2df6..d0d00b52c 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -24,6 +24,7 @@ import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.trading.ItemCost; import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.levelgen.LegacyRandomSource; import org.jetbrains.annotations.Nullable; @@ -196,7 +197,7 @@ public VillagerCommand.Offer anyOffersMatch(VillagerTrades.ItemListing[] listing VillagerTrades.ItemListing listing = newListings.remove(rand.nextInt(newListings.size())); MerchantOffer offer = listing.getOffer(trader, rand); if (offer != null) { - VillagerCommand.Offer x = new VillagerCommand.Offer(offer.getBaseCostA(), offer.getCostB(), offer.getResult()); + VillagerCommand.Offer x = new VillagerCommand.Offer(offer.getBaseCostA(), offer.getItemCostB().map(ItemCost::itemStack).orElse(null), offer.getResult()); if (predicate.test(x)) { return x; } else { From deeb1e603ce4ee97fa0c52d3330b74b2f252b6e1 Mon Sep 17 00:00:00 2001 From: Gaider10 <72764892+Gaider10@users.noreply.github.com> Date: Fri, 21 Jun 2024 18:43:01 +0300 Subject: [PATCH 21/78] Use the ambient sound that detected the desync for recracking --- .../features/VillagerRngSimulator.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index d0d00b52c..e2658dc28 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -252,12 +252,20 @@ public String toString() { } public void onAmbientSoundPlayed(float pitch) { + boolean justReset = false; + if (totalAmbientSounds == 2 && !madeSound) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); + reset(); + justReset = true; + } + if (totalAmbientSounds == 0) { totalAmbientSounds++; firstPitch = pitch; ambientSoundTime = -80; - madeSound = true; - ClientCommandHelper.addOverlayMessage(((MutableComponent) getCrackedState().getMessage(false)).withStyle(ChatFormatting.RED), 100); + if (!justReset) { + ClientCommandHelper.addOverlayMessage(((MutableComponent) getCrackedState().getMessage(false)).withStyle(ChatFormatting.RED), 100); + } return; } @@ -266,7 +274,6 @@ public void onAmbientSoundPlayed(float pitch) { ticksBetweenSounds = ambientSoundTime - (-80); secondPitch = pitch; ambientSoundTime = -80; - madeSound = true; if (seedsFromTwoPitches != null) { int matchingSeeds = 0; @@ -311,12 +318,6 @@ public void onAmbientSoundPlayed(float pitch) { ambientSoundTime = -80; ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.crack.failed", seeds.length).withStyle(ChatFormatting.RED), 100); } - return; - } - - if (!madeSound) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); - reset(); } } From e4732b91e544ce2af4d5f6144ce0aa824a9f423c Mon Sep 17 00:00:00 2001 From: Gaider10 <72764892+Gaider10@users.noreply.github.com> Date: Fri, 21 Jun 2024 20:21:26 +0300 Subject: [PATCH 22/78] Fix nighttime check --- .../earthcomputer/clientcommands/features/VillagerCracker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 1ab24e127..d2999a456 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -74,7 +74,7 @@ public static void setTargetVillager(@Nullable Villager villager) { ClientLevel level = Minecraft.getInstance().level; - if (level.getDayTime() < 12000 || (level.dimensionType().fixedTime().isPresent() && level.dimensionType().fixedTime().getAsLong() < 12000)) { + if (level.getDayTime() % 24000 < 12000) { ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); } From 5c304e4b2d8ea0beac2cdb9a7f5fcb15395dcb27 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sat, 22 Jun 2024 14:35:41 -0400 Subject: [PATCH 23/78] - added custom out of sync messages - added out of sync message for range - added already brute forcing check --- .../command/VillagerCommand.java | 18 ++++++++---- .../arguments/PredicatedRangeArgument.java | 2 +- .../features/VillagerCracker.java | 10 ++----- .../features/VillagerRngSimulator.java | 22 +++++++++++---- .../mixin/rngevents/MerchantScreenMixin.java | 28 +++++++++++++------ .../clientcommands/util/DebugRandom.java | 4 +-- .../assets/clientcommands/lang/en_us.json | 12 ++++++-- src/main/resources/clientcommands.aw | 1 + 8 files changed, 64 insertions(+), 33 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 61a0225aa..11f6d0df0 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -7,6 +7,8 @@ import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.datafixers.util.Pair; import net.earthcomputer.clientcommands.Configs; +import net.earthcomputer.clientcommands.command.arguments.ItemAndEnchantmentsPredicateArgument; +import net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument; import net.earthcomputer.clientcommands.command.arguments.WithStringArgument; import net.earthcomputer.clientcommands.features.FishingCracker; import net.earthcomputer.clientcommands.features.VillagerCracker; @@ -37,6 +39,7 @@ import static dev.xpple.clientarguments.arguments.CBlockPosArgument.*; import static dev.xpple.clientarguments.arguments.CEntityArgument.*; import static dev.xpple.clientarguments.arguments.CItemPredicateArgument.*; +import static net.earthcomputer.clientcommands.command.arguments.ItemAndEnchantmentsPredicateArgument.*; import static net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument.*; import static net.earthcomputer.clientcommands.command.arguments.WithStringArgument.*; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; @@ -47,6 +50,7 @@ public class VillagerCommand { private static final SimpleCommandExceptionType NO_PROFESSION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noProfession")); private static final SimpleCommandExceptionType NOT_LEVEL_1 = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notLevel1")); private static final SimpleCommandExceptionType NO_GOALS = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.listGoals.noGoals")); + private static final SimpleCommandExceptionType ALREADY_BRUTE_FORCING = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.alreadyBruteForcing")); private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); public static final List goals = new ArrayList<>(); @@ -58,14 +62,13 @@ public static void register(CommandDispatcher dispatc .then(argument("result-item", withString(itemPredicate(context))) .then(argument("result-item-quantity", withString(intRange(1, 64))) .executes(ctx -> addGoal(getWithString(ctx, "first-item", CItemStackPredicateArgument.class), getWithString(ctx, "first-item-quantity", MinMaxBounds.Ints.class), null, null, getWithString(ctx, "result-item", CItemStackPredicateArgument.class), getWithString(ctx, "result-item-quantity", MinMaxBounds.Ints.class)))))))) - .then(literal("add-three-item-goal") + .then(literal("add-enchanted-goal") .then(argument("first-item", withString(itemPredicate(context))) .then(argument("first-item-quantity", withString(intRange(1, 64))) .then(argument("second-item", withString(itemPredicate(context))) .then(argument("second-item-quantity", withString(intRange(1, 64))) - .then(argument("result-item", withString(itemPredicate(context))) - .then(argument("result-item-quantity", withString(intRange(1, 64))) - .executes(ctx -> addGoal(getWithString(ctx, "first-item", CItemStackPredicateArgument.class), getWithString(ctx, "first-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "second-item", CItemStackPredicateArgument.class), getWithString(ctx, "second-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "result-item", CItemStackPredicateArgument.class), getWithString(ctx, "result-item-quantity", MinMaxBounds.Ints.class)))))))))) + .then(argument("result-item", withString(itemAndEnchantmentsPredicate(context))) + .executes(ctx -> addGoal(getWithString(ctx, "first-item", CItemStackPredicateArgument.class), getWithString(ctx, "first-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "second-item", CItemStackPredicateArgument.class), getWithString(ctx, "second-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "result-item", ItemAndEnchantmentsPredicate.class), new WithStringArgument.Result<>("1..1", MinMaxBounds.Ints.between(1, 1)))))))))) .then(literal("list-goals") .executes(ctx -> listGoals(ctx.getSource()))) .then(literal("remove-goal") @@ -88,7 +91,7 @@ public static void register(CommandDispatcher dispatc .executes(ctx -> bruteForce(true))))); } - private static int addGoal(WithStringArgument.Result firstPredicate, WithStringArgument.Result firstItemQuantityRange, @Nullable WithStringArgument.Result secondPredicate, @Nullable WithStringArgument.Result secondItemQuantityRange, WithStringArgument.Result resultPredicate, WithStringArgument.Result resultItemQuantityRange) { + private static int addGoal(WithStringArgument.Result firstPredicate, WithStringArgument.Result firstItemQuantityRange, @Nullable WithStringArgument.Result secondPredicate, @Nullable WithStringArgument.Result secondItemQuantityRange, WithStringArgument.Result> resultPredicate, WithStringArgument.Result resultItemQuantityRange) { goals.add(new Goal( String.format("%s %s", firstItemQuantityRange.string(), firstPredicate.string()), item -> firstPredicate.value().test(item) && firstItemQuantityRange.value().matches(item.getCount()), @@ -176,11 +179,16 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { if (!(targetVillager instanceof IVillager iVillager) || !iVillager.clientcommands_getVillagerRngSimulator().getCrackedState().isCracked()) { throw NO_CRACKED_VILLAGER_PRESENT.create(); } + VillagerProfession profession = targetVillager.getVillagerData().getProfession(); if (profession == VillagerProfession.NONE) { throw NO_PROFESSION.create(); } + if (iVillager.clientcommands_getVillagerRngSimulator().isCracking()) { + throw ALREADY_BRUTE_FORCING.create(); + } + int currentLevel = targetVillager.getVillagerData().getLevel(); if (!levelUp && currentLevel != 1) { throw NOT_LEVEL_1.create(); diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java index 81cb1d3d5..2fdccda0f 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java @@ -23,7 +23,7 @@ static Ints intRange(@Nullable Integer min, @Nullable Integer max) { static Floats floatRange(@Nullable Double min, @Nullable Double max) { return new Floats(min, max); } - + class Ints implements PredicatedRangeArgument { @Nullable private final Integer min; diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index d2999a456..487f25f28 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -9,10 +9,8 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; -import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.entity.npc.VillagerProfession; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; @@ -88,7 +86,7 @@ public static void setClockPos(@Nullable GlobalPos pos) { public static void onSoundEventPlayed(ClientboundSoundPacket packet) { Villager targetVillager = getVillager(); - if (targetVillager == null) { + if (targetVillager == null || getClockPos() == null) { return; } @@ -118,15 +116,11 @@ public static void onServerTick() { return; } - if (lastServerTick != null && now - lastServerTick > 50L && !receivedClockRateWarning) { + if (lastServerTick != null && now - lastServerTick > 80L && !receivedClockRateWarning) { ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.tooSlow")); receivedClockRateWarning = true; } - if (targetVillager.getVillagerData().getProfession() != VillagerProfession.NONE && targetVillager.getVillagerData().getProfession() != VillagerProfession.NITWIT && !Minecraft.getInstance().player.getItemInHand(InteractionHand.MAIN_HAND).isEmpty()) { - ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.heldItem")); - } - ((IVillager) targetVillager).clientcommands_onServerTick(); lastServerTick = now; diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index e2658dc28..a1d067cd9 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -114,14 +114,20 @@ public VillagerRngSimulator(@Nullable JRand random, int ambientSoundTime) { public VillagerRngSimulator copy() { VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : random.copy(), ambientSoundTime); + that.random = this.random; + that.prevRandomSeed = this.prevRandomSeed; + that.ambientSoundTime = this.ambientSoundTime; + that.prevAmbientSoundTime = this.prevAmbientSoundTime; that.madeSound = this.madeSound; that.totalAmbientSounds = this.totalAmbientSounds; that.callsAtStartOfBruteForce = this.callsAtStartOfBruteForce; that.callsInBruteForce = this.callsInBruteForce; that.totalCalls = this.totalCalls; + that.prevTotalCalls = this.prevTotalCalls; that.firstPitch = this.firstPitch; that.ticksBetweenSounds = this.ticksBetweenSounds; that.secondPitch = this.secondPitch; + that.seedsFromTwoPitches = this.seedsFromTwoPitches; that.activeGoalResult = this.activeGoalResult; return that; } @@ -230,6 +236,10 @@ public void setRandom(@Nullable JRand random) { this.random = random; } + public boolean isCracking() { + return callsInBruteForce > 0; + } + public void reset() { random = null; prevRandomSeed = 0; @@ -254,7 +264,7 @@ public String toString() { public void onAmbientSoundPlayed(float pitch) { boolean justReset = false; if (totalAmbientSounds == 2 && !madeSound) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.ambient").withStyle(ChatFormatting.RED), 100); reset(); justReset = true; } @@ -332,7 +342,7 @@ public void onNoSoundPlayed(float pitch, boolean fromGuiInteract) { } float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; if (pitch != simulatedPitch) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.no").withStyle(ChatFormatting.RED), 100); reset(); } } @@ -347,7 +357,7 @@ public void onYesSoundPlayed(float pitch) { ambientSoundTime = -80; float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; if (pitch != simulatedPitch) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.yes").withStyle(ChatFormatting.RED), 100); reset(); } } @@ -363,7 +373,7 @@ public void onSplashSoundPlayed(float pitch) { totalCalls += 2; float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.4f + 1.0f; if (pitch != simulatedPitch) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.splash").withStyle(ChatFormatting.RED), 100); reset(); return; } @@ -386,7 +396,7 @@ public void onXpOrbSpawned(int value) { boolean leveledUp = value > 3 + 3; if (leveledUp) simulatedValue += 5; if (value != simulatedValue) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.generic").withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.xpOrb").withStyle(ChatFormatting.RED), 100); reset(); } } @@ -493,7 +503,7 @@ public boolean isCracked() { public Component getMessage(boolean addColor) { return switch (this) { - case UNCRACKED -> Component.translatable("commands.cvillager.noCrackedVillagerPresent").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); + case UNCRACKED -> Component.translatable("commands.cvillager.halfCracked").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); case CRACKED -> Component.translatable("commands.cvillager.inSync").withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); }; } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java index 272eb656d..589c28624 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java @@ -4,12 +4,15 @@ import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerCracker; +import net.earthcomputer.clientcommands.interfaces.IVillager; import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.MerchantScreen; import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; +import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.MerchantMenu; import net.minecraft.world.item.trading.ItemCost; @@ -26,15 +29,24 @@ public MerchantScreenMixin(MerchantMenu menu, Inventory playerInventory, Compone @Inject(method = "render", at = @At("HEAD")) private void onRender(CallbackInfo ci) { - if (VillagerCracker.targetOffer != null) { - if (menu.getOffers().stream().map(offer -> new VillagerCommand.Offer(offer.getBaseCostA(), offer.getItemCostB().map(ItemCost::itemStack).orElse(null), offer.getResult())).anyMatch(offer -> offer.equals(VillagerCracker.targetOffer))) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.success", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.GREEN), 100); - minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); - } else { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.RED), 100); - minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); + Villager targetVillager = VillagerCracker.getVillager(); + if (targetVillager != null && ((IVillager) targetVillager).clientcommands_getVillagerRngSimulator().getCrackedState().isCracked()) { + if (Minecraft.getInstance().player.distanceToSqr(targetVillager) > 2.0) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.distance").withStyle(ChatFormatting.RED), 100); + ((IVillager) targetVillager).clientcommands_getVillagerRngSimulator().reset(); + return; + } + + if (VillagerCracker.targetOffer != null) { + if (menu.getOffers().stream().map(offer -> new VillagerCommand.Offer(offer.getBaseCostA(), offer.getItemCostB().map(ItemCost::itemStack).orElse(null), offer.getResult())).anyMatch(offer -> offer.equals(VillagerCracker.targetOffer))) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.success", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.GREEN), 100); + minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); + } else { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.RED), 100); + minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); + } + VillagerCracker.targetOffer = null; } - VillagerCracker.targetOffer = null; } } } diff --git a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java index 41dca4c96..2fc0ef63b 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java @@ -95,7 +95,7 @@ public void tick() { private void handleStackTrace(int stackTrace) { this.stackTracesThisTick.add(stackTrace); try { - NbtIo.writeUnnamedTagWithFallback(firstTick ? new CompoundTag() : entity.saveWithoutId(new CompoundTag()), nbtStream); + NbtIo.writeUnnamedTagWithFallback(/*firstTick ? */new CompoundTag()/* : entity.saveWithoutId(new CompoundTag())*/, nbtStream); } catch (IOException e) { throw new AssertionError(e); } @@ -269,7 +269,7 @@ class DebugRandomSourcePanel extends JPanel { } }); bottomPanel.add(dumpStackTraceButton); - JButton dumpStackTracesWithQuantitiesButton = new JButton("Dump stack traces with quantities"); + JButton dumpStackTracesWithQuantitiesButton = new JButton("Dump unique stack traces with quantities"); dumpStackTracesWithQuantitiesButton.addActionListener(e -> { if (selectedTick == null) { return; diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index c8c4eb5a5..37b103ee5 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -242,6 +242,7 @@ "commands.cvar.list.empty": "No available variables", "commands.cvar.list": "Available variables: %s", + "commands.cvillager.alreadyBruteForcing": "Cannot brute-force villager RNG since your target villager is already brute forcing.", "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %d calls.", "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls.", "commands.cvillager.clock.cleared": "Clock cleared", @@ -250,8 +251,8 @@ "commands.cvillager.crack.success": "Villager RNG cracked: %d", "commands.cvillager.failure": "Got the incorrect trade with correction of %dms", "commands.cvillager.goalAdded": "Added goal successfully.", + "commands.cvillager.halfCracked": "Your villager's RNG is partially cracked (~83m seeds remain)", "commands.cvillager.help.day": "Help: Villager RNG manipulation is likely to break if it's not night-time", - "commands.cvillager.help.heldItem": "Help: Villager RNG manipulation could break if an item is held in your mainhand while the villager has a profession.", "commands.cvillager.help.noClock": "Help: Villager RNG manipulation requires a 20 Hz clock.", "commands.cvillager.help.tooSlow": "Help: Villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running much slower.", "commands.cvillager.inSync": "Your villager's RNG is cracked", @@ -262,10 +263,15 @@ "commands.cvillager.noProfession": "The targeted villager has no profession.", "commands.cvillager.notAVillager": "Target was not a villager", "commands.cvillager.notLevel1": "The targeted villager has level above 1.", - "commands.cvillager.outOfSync.generic": "Your Villager's RNG was out of sync, re-cracking.", + "commands.cvillager.outOfSync.ambient": "Your Villager's hrmm sound was incorrectly timed and or incorrectly pitched, re-cracking.", + "commands.cvillager.outOfSync.distance": "Your Villager was too far away from you, re-cracking.", + "commands.cvillager.outOfSync.no": "Your Villager's no sound was incorrectly pitched, re-cracking.", + "commands.cvillager.outOfSync.splash": "Your Villager's splash sound was incorrectly pitched, re-cracking.", + "commands.cvillager.outOfSync.xpOrb": "Your Villager's xp orb was incorrectly sized, re-cracking.", + "commands.cvillager.outOfSync.yes": "Your Villager's yes sound was incorrectly pitched, re-cracking.", "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals.", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", - "commands.cvillager.resetCracker": "Successfully reset villager cracked RNG.", + "commands.cvillager.resetCracker": "Successfully reset cracked villager RNG.", "commands.cvillager.success": "Got the correct trade with correction of %dms", "commands.cvillager.target.cleared": "Target entity cleared", "commands.cvillager.target.set": "Target entity set", diff --git a/src/main/resources/clientcommands.aw b/src/main/resources/clientcommands.aw index 6fe0f89aa..52fa53310 100644 --- a/src/main/resources/clientcommands.aw +++ b/src/main/resources/clientcommands.aw @@ -50,3 +50,4 @@ accessible class net/minecraft/client/renderer/RenderStateShard$LineStateShard accessible field net/minecraft/world/entity/LivingEntity lastHurt F accessible field net/minecraft/world/entity/decoration/ArmorStand invisible Z accessible field net/minecraft/world/level/levelgen/LegacyRandomSource seed Ljava/util/concurrent/atomic/AtomicLong; +accessible field net/minecraft/world/inventory/MerchantMenu trader Lnet/minecraft/world/item/trading/Merchant; From 38b8d69c073a7a238e09fe6751b1240a5ab55265 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sun, 23 Jun 2024 11:56:36 -0400 Subject: [PATCH 24/78] - added nicer display to goals using ItemParser - fixed cfish not working on books in 1.21 --- .../command/VillagerCommand.java | 61 +++++++++++++------ .../ItemAndEnchantmentsPredicateArgument.java | 3 +- .../features/VillagerRngSimulator.java | 28 +++------ .../commands/villager/VillagerMixin.java | 2 +- .../mixin/rngevents/MerchantScreenMixin.java | 2 +- .../clientcommands/util/DebugRandom.java | 2 +- .../assets/clientcommands/lang/en_us.json | 2 +- 7 files changed, 57 insertions(+), 43 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 11f6d0df0..c70df1624 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -2,13 +2,12 @@ import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; +import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.datafixers.util.Pair; import net.earthcomputer.clientcommands.Configs; -import net.earthcomputer.clientcommands.command.arguments.ItemAndEnchantmentsPredicateArgument; -import net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument; import net.earthcomputer.clientcommands.command.arguments.WithStringArgument; import net.earthcomputer.clientcommands.features.FishingCracker; import net.earthcomputer.clientcommands.features.VillagerCracker; @@ -18,9 +17,12 @@ import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.client.Minecraft; import net.minecraft.commands.CommandBuildContext; +import net.minecraft.commands.arguments.item.ItemParser; import net.minecraft.core.BlockPos; import net.minecraft.core.GlobalPos; +import net.minecraft.core.HolderLookup; import net.minecraft.network.chat.Component; +import net.minecraft.tags.EnchantmentTags; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.VillagerProfession; @@ -67,8 +69,8 @@ public static void register(CommandDispatcher dispatc .then(argument("first-item-quantity", withString(intRange(1, 64))) .then(argument("second-item", withString(itemPredicate(context))) .then(argument("second-item-quantity", withString(intRange(1, 64))) - .then(argument("result-item", withString(itemAndEnchantmentsPredicate(context))) - .executes(ctx -> addGoal(getWithString(ctx, "first-item", CItemStackPredicateArgument.class), getWithString(ctx, "first-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "second-item", CItemStackPredicateArgument.class), getWithString(ctx, "second-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "result-item", ItemAndEnchantmentsPredicate.class), new WithStringArgument.Result<>("1..1", MinMaxBounds.Ints.between(1, 1)))))))))) + .then(argument("result-item", withString(itemAndEnchantmentsPredicate(context).withEnchantmentPredicate((item, enchantment) -> enchantment.is(EnchantmentTags.TRADEABLE)))) + .executes(ctx -> addGoal(getWithString(ctx, "first-item", CItemStackPredicateArgument.class), getWithString(ctx, "first-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "second-item", CItemStackPredicateArgument.class), getWithString(ctx, "second-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "result-item", ItemAndEnchantmentsPredicate.class), new WithStringArgument.Result<>("1", MinMaxBounds.Ints.between(1, 1)))))))))) .then(literal("list-goals") .executes(ctx -> listGoals(ctx.getSource()))) .then(literal("remove-goal") @@ -91,15 +93,40 @@ public static void register(CommandDispatcher dispatc .executes(ctx -> bruteForce(true))))); } - private static int addGoal(WithStringArgument.Result firstPredicate, WithStringArgument.Result firstItemQuantityRange, @Nullable WithStringArgument.Result secondPredicate, @Nullable WithStringArgument.Result secondItemQuantityRange, WithStringArgument.Result> resultPredicate, WithStringArgument.Result resultItemQuantityRange) { + private static int addGoal(Result firstPredicate, Result firstItemQuantityRange, @Nullable Result secondPredicate, @Nullable Result secondItemQuantityRange, Result> resultPredicate, Result resultItemQuantityRange) { + HolderLookup.Provider registries = Minecraft.getInstance().level.registryAccess(); + String firstItemString; + try { + ItemParser.ItemResult firstItemResult = new ItemParser(registries).parse(new StringReader(firstPredicate.string())); + firstItemString = displayText(new ItemStack(firstItemResult.item(), 1, firstItemResult.components()), true); + } catch (CommandSyntaxException e) { + firstItemString = firstPredicate.string(); + } + String secondItemString = null; + if (secondPredicate != null) { + try { + ItemParser.ItemResult secondItemResult = new ItemParser(registries).parse(new StringReader(secondPredicate.string())); + secondItemString = displayText(new ItemStack(secondItemResult.item(), 1, secondItemResult.components()), true); + } catch (CommandSyntaxException e) { + secondItemString = secondPredicate.string(); + } + } + String resultItemString; + try { + ItemParser.ItemResult resultItemResult = new ItemParser(registries).parse(new StringReader(resultPredicate.string())); + resultItemString = displayText(new ItemStack(resultItemResult.item(), 1, resultItemResult.components()), true); + } catch (CommandSyntaxException e) { + resultItemString = resultPredicate.string(); + } + goals.add(new Goal( - String.format("%s %s", firstItemQuantityRange.string(), firstPredicate.string()), + String.format("%sx %s", firstItemQuantityRange.string(), firstItemString), item -> firstPredicate.value().test(item) && firstItemQuantityRange.value().matches(item.getCount()), - secondPredicate == null ? null : String.format("%s %s", secondItemQuantityRange.string(), secondPredicate.string()), - secondPredicate == null ? null : item -> secondPredicate.value().test(item) && secondItemQuantityRange.value().matches(item.getCount()), + secondPredicate == null || secondItemQuantityRange == null ? null : String.format("%sx %s", secondItemQuantityRange.string(), secondItemString), + secondPredicate == null || secondItemQuantityRange == null ? null : item -> secondPredicate.value().test(item) && secondItemQuantityRange.value().matches(item.getCount()), - String.format("%s %s", resultItemQuantityRange.string(), resultPredicate.string()), + String.format("%sx %s", resultItemQuantityRange.string(), resultItemString), item -> resultPredicate.value().test(item) && resultItemQuantityRange.value().matches(item.getCount()))); ClientCommandHelper.sendFeedback("commands.cvillager.goalAdded"); @@ -110,7 +137,7 @@ private static int listGoals(FabricClientCommandSource source) { if (goals.isEmpty()) { source.sendFeedback(Component.translatable("commands.cvillager.listGoals.noGoals").withStyle(style -> style.withColor(ChatFormatting.RED))); } else { - if (FishingCracker.goals.size() == 1) { + if (goals.size() == 1) { source.sendFeedback(Component.translatable("commands.cvillager.listGoal.success")); } else { source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", FishingCracker.goals.size() + 1)); @@ -206,11 +233,11 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { } else { String price; if (offer.second() == null) { - price = VillagerCommand.displayText(offer.first()); + price = displayText(offer.first(), false); } else { - price = VillagerCommand.displayText(offer.first()) + " + " + VillagerCommand.displayText(offer.second()); + price = displayText(offer.first(), false) + " + " + displayText(offer.second(), false); } - ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", VillagerCommand.displayText(offer.result()), price, calls).withStyle(ChatFormatting.GREEN)); + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", displayText(offer.result(), false), price, calls).withStyle(ChatFormatting.GREEN)); VillagerCracker.targetOffer = offer; iVillager.clientcommands_getVillagerRngSimulator().setCallsUntilToggleGui(calls, offer.result()); } @@ -249,16 +276,16 @@ public boolean equals(Object obj) { @Override public String toString() { if (second == null) { - return String.format("%s = %s", displayText(first), displayText(result)); + return String.format("%s = %s", displayText(first, false), displayText(result, false)); } else { - return String.format("%s + %s = %s", displayText(first), displayText(second), displayText(result)); + return String.format("%s + %s = %s", displayText(first, false), displayText(second, false), displayText(result, false)); } } } - public static String displayText(ItemStack stack) { + public static String displayText(ItemStack stack, boolean ignoreCount) { String quantityPrefix; - if (stack.getCount() == 1) { + if (stack.getCount() == 1 || ignoreCount) { quantityPrefix = ""; } else if (stack.getCount() < 64) { quantityPrefix = stack.getCount() + " "; diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java index 32812c0a4..6e2bd6e7c 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java @@ -38,6 +38,7 @@ import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Predicate; +import java.util.stream.Stream; public class ItemAndEnchantmentsPredicateArgument implements ArgumentType { @@ -158,7 +159,7 @@ public boolean test(ItemStack stack) { if (item != stack.getItem() && (item != Items.BOOK || stack.getItem() != Items.ENCHANTED_BOOK)) { return false; } - List enchantments = stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY).entrySet().stream() + List enchantments = Stream.concat(stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY).entrySet().stream(), stack.getOrDefault(DataComponents.STORED_ENCHANTMENTS, ItemEnchantments.EMPTY).entrySet().stream()) .map(entry -> new EnchantmentInstance(entry.getKey(), entry.getIntValue())) .toList(); return predicate.test(enchantments); diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index a1d067cd9..70f7b0836 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -44,15 +44,15 @@ public class VillagerRngSimulator { @Nullable private JRand random; - private long prevRandomSeed; - private int ambientSoundTime; - private int prevAmbientSoundTime; + private long prevRandomSeed = 0; + private int ambientSoundTime = -80; + private int prevAmbientSoundTime = -80; private boolean madeSound = false; private int totalAmbientSounds = 0; private int callsAtStartOfBruteForce = 0; private int callsInBruteForce = 0; private int totalCalls = 0; - private int prevTotalCalls; + private int prevTotalCalls = 0; private float firstPitch = Float.NaN; private int ticksBetweenSounds = 0; private float secondPitch = Float.NaN; @@ -107,28 +107,18 @@ public class VillagerRngSimulator { } } - public VillagerRngSimulator(@Nullable JRand random, int ambientSoundTime) { + public VillagerRngSimulator(@Nullable JRand random) { this.random = random; - this.ambientSoundTime = ambientSoundTime; } public VillagerRngSimulator copy() { - VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : random.copy(), ambientSoundTime); - that.random = this.random; - that.prevRandomSeed = this.prevRandomSeed; + VillagerRngSimulator that = new VillagerRngSimulator(random == null ? null : random.copy()); that.ambientSoundTime = this.ambientSoundTime; that.prevAmbientSoundTime = this.prevAmbientSoundTime; that.madeSound = this.madeSound; that.totalAmbientSounds = this.totalAmbientSounds; - that.callsAtStartOfBruteForce = this.callsAtStartOfBruteForce; - that.callsInBruteForce = this.callsInBruteForce; that.totalCalls = this.totalCalls; that.prevTotalCalls = this.prevTotalCalls; - that.firstPitch = this.firstPitch; - that.ticksBetweenSounds = this.ticksBetweenSounds; - that.secondPitch = this.secondPitch; - that.seedsFromTwoPitches = this.seedsFromTwoPitches; - that.activeGoalResult = this.activeGoalResult; return that; } @@ -232,10 +222,6 @@ public CrackedState getCrackedState() { return CrackedState.CRACKED; } - public void setRandom(@Nullable JRand random) { - this.random = random; - } - public boolean isCracking() { return callsInBruteForce > 0; } @@ -503,7 +489,7 @@ public boolean isCracked() { public Component getMessage(boolean addColor) { return switch (this) { - case UNCRACKED -> Component.translatable("commands.cvillager.halfCracked").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); + case UNCRACKED -> Component.translatable("commands.cvillager.partiallyCracked").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); case CRACKED -> Component.translatable("commands.cvillager.inSync").withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); }; } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index daa400df9..1ec26cd3d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -21,7 +21,7 @@ public VillagerMixin(EntityType entityType, Level le } @Unique - VillagerRngSimulator rng = new VillagerRngSimulator(null, -80); + VillagerRngSimulator rng = new VillagerRngSimulator(null); @Override public void clientcommands_onAmbientSoundPlayed(float pitch) { diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java index 589c28624..8dd3adde3 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java @@ -30,7 +30,7 @@ public MerchantScreenMixin(MerchantMenu menu, Inventory playerInventory, Compone @Inject(method = "render", at = @At("HEAD")) private void onRender(CallbackInfo ci) { Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager != null && ((IVillager) targetVillager).clientcommands_getVillagerRngSimulator().getCrackedState().isCracked()) { + if (targetVillager != null) { if (Minecraft.getInstance().player.distanceToSqr(targetVillager) > 2.0) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.distance").withStyle(ChatFormatting.RED), 100); ((IVillager) targetVillager).clientcommands_getVillagerRngSimulator().reset(); diff --git a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java index 2fc0ef63b..0cfcf4b32 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java @@ -95,7 +95,7 @@ public void tick() { private void handleStackTrace(int stackTrace) { this.stackTracesThisTick.add(stackTrace); try { - NbtIo.writeUnnamedTagWithFallback(/*firstTick ? */new CompoundTag()/* : entity.saveWithoutId(new CompoundTag())*/, nbtStream); + NbtIo.writeUnnamedTagWithFallback(firstTick ? new CompoundTag() : entity.saveWithoutId(new CompoundTag()), nbtStream); } catch (IOException e) { throw new AssertionError(e); } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 37b103ee5..660480791 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -251,7 +251,6 @@ "commands.cvillager.crack.success": "Villager RNG cracked: %d", "commands.cvillager.failure": "Got the incorrect trade with correction of %dms", "commands.cvillager.goalAdded": "Added goal successfully.", - "commands.cvillager.halfCracked": "Your villager's RNG is partially cracked (~83m seeds remain)", "commands.cvillager.help.day": "Help: Villager RNG manipulation is likely to break if it's not night-time", "commands.cvillager.help.noClock": "Help: Villager RNG manipulation requires a 20 Hz clock.", "commands.cvillager.help.tooSlow": "Help: Villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running much slower.", @@ -269,6 +268,7 @@ "commands.cvillager.outOfSync.splash": "Your Villager's splash sound was incorrectly pitched, re-cracking.", "commands.cvillager.outOfSync.xpOrb": "Your Villager's xp orb was incorrectly sized, re-cracking.", "commands.cvillager.outOfSync.yes": "Your Villager's yes sound was incorrectly pitched, re-cracking.", + "commands.cvillager.partiallyCracked": "Your villager's RNG is partially cracked (~83m seeds remain)", "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals.", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", "commands.cvillager.resetCracker": "Successfully reset cracked villager RNG.", From 3813d7ba5a47314f46ef8d4e71064e25544ec861 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sun, 23 Jun 2024 18:02:54 -0400 Subject: [PATCH 25/78] added toString --- .../command/VillagerCommand.java | 14 +++-- .../ItemAndEnchantmentsPredicateArgument.java | 59 ++++++++++++++++++- 2 files changed, 65 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index c70df1624..d7b487f70 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -112,11 +112,15 @@ private static int addGoal(Result firstPredicate, R } } String resultItemString; - try { - ItemParser.ItemResult resultItemResult = new ItemParser(registries).parse(new StringReader(resultPredicate.string())); - resultItemString = displayText(new ItemStack(resultItemResult.item(), 1, resultItemResult.components()), true); - } catch (CommandSyntaxException e) { - resultItemString = resultPredicate.string(); + if (resultPredicate.value() instanceof ItemAndEnchantmentsPredicate predicate) { + resultItemString = predicate.toString(); + } else { + try { + ItemParser.ItemResult resultItemResult = new ItemParser(registries).parse(new StringReader(resultPredicate.string())); + resultItemString = displayText(new ItemStack(resultItemResult.item(), 1, resultItemResult.components()), true); + } catch (CommandSyntaxException e) { + resultItemString = resultPredicate.string(); + } } goals.add(new Goal( diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java index 6e2bd6e7c..ca874e349 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java @@ -38,6 +38,7 @@ import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Predicate; +import java.util.stream.Collectors; import java.util.stream.Stream; public class ItemAndEnchantmentsPredicateArgument implements ArgumentType { @@ -127,7 +128,7 @@ public ItemAndEnchantmentsPredicate parse(StringReader reader) throws CommandSyn return true; }; - return new ItemAndEnchantmentsPredicate(parser.item, predicate, parser.with.size()); + return new ItemAndEnchantmentsPredicate(parser.item, predicate, parser.with, parser.without, parser.exact, parser.ordered); } @Override @@ -153,7 +154,7 @@ public Collection getExamples() { return EXAMPLES; } - public record ItemAndEnchantmentsPredicate(Item item, Predicate> predicate, int numEnchantments) implements Predicate { + public record ItemAndEnchantmentsPredicate(Item item, Predicate> predicate, List with, List without, boolean exact, boolean ordered) implements Predicate { @Override public boolean test(ItemStack stack) { if (item != stack.getItem() && (item != Items.BOOK || stack.getItem() != Items.ENCHANTED_BOOK)) { @@ -164,6 +165,30 @@ public boolean test(ItemStack stack) { .toList(); return predicate.test(enchantments); } + + @Override + public String toString() { + String itemName = item.getName(new ItemStack(item)).getString(); + + StringBuilder flagsBuilder = new StringBuilder(); + if (exact) { + flagsBuilder.append("Exactly"); + } + if (ordered) { + flagsBuilder.append("Ordered"); + } + String flags = flagsBuilder.isEmpty() ? "" : " [" + flagsBuilder + ')'; + + String enchantments = Stream.concat( + with.stream().filter(enchantment -> enchantment.enchantment().unwrapKey().isPresent()).map(EnchantmentInstancePredicate::toString), + without.stream().filter(enchantment -> enchantment.enchantment().unwrapKey().isPresent()).map(enchantment -> "!" + enchantment) + ).collect(Collectors.joining(", ")); + if (!enchantments.isEmpty()) { + enchantments = '(' + enchantments + ')'; + } + + return String.format("%s%s %s", itemName, flags, enchantments); + } } private class Parser { @@ -456,10 +481,38 @@ private void suggestOption() { } } - private record EnchantmentInstancePredicate(Holder enchantment, MinMaxBounds.Ints level) implements Predicate { + public record EnchantmentInstancePredicate(Holder enchantment, MinMaxBounds.Ints level) implements Predicate { @Override public boolean test(EnchantmentInstance enchInstance) { return enchantment.equals(enchInstance.enchantment) && level.matches(enchInstance.level); } + + @Override + public String toString() { + String name = Component.translatable(enchantment.unwrapKey().get().location().toLanguageKey("enchantment")).getString(); + + int maxLevel = enchantment.value().getMaxLevel(); + String levelString; + if (maxLevel == 1) { + levelString = ""; + } else if ((level.min().isEmpty() || level.min().get() == 1) && (level.max().isPresent() && level.max().get() == maxLevel)) { + levelString = " *"; + } else if (level.min().equals(level.max()) && level.min().isPresent()) { + levelString = " " + level.min().get(); + } else { + levelString = " "; + if (level.min().isPresent()) { + levelString = levelString + level.min().get(); + } + if (!levelString.equals(" ") || level.max().isPresent()) { + levelString = levelString + ".."; + } + if (level.max().isPresent()) { + levelString = levelString + level.max().get(); + } + } + + return name + levelString; + } } } From 7c2fe747a779eb5cc7069933341fd9db68334678 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sat, 29 Jun 2024 17:06:00 -0400 Subject: [PATCH 26/78] ?? --- .../clientcommands/command/VillagerCommand.java | 2 +- .../clientcommands/features/FishingCracker.java | 2 +- .../clientcommands/features/VillagerRngSimulator.java | 7 +------ 3 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index d7b487f70..d56e4630d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -243,7 +243,7 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { } ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", displayText(offer.result(), false), price, calls).withStyle(ChatFormatting.GREEN)); VillagerCracker.targetOffer = offer; - iVillager.clientcommands_getVillagerRngSimulator().setCallsUntilToggleGui(calls, offer.result()); + iVillager.clientcommands_getVillagerRngSimulator().setCallsUntilToggleGui(calls); } return Command.SINGLE_SUCCESS; diff --git a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java index fd7865a32..266faeca3 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java @@ -425,7 +425,7 @@ record ErrorEntry(int tick, boolean isBox) {} LootTable fishingLootTable = MCLootTables.FISHING.get().apply(SeedfindingUtil.getMCVersion()); for (var goal : goals) { if (goal.value() instanceof ClientItemPredicateArgument.EnchantedItemPredicate predicate) { - if (predicate.isEnchantedBook() && predicate.predicate.numEnchantments() >= 2) { + if (predicate.isEnchantedBook() && predicate.predicate.with().size() >= 2) { if (!hasWarnedMultipleEnchants) { ClientCommandHelper.sendHelp(Component.translatable("commands.cfish.help.tooManyEnchants")); hasWarnedMultipleEnchants = true; diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 70f7b0836..cea183765 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -23,7 +23,6 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.VillagerTrades; -import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.trading.ItemCost; import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.levelgen.LegacyRandomSource; @@ -58,8 +57,6 @@ public class VillagerRngSimulator { private float secondPitch = Float.NaN; @Nullable private long[] seedsFromTwoPitches = null; - @Nullable - private ItemStack activeGoalResult = null; static { try { @@ -204,10 +201,9 @@ public VillagerCommand.Offer anyOffersMatch(VillagerTrades.ItemListing[] listing return null; } - public void setCallsUntilToggleGui(int calls, ItemStack resultStack) { + public void setCallsUntilToggleGui(int calls) { callsAtStartOfBruteForce = totalCalls; callsInBruteForce = calls; - activeGoalResult = resultStack; } public int getTotalCalls() { @@ -239,7 +235,6 @@ public void reset() { ticksBetweenSounds = 0; secondPitch = Float.NaN; seedsFromTwoPitches = null; - activeGoalResult = null; } @Override From 951991163acb910779ae89f9156ec4945dd5bac8 Mon Sep 17 00:00:00 2001 From: RTTV Date: Mon, 1 Jul 2024 11:17:48 -0400 Subject: [PATCH 27/78] changes in response to review --- .../command/VillagerCommand.java | 184 ++++++++++-------- .../ItemAndEnchantmentsPredicateArgument.java | 32 +-- .../arguments/PredicatedRangeArgument.java | 82 -------- .../assets/clientcommands/lang/en_us.json | 35 ++-- 4 files changed, 124 insertions(+), 209 deletions(-) delete mode 100644 src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index d56e4630d..732db250a 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -7,8 +7,8 @@ import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.datafixers.util.Pair; +import dev.xpple.clientarguments.arguments.CRangeArgument; import net.earthcomputer.clientcommands.Configs; -import net.earthcomputer.clientcommands.command.arguments.WithStringArgument; import net.earthcomputer.clientcommands.features.FishingCracker; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.interfaces.IVillager; @@ -41,36 +41,37 @@ import static dev.xpple.clientarguments.arguments.CBlockPosArgument.*; import static dev.xpple.clientarguments.arguments.CEntityArgument.*; import static dev.xpple.clientarguments.arguments.CItemPredicateArgument.*; +import static dev.xpple.clientarguments.arguments.CRangeArgument.*; import static net.earthcomputer.clientcommands.command.arguments.ItemAndEnchantmentsPredicateArgument.*; -import static net.earthcomputer.clientcommands.command.arguments.PredicatedRangeArgument.*; import static net.earthcomputer.clientcommands.command.arguments.WithStringArgument.*; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; public class VillagerCommand { private static final SimpleCommandExceptionType NOT_A_VILLAGER_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notAVillager")); - private static final SimpleCommandExceptionType NO_CRACKED_VILLAGER_PRESENT = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noCrackedVillagerPresent")); - private static final SimpleCommandExceptionType NO_PROFESSION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noProfession")); - private static final SimpleCommandExceptionType NOT_LEVEL_1 = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notLevel1")); - private static final SimpleCommandExceptionType NO_GOALS = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.listGoals.noGoals")); - private static final SimpleCommandExceptionType ALREADY_BRUTE_FORCING = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.alreadyBruteForcing")); - private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); - public static final List goals = new ArrayList<>(); + private static final SimpleCommandExceptionType NO_CRACKED_VILLAGER_PRESENT_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noCrackedVillagerPresent")); + private static final SimpleCommandExceptionType NO_PROFESSION_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noProfession")); + private static final SimpleCommandExceptionType NOT_LEVEL_1_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notLevel1")); + private static final SimpleCommandExceptionType NO_GOALS_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.listGoals.noGoals")); + private static final SimpleCommandExceptionType ALREADY_BRUTE_FORCING_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.alreadyBruteForcing")); + private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX_EXCEPTION = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); + private static final Dynamic2CommandExceptionType ITEM_QUANTITY_OUT_OF_RANGE_EXCEPTION = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); + private static final List goals = new ArrayList<>(); public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { dispatcher.register(literal("cvillager") - .then(literal("add-goal") + .then(literal("add-two-item-goal") .then(argument("first-item", withString(itemPredicate(context))) - .then(argument("first-item-quantity", withString(intRange(1, 64))) + .then(argument("first-count", intRange()) .then(argument("result-item", withString(itemPredicate(context))) - .then(argument("result-item-quantity", withString(intRange(1, 64))) - .executes(ctx -> addGoal(getWithString(ctx, "first-item", CItemStackPredicateArgument.class), getWithString(ctx, "first-item-quantity", MinMaxBounds.Ints.class), null, null, getWithString(ctx, "result-item", CItemStackPredicateArgument.class), getWithString(ctx, "result-item-quantity", MinMaxBounds.Ints.class)))))))) - .then(literal("add-enchanted-goal") + .then(argument("result-count", intRange()) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "first-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "first-count"), null, null, getWithString(ctx, "result-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "result-count")))))))) + .then(literal("add-three-item-enchanted-goal") .then(argument("first-item", withString(itemPredicate(context))) - .then(argument("first-item-quantity", withString(intRange(1, 64))) + .then(argument("first-count", intRange()) .then(argument("second-item", withString(itemPredicate(context))) - .then(argument("second-item-quantity", withString(intRange(1, 64))) + .then(argument("second-count", intRange()) .then(argument("result-item", withString(itemAndEnchantmentsPredicate(context).withEnchantmentPredicate((item, enchantment) -> enchantment.is(EnchantmentTags.TRADEABLE)))) - .executes(ctx -> addGoal(getWithString(ctx, "first-item", CItemStackPredicateArgument.class), getWithString(ctx, "first-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "second-item", CItemStackPredicateArgument.class), getWithString(ctx, "second-item-quantity", MinMaxBounds.Ints.class), getWithString(ctx, "result-item", ItemAndEnchantmentsPredicate.class), new WithStringArgument.Result<>("1", MinMaxBounds.Ints.between(1, 1)))))))))) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "first-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "first-count"), getWithString(ctx, "second-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "second-count"), getWithString(ctx, "result-item", ItemAndEnchantmentsPredicate.class), MinMaxBounds.Ints.between(1, 1))))))))) .then(literal("list-goals") .executes(ctx -> listGoals(ctx.getSource()))) .then(literal("remove-goal") @@ -93,47 +94,23 @@ public static void register(CommandDispatcher dispatc .executes(ctx -> bruteForce(true))))); } - private static int addGoal(Result firstPredicate, Result firstItemQuantityRange, @Nullable Result secondPredicate, @Nullable Result secondItemQuantityRange, Result> resultPredicate, Result resultItemQuantityRange) { - HolderLookup.Provider registries = Minecraft.getInstance().level.registryAccess(); - String firstItemString; - try { - ItemParser.ItemResult firstItemResult = new ItemParser(registries).parse(new StringReader(firstPredicate.string())); - firstItemString = displayText(new ItemStack(firstItemResult.item(), 1, firstItemResult.components()), true); - } catch (CommandSyntaxException e) { - firstItemString = firstPredicate.string(); - } - String secondItemString = null; - if (secondPredicate != null) { - try { - ItemParser.ItemResult secondItemResult = new ItemParser(registries).parse(new StringReader(secondPredicate.string())); - secondItemString = displayText(new ItemStack(secondItemResult.item(), 1, secondItemResult.components()), true); - } catch (CommandSyntaxException e) { - secondItemString = secondPredicate.string(); - } - } - String resultItemString; - if (resultPredicate.value() instanceof ItemAndEnchantmentsPredicate predicate) { - resultItemString = predicate.toString(); - } else { - try { - ItemParser.ItemResult resultItemResult = new ItemParser(registries).parse(new StringReader(resultPredicate.string())); - resultItemString = displayText(new ItemStack(resultItemResult.item(), 1, resultItemResult.components()), true); - } catch (CommandSyntaxException e) { - resultItemString = resultPredicate.string(); - } - } + private static int addGoal(FabricClientCommandSource ctx, Result> first, MinMaxBounds.Ints firstCount, @Nullable Result> second, @Nullable MinMaxBounds.Ints secondCount, Result> result, MinMaxBounds.Ints resultCount) throws CommandSyntaxException { + HolderLookup.Provider registries = ctx.getWorld().registryAccess(); + String firstString = displayPredicate(first, firstCount, registries); + String secondString = second == null || secondCount == null ? null : displayPredicate(second, secondCount, registries); + String resultString = displayPredicate(result, resultCount, registries); goals.add(new Goal( - String.format("%sx %s", firstItemQuantityRange.string(), firstItemString), - item -> firstPredicate.value().test(item) && firstItemQuantityRange.value().matches(item.getCount()), + firstString, + item -> first.value().test(item) && firstCount.matches(item.getCount()), - secondPredicate == null || secondItemQuantityRange == null ? null : String.format("%sx %s", secondItemQuantityRange.string(), secondItemString), - secondPredicate == null || secondItemQuantityRange == null ? null : item -> secondPredicate.value().test(item) && secondItemQuantityRange.value().matches(item.getCount()), + secondString, + second == null || secondCount == null ? null : item -> second.value().test(item) && secondCount.matches(item.getCount()), - String.format("%sx %s", resultItemQuantityRange.string(), resultItemString), - item -> resultPredicate.value().test(item) && resultItemQuantityRange.value().matches(item.getCount()))); - ClientCommandHelper.sendFeedback("commands.cvillager.goalAdded"); + resultString, + item -> result.value().test(item) && resultCount.matches(item.getCount()))); + ctx.sendFeedback(Component.translatable("commands.cvillager.goalAdded")); return Command.SINGLE_SUCCESS; } @@ -142,7 +119,7 @@ private static int listGoals(FabricClientCommandSource source) { source.sendFeedback(Component.translatable("commands.cvillager.listGoals.noGoals").withStyle(style -> style.withColor(ChatFormatting.RED))); } else { if (goals.size() == 1) { - source.sendFeedback(Component.translatable("commands.cvillager.listGoal.success")); + source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success.one")); } else { source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", FishingCracker.goals.size() + 1)); } @@ -160,21 +137,20 @@ private static int removeGoal(FabricClientCommandSource source, int index) throw Goal goal = goals.remove(index); source.sendFeedback(Component.translatable("commands.cvillager.removeGoal.success", goal.toString())); } else { - throw INVALID_GOAL_INDEX.create(index + 1, goals.size()); + throw INVALID_GOAL_INDEX_EXCEPTION.create(index + 1, goals.size()); } return Command.SINGLE_SUCCESS; } private static int setVillagerTarget(@Nullable Entity target) throws CommandSyntaxException { - if (!(target instanceof Villager) && target != null) { - throw NOT_A_VILLAGER_EXCEPTION.create(); - } - - VillagerCracker.setTargetVillager((Villager) target); - if (target == null) { + if (target instanceof Villager villager) { + VillagerCracker.setTargetVillager(villager); + ClientCommandHelper.sendFeedback("commands.cvillager.target.set"); + } else if (target == null) { + VillagerCracker.setTargetVillager(null); ClientCommandHelper.sendFeedback("commands.cvillager.target.cleared"); } else { - ClientCommandHelper.sendFeedback("commands.cvillager.target.set"); + throw NOT_A_VILLAGER_EXCEPTION.create(); } return Command.SINGLE_SUCCESS; @@ -204,25 +180,25 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { Villager targetVillager = VillagerCracker.getVillager(); if (goals.isEmpty()) { - throw NO_GOALS.create(); + throw NO_GOALS_EXCEPTION.create(); } if (!(targetVillager instanceof IVillager iVillager) || !iVillager.clientcommands_getVillagerRngSimulator().getCrackedState().isCracked()) { - throw NO_CRACKED_VILLAGER_PRESENT.create(); + throw NO_CRACKED_VILLAGER_PRESENT_EXCEPTION.create(); } VillagerProfession profession = targetVillager.getVillagerData().getProfession(); if (profession == VillagerProfession.NONE) { - throw NO_PROFESSION.create(); + throw NO_PROFESSION_EXCEPTION.create(); } if (iVillager.clientcommands_getVillagerRngSimulator().isCracking()) { - throw ALREADY_BRUTE_FORCING.create(); + throw ALREADY_BRUTE_FORCING_EXCEPTION.create(); } int currentLevel = targetVillager.getVillagerData().getLevel(); if (!levelUp && currentLevel != 1) { - throw NOT_LEVEL_1.create(); + throw NOT_LEVEL_1_EXCEPTION.create(); } int crackedLevel = levelUp ? currentLevel + 1 : currentLevel; @@ -249,11 +225,11 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { return Command.SINGLE_SUCCESS; } - public record Goal(String firstString, Predicate firstPredicate, @Nullable String secondString, @Nullable Predicate secondPredicate, String resultString, Predicate resultPredicate) { - public boolean matches(ItemStack firstItem, @Nullable ItemStack secondItem, ItemStack result) { - return firstPredicate.test(firstItem) - && ((secondPredicate == null && secondItem == null) || secondItem != null && secondPredicate != null && secondPredicate.test(secondItem)) - && resultPredicate.test(result); + public record Goal(String firstString, Predicate first, @Nullable String secondString, @Nullable Predicate second, String resultString, Predicate result) { + public boolean matches(ItemStack firstItem, @Nullable ItemStack secondItem, ItemStack resultItem) { + return first.test(firstItem) + && ((second == null && secondItem == null) || secondItem != null && second != null && second.test(secondItem)) + && result.test(resultItem); } @Override @@ -287,17 +263,63 @@ public String toString() { } } - public static String displayText(ItemStack stack, boolean ignoreCount) { - String quantityPrefix; - if (stack.getCount() == 1 || ignoreCount) { - quantityPrefix = ""; - } else if (stack.getCount() < 64) { - quantityPrefix = stack.getCount() + " "; - } else if (stack.getCount() % 64 == 0) { - quantityPrefix = stack.getCount() / 64 + " stx "; + private static String displayPredicate(Result> item, MinMaxBounds.Ints count, HolderLookup.Provider registries) throws CommandSyntaxException { + String name; + int maxCount = 64; + if (item.value() instanceof ItemAndEnchantmentsPredicate itemAndEnchantmentsPredicate) { + name = item.value().toString(); + maxCount = itemAndEnchantmentsPredicate.item().getDefaultMaxStackSize(); + } else { + try { + ItemParser.ItemResult firstItemResult = new ItemParser(registries).parse(new StringReader(item.string())); + name = displayText(new ItemStack(firstItemResult.item(), 1, firstItemResult.components()), true); + maxCount = firstItemResult.item().value().getDefaultMaxStackSize(); + } catch (CommandSyntaxException e) { + name = item.string(); + } + } + + @Nullable + String rangeString = displayRange(maxCount, count); + if (rangeString == null) { + throw ITEM_QUANTITY_OUT_OF_RANGE_EXCEPTION.create(count.min().map(Object::toString).orElse("") + ".." + count.max().map(Object::toString).orElse(""), maxCount); + } + + return rangeString + name; + } + + @Nullable + public static String displayRange(int maxCount, MinMaxBounds.Ints range) { + if (range.max().isPresent() && range.max().get() > maxCount || range.min().isPresent() && range.min().get() > maxCount) { + return null; + } + + if (maxCount == 1) { + return ""; + } + + String string = ""; + if ((range.min().isEmpty() || range.min().get() == 1) && (range.max().isPresent() && range.max().get() == maxCount)) { + string = "*"; + } else if (range.min().equals(range.max()) && range.min().isPresent()) { + string = range.min().get().toString(); } else { - quantityPrefix = stack.getCount() / 64 + " stx & " + stack.getCount() % 64 + " "; + if (range.min().isPresent()) { + string = string + range.min().get(); + } + if (!string.equals(" ") || range.max().isPresent()) { + string = string + ".."; + } + if (range.max().isPresent()) { + string = string + range.max().get(); + } } + + return string; + } + + public static String displayText(ItemStack stack, boolean hideCount) { + String quantityPrefix = hideCount || stack.getCount() == 1 ? "" : stack.getCount() + " "; List lines = stack.getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL); String itemDescription = lines.stream().skip(1).map(Component::getString).collect(Collectors.joining(", ")); if (lines.size() == 1) { diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java index ca874e349..eb214049b 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java @@ -9,6 +9,7 @@ import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; +import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.util.MultiVersionCompat; import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.commands.SharedSuggestionProvider; @@ -29,11 +30,7 @@ import net.minecraft.world.item.enchantment.ItemEnchantments; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.function.BiPredicate; import java.util.function.Consumer; @@ -489,30 +486,7 @@ public boolean test(EnchantmentInstance enchInstance) { @Override public String toString() { - String name = Component.translatable(enchantment.unwrapKey().get().location().toLanguageKey("enchantment")).getString(); - - int maxLevel = enchantment.value().getMaxLevel(); - String levelString; - if (maxLevel == 1) { - levelString = ""; - } else if ((level.min().isEmpty() || level.min().get() == 1) && (level.max().isPresent() && level.max().get() == maxLevel)) { - levelString = " *"; - } else if (level.min().equals(level.max()) && level.min().isPresent()) { - levelString = " " + level.min().get(); - } else { - levelString = " "; - if (level.min().isPresent()) { - levelString = levelString + level.min().get(); - } - if (!levelString.equals(" ") || level.max().isPresent()) { - levelString = levelString + ".."; - } - if (level.max().isPresent()) { - levelString = levelString + level.max().get(); - } - } - - return name + levelString; + return Component.translatable(enchantment.unwrapKey().get().location().toLanguageKey("enchantment")).getString() + " " + Objects.requireNonNullElse(VillagerCommand.displayRange(enchantment.value().getMaxLevel(), level), "*"); } } } diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java deleted file mode 100644 index 2fdccda0f..000000000 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/PredicatedRangeArgument.java +++ /dev/null @@ -1,82 +0,0 @@ -package net.earthcomputer.clientcommands.command.arguments; - -import com.mojang.brigadier.StringReader; -import com.mojang.brigadier.arguments.ArgumentType; -import com.mojang.brigadier.context.CommandContext; -import com.mojang.brigadier.exceptions.CommandSyntaxException; -import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; -import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; -import net.minecraft.advancements.critereon.MinMaxBounds; -import net.minecraft.network.chat.Component; -import org.jetbrains.annotations.Nullable; - -public interface PredicatedRangeArgument> extends ArgumentType { - Dynamic2CommandExceptionType INTEGER_VALUE_TOO_LOW = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("argument.integer.low", a, b)); - Dynamic2CommandExceptionType INTEGER_VALUE_TOO_HIGH = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("argument.integer.low", a, b)); - Dynamic2CommandExceptionType FLOAT_VALUE_TOO_LOW = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("argument.float.low", a, b)); - Dynamic2CommandExceptionType FLOAT_VALUE_TOO_HIGH = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("argument.float.low", a, b)); - - static Ints intRange(@Nullable Integer min, @Nullable Integer max) { - return new Ints(min, max); - } - - static Floats floatRange(@Nullable Double min, @Nullable Double max) { - return new Floats(min, max); - } - - class Ints implements PredicatedRangeArgument { - @Nullable - private final Integer min; - @Nullable - private final Integer max; - - public Ints(@Nullable Integer min, @Nullable Integer max) { - this.min = min; - this.max = max; - } - - public static MinMaxBounds.Ints getRangeArgument(final CommandContext context, final String name) { - return context.getArgument(name, MinMaxBounds.Ints.class); - } - - @Override - public MinMaxBounds.Ints parse(StringReader reader) throws CommandSyntaxException { - MinMaxBounds.Ints range = MinMaxBounds.Ints.fromReader(reader); - if (min != null && (range.min().isEmpty() || range.min().get() < min)) { - throw INTEGER_VALUE_TOO_LOW.create(min, range.min().orElse(Integer.MIN_VALUE)); - } - if (max != null && (range.max().isEmpty() || range.max().get() > max)) { - throw INTEGER_VALUE_TOO_HIGH.create(max, range.max().orElse(Integer.MAX_VALUE)); - } - return range; - } - } - - class Floats implements PredicatedRangeArgument { - @Nullable - private final Double min; - @Nullable - private final Double max; - - public Floats(@Nullable Double min, @Nullable Double max) { - this.min = min; - this.max = max; - } - - public static MinMaxBounds.Doubles getRangeArgument(final CommandContext context, final String name) { - return context.getArgument(name, MinMaxBounds.Doubles.class); - } - - @Override - public MinMaxBounds.Doubles parse(StringReader reader) throws CommandSyntaxException { - MinMaxBounds.Doubles range = MinMaxBounds.Doubles.fromReader(reader); - if (min != null && (range.min().isEmpty() || range.min().get() < min)) { - throw FLOAT_VALUE_TOO_LOW.create(min, range.min().orElse(-Double.MAX_VALUE)); - } - if (max != null && (range.max().isEmpty() || range.max().get() < max)) { - throw FLOAT_VALUE_TOO_HIGH.create(max, range.max().orElse(Double.MAX_VALUE)); - } - return range; - } - } -} diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 660480791..331ed3649 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -242,9 +242,9 @@ "commands.cvar.list.empty": "No available variables", "commands.cvar.list": "Available variables: %s", - "commands.cvillager.alreadyBruteForcing": "Cannot brute-force villager RNG since your target villager is already brute forcing.", - "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %d calls.", - "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls.", + "commands.cvillager.alreadyBruteForcing": "Cannot brute-force villager RNG since your target villager is already brute forcing", + "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %d calls", + "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls", "commands.cvillager.clock.cleared": "Clock cleared", "commands.cvillager.clock.set": "Clock set", "commands.cvillager.crack.failed": "Failed to crack villager seed (found %d seeds), re-cracking...", @@ -252,26 +252,27 @@ "commands.cvillager.failure": "Got the incorrect trade with correction of %dms", "commands.cvillager.goalAdded": "Added goal successfully.", "commands.cvillager.help.day": "Help: Villager RNG manipulation is likely to break if it's not night-time", - "commands.cvillager.help.noClock": "Help: Villager RNG manipulation requires a 20 Hz clock.", - "commands.cvillager.help.tooSlow": "Help: Villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running much slower.", + "commands.cvillager.help.noClock": "Help: Villager RNG manipulation requires a 20 Hz clock", + "commands.cvillager.help.tooSlow": "Help: Villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running much slower", "commands.cvillager.inSync": "Your villager's RNG is cracked", - "commands.cvillager.listGoal.success": "There is 1 villager goal:", - "commands.cvillager.listGoals.noGoals": "There are no villager goals.", + "commands.cvillager.listGoals.noGoals": "There are no villager goals", "commands.cvillager.listGoals.success": "There are %d villager goals:", + "commands.cvillager.listGoals.success.one": "There is 1 villager goal:", "commands.cvillager.noCrackedVillagerPresent": "There was no cracked villager available to use", - "commands.cvillager.noProfession": "The targeted villager has no profession.", + "commands.cvillager.noProfession": "The targeted villager has no profession", "commands.cvillager.notAVillager": "Target was not a villager", - "commands.cvillager.notLevel1": "The targeted villager has level above 1.", - "commands.cvillager.outOfSync.ambient": "Your Villager's hrmm sound was incorrectly timed and or incorrectly pitched, re-cracking.", - "commands.cvillager.outOfSync.distance": "Your Villager was too far away from you, re-cracking.", - "commands.cvillager.outOfSync.no": "Your Villager's no sound was incorrectly pitched, re-cracking.", - "commands.cvillager.outOfSync.splash": "Your Villager's splash sound was incorrectly pitched, re-cracking.", - "commands.cvillager.outOfSync.xpOrb": "Your Villager's xp orb was incorrectly sized, re-cracking.", - "commands.cvillager.outOfSync.yes": "Your Villager's yes sound was incorrectly pitched, re-cracking.", + "commands.cvillager.notLevel1": "The targeted villager has level above 1", + "commands.cvillager.outOfSync.ambient": "Your villager's hrmm sound was incorrectly timed and or incorrectly pitched, re-cracking", + "commands.cvillager.outOfSync.distance": "Your villager was too far away from you, re-cracking", + "commands.cvillager.outOfSync.no": "Your villager's no sound was incorrectly pitched, re-cracking", + "commands.cvillager.outOfSync.splash": "Your villager's splash sound was incorrectly pitched, re-cracking", + "commands.cvillager.outOfSync.xpOrb": "Your villager's xp orb was incorrectly sized, re-cracking", + "commands.cvillager.outOfSync.yes": "Your villager's yes sound was incorrectly pitched, re-cracking", "commands.cvillager.partiallyCracked": "Your villager's RNG is partially cracked (~83m seeds remain)", - "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals.", + "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals", + "commands.cvillager.itemCountOutOfRange": "The specified item count range (%s) overlaps into an item count outside the maximum (%d)", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", - "commands.cvillager.resetCracker": "Successfully reset cracked villager RNG.", + "commands.cvillager.resetCracker": "Successfully reset cracked villager RNG", "commands.cvillager.success": "Got the correct trade with correction of %dms", "commands.cvillager.target.cleared": "Target entity cleared", "commands.cvillager.target.set": "Target entity set", From 42e3a20ef94722d114a15a96a0b91929f35d7aaa Mon Sep 17 00:00:00 2001 From: RTTV Date: Mon, 1 Jul 2024 22:27:30 -0400 Subject: [PATCH 28/78] added three-item-goal and two-item-enchanted-goal --- .../command/VillagerCommand.java | 23 +++++++++++++++---- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 732db250a..c85dde8d7 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -65,6 +65,19 @@ public static void register(CommandDispatcher dispatc .then(argument("result-item", withString(itemPredicate(context))) .then(argument("result-count", intRange()) .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "first-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "first-count"), null, null, getWithString(ctx, "result-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "result-count")))))))) + .then(literal("add-three-item-goal") + .then(argument("first-item", withString(itemPredicate(context))) + .then(argument("first-count", intRange()) + .then(argument("second-item", withString(itemPredicate(context))) + .then(argument("second-count", intRange()) + .then(argument("result-item", withString(itemPredicate(context))) + .then(argument("result-count", intRange()) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "first-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "first-count"), getWithString(ctx, "second-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "second-count"), getWithString(ctx, "result-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "result-count")))))))))) + .then(literal("add-two-item-enchanted-goal") + .then(argument("first-item", withString(itemPredicate(context))) + .then(argument("first-count", intRange()) + .then(argument("result-item", withString(itemAndEnchantmentsPredicate(context).withEnchantmentPredicate((item, enchantment) -> enchantment.is(EnchantmentTags.TRADEABLE)))) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "first-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "first-count"), null, null, getWithString(ctx, "result-item", ItemAndEnchantmentsPredicate.class), MinMaxBounds.Ints.between(1, 1))))))) .then(literal("add-three-item-enchanted-goal") .then(argument("first-item", withString(itemPredicate(context))) .then(argument("first-count", intRange()) @@ -205,7 +218,7 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(crackedLevel, new VillagerTrades.ItemListing[0]); int adjustmentTicks = 1 + (levelUp ? -40 : 0); - Pair pair = iVillager.clientcommands_getVillagerRngSimulator().bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer.first(), offer.second(), offer.result()))).mapFirst(x -> x + adjustmentTicks * 2); + Pair pair = iVillager.clientcommands_getVillagerRngSimulator().bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer))).mapFirst(x -> x + adjustmentTicks * 2); int calls = pair.getFirst(); Offer offer = pair.getSecond(); if (calls < 0) { @@ -226,10 +239,10 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { } public record Goal(String firstString, Predicate first, @Nullable String secondString, @Nullable Predicate second, String resultString, Predicate result) { - public boolean matches(ItemStack firstItem, @Nullable ItemStack secondItem, ItemStack resultItem) { - return first.test(firstItem) - && ((second == null && secondItem == null) || secondItem != null && second != null && second.test(secondItem)) - && result.test(resultItem); + public boolean matches(Offer offer) { + return first.test(offer.first) + && ((second == null && offer.second == null) || offer.second != null && second != null && second.test(offer.second)) + && result.test(offer.result); } @Override From 6ecb586394c59502c6c69678580b8ad611a06864 Mon Sep 17 00:00:00 2001 From: RTTV Date: Tue, 2 Jul 2024 21:52:32 -0400 Subject: [PATCH 29/78] whoop --- .../earthcomputer/clientcommands/command/VillagerCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index c85dde8d7..bc3e99a9c 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -54,7 +54,7 @@ public class VillagerCommand { private static final SimpleCommandExceptionType NO_GOALS_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.listGoals.noGoals")); private static final SimpleCommandExceptionType ALREADY_BRUTE_FORCING_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.alreadyBruteForcing")); private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX_EXCEPTION = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); - private static final Dynamic2CommandExceptionType ITEM_QUANTITY_OUT_OF_RANGE_EXCEPTION = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); + private static final Dynamic2CommandExceptionType ITEM_QUANTITY_OUT_OF_RANGE_EXCEPTION = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.itemCountOutOfRange", a, b)); private static final List goals = new ArrayList<>(); public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { From c453a39919159bc228f283f120d206269c4d2084 Mon Sep 17 00:00:00 2001 From: RTTV Date: Tue, 9 Jul 2024 17:20:14 -0400 Subject: [PATCH 30/78] updated and some minor, minor stuff --- .../command/VillagerCommand.java | 23 +++++++++++++++---- .../features/VillagerCracker.java | 5 ++-- .../assets/clientcommands/lang/en_us.json | 5 ++-- 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index bc3e99a9c..f4cd74b64 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -15,13 +15,13 @@ import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.ChatFormatting; import net.minecraft.advancements.critereon.MinMaxBounds; -import net.minecraft.client.Minecraft; import net.minecraft.commands.CommandBuildContext; import net.minecraft.commands.arguments.item.ItemParser; import net.minecraft.core.BlockPos; import net.minecraft.core.GlobalPos; import net.minecraft.core.HolderLookup; import net.minecraft.network.chat.Component; +import net.minecraft.resources.ResourceKey; import net.minecraft.tags.EnchantmentTags; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; @@ -30,6 +30,7 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; @@ -95,8 +96,9 @@ public static void register(CommandDispatcher dispatc .then(argument("entity", entity()) .executes(ctx -> setVillagerTarget(getEntity(ctx, "entity"))))) .then(literal("clock") + .executes(ctx -> getClockPos()) .then(argument("pos", blockPos()) - .executes(ctx -> setClockPos(getBlockPos(ctx, "pos"))))) + .executes(ctx -> setClockPos(ctx.getSource(), getBlockPos(ctx, "pos"))))) .then(literal("reset-cracker") .executes(ctx -> resetCracker())) .then(literal("brute-force") @@ -169,12 +171,23 @@ private static int setVillagerTarget(@Nullable Entity target) throws CommandSynt return Command.SINGLE_SUCCESS; } - private static int setClockPos(BlockPos pos) { - VillagerCracker.setClockPos(pos == null ? null : new GlobalPos(Minecraft.getInstance().player.level().dimension(), pos)); + private static int getClockPos() { + GlobalPos pos = VillagerCracker.getClockPos(); if (pos == null) { ClientCommandHelper.sendFeedback("commands.cvillager.clock.cleared"); } else { - ClientCommandHelper.sendFeedback("commands.cvillager.clock.set"); + ClientCommandHelper.sendFeedback("commands.cvillager.clock.set", pos.pos().getX(), pos.pos().getY(), pos.pos().getZ(), pos.dimension().location()); + } + return Command.SINGLE_SUCCESS; + } + + private static int setClockPos(FabricClientCommandSource ctx, BlockPos pos) { + ResourceKey dimension = ctx.getWorld().dimension(); + VillagerCracker.setClockPos(pos == null ? null : new GlobalPos(dimension, pos)); + if (pos == null) { + ClientCommandHelper.sendFeedback("commands.cvillager.clock.set.cleared"); + } else { + ClientCommandHelper.sendFeedback("commands.cvillager.clock.set", pos.getX(), pos.getY(), pos.getZ(), dimension.location()); } return Command.SINGLE_SUCCESS; } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 487f25f28..b869b79e4 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -44,8 +44,9 @@ public static Villager getVillager() { return villager; } } - if (Minecraft.getInstance().level != null) { - for (Entity entity : Minecraft.getInstance().level.entitiesForRendering()) { + ClientLevel level = Minecraft.getInstance().level; + if (level != null) { + for (Entity entity : level.entitiesForRendering()) { if (entity.getUUID() == villagerUuid && entity instanceof Villager villager) { cachedVillager = new WeakReference<>(villager); return villager; diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 331ed3649..fea7eee08 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -245,8 +245,9 @@ "commands.cvillager.alreadyBruteForcing": "Cannot brute-force villager RNG since your target villager is already brute forcing", "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %d calls", "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls", - "commands.cvillager.clock.cleared": "Clock cleared", - "commands.cvillager.clock.set": "Clock set", + "commands.cvillager.clock.cleared": "Your clock is cleared", + "commands.cvillager.clock.set": "Clock set to %d %d %d (%s)", + "commands.cvillager.clock.set.cleared": "Your clock is now cleared", "commands.cvillager.crack.failed": "Failed to crack villager seed (found %d seeds), re-cracking...", "commands.cvillager.crack.success": "Villager RNG cracked: %d", "commands.cvillager.failure": "Got the incorrect trade with correction of %dms", From 6293252021fd266f18bb49b9394dae66303f31d3 Mon Sep 17 00:00:00 2001 From: Katie <72476111+RealRTTV@users.noreply.github.com> Date: Fri, 12 Jul 2024 16:45:26 -0400 Subject: [PATCH 31/78] Update clientcommands.aw --- src/main/resources/clientcommands.aw | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/resources/clientcommands.aw b/src/main/resources/clientcommands.aw index 52fa53310..6fe0f89aa 100644 --- a/src/main/resources/clientcommands.aw +++ b/src/main/resources/clientcommands.aw @@ -50,4 +50,3 @@ accessible class net/minecraft/client/renderer/RenderStateShard$LineStateShard accessible field net/minecraft/world/entity/LivingEntity lastHurt F accessible field net/minecraft/world/entity/decoration/ArmorStand invisible Z accessible field net/minecraft/world/level/levelgen/LegacyRandomSource seed Ljava/util/concurrent/atomic/AtomicLong; -accessible field net/minecraft/world/inventory/MerchantMenu trader Lnet/minecraft/world/item/trading/Merchant; From b4a94ef6b42758b589a88c32babbef44906a6c10 Mon Sep 17 00:00:00 2001 From: Katie <72476111+RealRTTV@users.noreply.github.com> Date: Sat, 13 Jul 2024 10:25:30 -0400 Subject: [PATCH 32/78] removed wildcard import --- .../arguments/ItemAndEnchantmentsPredicateArgument.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java index eb214049b..7ada8314b 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java @@ -30,7 +30,11 @@ import net.minecraft.world.item.enchantment.ItemEnchantments; import org.jetbrains.annotations.Nullable; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.function.BiPredicate; import java.util.function.Consumer; From 75bd52ef6dfdfa365f3da7749e86579e6e541687 Mon Sep 17 00:00:00 2001 From: Katie <72476111+RealRTTV@users.noreply.github.com> Date: Sat, 13 Jul 2024 10:29:05 -0400 Subject: [PATCH 33/78] Update DebugRandom.java --- .../java/net/earthcomputer/clientcommands/util/DebugRandom.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java index 0cfcf4b32..3c8d729f4 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java @@ -32,7 +32,6 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; import java.util.Vector; import java.util.zip.GZIPInputStream; From c170054a2723c0bc176827ae1de1dce4d472c915 Mon Sep 17 00:00:00 2001 From: Katie <72476111+RealRTTV@users.noreply.github.com> Date: Sat, 13 Jul 2024 10:29:11 -0400 Subject: [PATCH 34/78] Update DebugRandom.java --- .../java/net/earthcomputer/clientcommands/util/DebugRandom.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java index 3c8d729f4..6e7c28b73 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java @@ -16,7 +16,6 @@ import net.minecraft.world.entity.EntityType; import net.minecraft.world.level.levelgen.LegacyRandomSource; import net.minecraft.world.level.levelgen.RandomSupport; -import org.apache.commons.lang3.mutable.MutableInt; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; From c3e40900a68e92f3b4ca3ffcf3e7504b6c02fbdf Mon Sep 17 00:00:00 2001 From: Katie <72476111+RealRTTV@users.noreply.github.com> Date: Sat, 13 Jul 2024 10:29:16 -0400 Subject: [PATCH 35/78] Update DebugRandom.java --- .../clientcommands/util/DebugRandom.java | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java index 6e7c28b73..7c57785d9 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java @@ -267,19 +267,6 @@ class DebugRandomSourcePanel extends JPanel { } }); bottomPanel.add(dumpStackTraceButton); - JButton dumpStackTracesWithQuantitiesButton = new JButton("Dump unique stack traces with quantities"); - dumpStackTracesWithQuantitiesButton.addActionListener(e -> { - if (selectedTick == null) { - return; - } - - LinkedHashMap map = new LinkedHashMap<>(); - for (RandomCall call : selectedTick) { - map.computeIfAbsent(call, k -> new MutableInt(1)).add(1); - } - DebugRandom.LOGGER.info(String.join("\n\n", map.entrySet().stream().map(entry -> String.format("[x%d] %s", entry.getValue().getValue(), DebugRandom.stackTraceById.get(entry.getKey().stackTrace()))).toArray(String[]::new))); - }); - bottomPanel.add(dumpStackTracesWithQuantitiesButton); add(bottomPanel, BorderLayout.SOUTH); } From 7ac0113e783e4a8c7dac0b73658341fdcaf22a5d Mon Sep 17 00:00:00 2001 From: Katie <72476111+RealRTTV@users.noreply.github.com> Date: Sat, 13 Jul 2024 10:34:08 -0400 Subject: [PATCH 36/78] Update ItemAndEnchantmentsPredicateArgument.java --- .../command/arguments/ItemAndEnchantmentsPredicateArgument.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java index 7ada8314b..0119b26c6 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java @@ -39,6 +39,7 @@ import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Predicate; +import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; From 02ee3c749e299d6ceda741daddefe8fa2b9bec7b Mon Sep 17 00:00:00 2001 From: RTTV Date: Sat, 28 Sep 2024 12:01:23 -0400 Subject: [PATCH 37/78] fixed some todo items --- .../clientcommands/features/CCrackRngGen.java | 2 +- .../net/earthcomputer/clientcommands/util/DebugRandom.java | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/CCrackRngGen.java b/src/main/java/net/earthcomputer/clientcommands/features/CCrackRngGen.java index d136e0049..74c8c23fd 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/CCrackRngGen.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/CCrackRngGen.java @@ -26,7 +26,7 @@ private CCrackRngGen() {} private static final BigVector ORIGIN = DeserializeRt.vec( "\u0a00ʈ뒦벎츖ʐ駗질긾ʘ뾖黱덪ʠ뚊ꃪ쀆ʨ躛\ue6d4锦ʰ힒볩ﱁʸꆽ\uaaf8葉ˀﲈ쎉錏ˈ\uf8a5\uf19e똠Ȁ"); private static final BigVector ROOT_ORIGIN = DeserializeRt.vec( - "\u0ad7醌뗤ꪜހ肀肀耠횑貵\ue4aaﰃ肀肀肀‟ࣞ뚂\uf1e0뮚Ҁ肀肀耠骤蟓ꊳ輆肀肀肀⃟뚂\uf1e0뭲肀肀肀ဦ࢚ꒇ펢뎧ڀ肀肀耠\udeb6英\ue0bb㺀肀肀耐\udfb6英\ue0bbʀ肀肀耠"); + "\u0ad7醌뗤ꪜހ肀肀耠횑貵\ue4aaﰃ肀肀肀‟ࣞ뚂\uf1e0뮚Ҁ肀肀耠骤蟓ꊳ輆肀肀肀⃟뚂\uf1e0뭲肀肀肀ဦ\u089aꒇ펢뎧ڀ肀肀耠\udeb6英\ue0bb㺀肀肀耐\udfb6英\ue0bbʀ肀肀耠"); /** * Finds all values of {@code seed} that could produce the given results in the following code: diff --git a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java index 7c57785d9..885a4e479 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java @@ -260,13 +260,6 @@ class DebugRandomSourcePanel extends JPanel { add(tabbedPane, BorderLayout.CENTER); JPanel bottomPanel = new JPanel(); - JButton dumpStackTraceButton = new JButton("Dump stack trace"); - dumpStackTraceButton.addActionListener(e -> { - if (selectedStackTrace >= 0 && selectedStackTrace < DebugRandom.stackTraceById.size()) { - DebugRandom.LOGGER.info(DebugRandom.stackTraceById.get(selectedStackTrace)); - } - }); - bottomPanel.add(dumpStackTraceButton); add(bottomPanel, BorderLayout.SOUTH); } From ee6123392980720ffde44add86a2f9ad0bd61545 Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 21 Nov 2024 14:35:54 -0500 Subject: [PATCH 38/78] added error calculation and updated to 1.21.3 --- gradle.properties | 2 +- .../command/VillagerCommand.java | 52 ++++++++------ .../ItemAndEnchantmentsPredicateArgument.java | 3 +- .../features/VillagerCracker.java | 5 +- .../features/VillagerRngSimulator.java | 67 +++++++++++++++++-- .../commands/villager/VillagerMixin.java | 2 +- .../rngevents/ClientPacketListenerMixin.java | 2 +- .../mixin/rngevents/MerchantScreenMixin.java | 45 ++++++++++++- .../assets/clientcommands/lang/en_us.json | 1 + 9 files changed, 144 insertions(+), 35 deletions(-) diff --git a/gradle.properties b/gradle.properties index e603b5fb1..f44b170c4 100644 --- a/gradle.properties +++ b/gradle.properties @@ -7,7 +7,7 @@ org.gradle.jvmargs=-Xmx2G minecraft_version_dependency=>=1.21.2 <=1.21.3 minecraft_version_list=1.21.2, 1.21.3 minecraft_version_list_presentable=1.21.2 - 1.21.3 - loader_version=0.16.7 + loader_version=0.16.8 parchment_mcversion=1.21 parchment_version=2024.07.28 diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index f4cd74b64..63673b7d5 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -11,6 +11,7 @@ import net.earthcomputer.clientcommands.Configs; import net.earthcomputer.clientcommands.features.FishingCracker; import net.earthcomputer.clientcommands.features.VillagerCracker; +import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.ChatFormatting; @@ -30,10 +31,13 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.item.trading.ItemCost; +import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -136,7 +140,7 @@ private static int listGoals(FabricClientCommandSource source) { if (goals.size() == 1) { source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success.one")); } else { - source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", FishingCracker.goals.size() + 1)); + source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", goals.size() + 1)); } for (int i = 0; i < goals.size(); i++) { Goal goal = goals.get(i); @@ -176,7 +180,7 @@ private static int getClockPos() { if (pos == null) { ClientCommandHelper.sendFeedback("commands.cvillager.clock.cleared"); } else { - ClientCommandHelper.sendFeedback("commands.cvillager.clock.set", pos.pos().getX(), pos.pos().getY(), pos.pos().getZ(), pos.dimension().location()); + ClientCommandHelper.sendFeedback("commands.cvillager.clock.set", pos.pos().getX(), pos.pos().getY(), pos.pos().getZ(), String.valueOf(pos.dimension().location())); } return Command.SINGLE_SUCCESS; } @@ -187,7 +191,7 @@ private static int setClockPos(FabricClientCommandSource ctx, BlockPos pos) { if (pos == null) { ClientCommandHelper.sendFeedback("commands.cvillager.clock.set.cleared"); } else { - ClientCommandHelper.sendFeedback("commands.cvillager.clock.set", pos.getX(), pos.getY(), pos.getZ(), dimension.location()); + ClientCommandHelper.sendFeedback("commands.cvillager.clock.set", pos.getX(), pos.getY(), pos.getZ(), String.valueOf(dimension.location())); } return Command.SINGLE_SUCCESS; } @@ -231,22 +235,24 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(crackedLevel, new VillagerTrades.ItemListing[0]); int adjustmentTicks = 1 + (levelUp ? -40 : 0); - Pair pair = iVillager.clientcommands_getVillagerRngSimulator().bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer))).mapFirst(x -> x + adjustmentTicks * 2); - int calls = pair.getFirst(); - Offer offer = pair.getSecond(); - if (calls < 0) { + VillagerRngSimulator.BruteForceResult result = iVillager.clientcommands_getVillagerRngSimulator().bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer))); + if (result == null) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationCalls).withStyle(ChatFormatting.RED), 100); + return Command.SINGLE_SUCCESS; + } + Pair, List> surroundingOffers = iVillager.clientcommands_getVillagerRngSimulator().generateSurroundingOffers(listings, result.ticksPassed(), 1000); + int calls = result.callsAtInteraction() + adjustmentTicks * 2; + Offer offer = result.offer(); + String price; + if (offer.second() == null) { + price = displayText(offer.first(), false); } else { - String price; - if (offer.second() == null) { - price = displayText(offer.first(), false); - } else { - price = displayText(offer.first(), false) + " + " + displayText(offer.second(), false); - } - ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", displayText(offer.result(), false), price, calls).withStyle(ChatFormatting.GREEN)); - VillagerCracker.targetOffer = offer; - iVillager.clientcommands_getVillagerRngSimulator().setCallsUntilToggleGui(calls); + price = displayText(offer.first(), false) + " + " + displayText(offer.second(), false); } + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", displayText(offer.result(), false), price, calls).withStyle(ChatFormatting.GREEN)); + VillagerCracker.targetOffer = offer; + VillagerCracker.surroundingOffers = surroundingOffers; + iVillager.clientcommands_getVillagerRngSimulator().setCallsUntilToggleGui(calls); return Command.SINGLE_SUCCESS; } @@ -269,14 +275,18 @@ public String toString() { } public record Offer(ItemStack first, @Nullable ItemStack second, ItemStack result) { + public Offer(MerchantOffer offer) { + this(offer.getBaseCostA(), offer.getItemCostB().map(ItemCost::itemStack).orElse(null), offer.getResult()); + } + @Override public boolean equals(Object obj) { - if (!(obj instanceof Offer other)) { + if (!(obj instanceof Offer(ItemStack offerFirst, ItemStack offerSecond, ItemStack offerResult))) { return false; } - return ItemStack.isSameItemSameComponents(this.first, other.first) && this.first.getCount() == other.first.getCount() - && (this.second == other.second || this.second != null && other.second != null && ItemStack.isSameItemSameComponents(this.second, other.second) && this.second.getCount() == other.second.getCount()) - && ItemStack.isSameItemSameComponents(this.result, other.result) && this.result.getCount() == other.result.getCount(); + return ItemStack.isSameItemSameComponents(this.first, offerFirst) && this.first.getCount() == offerFirst.getCount() + && (this.second == offerSecond || this.second != null && offerSecond != null && ItemStack.isSameItemSameComponents(this.second, offerSecond) && this.second.getCount() == offerSecond.getCount()) + && ItemStack.isSameItemSameComponents(this.result, offerResult) && this.result.getCount() == offerResult.getCount(); } @Override @@ -311,7 +321,7 @@ private static String displayPredicate(Result> it throw ITEM_QUANTITY_OUT_OF_RANGE_EXCEPTION.create(count.min().map(Object::toString).orElse("") + ".." + count.max().map(Object::toString).orElse(""), maxCount); } - return rangeString + name; + return rangeString + " " + name; } @Nullable diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java index 563c3b793..55f3ea9de 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java @@ -493,7 +493,8 @@ public boolean test(EnchantmentInstance enchInstance) { @Override public String toString() { - return Component.translatable(enchantment.unwrapKey().get().location().toLanguageKey("enchantment")).getString() + " " + Objects.requireNonNullElse(VillagerCommand.displayRange(enchantment.value().getMaxLevel(), level), "*"); + String quantity = VillagerCommand.displayRange(enchantment.value().getMaxLevel(), level); + return Component.translatable(enchantment.unwrapKey().get().location().toLanguageKey("enchantment")).getString() + " " + (quantity == null || quantity.isEmpty() ? "*" : quantity); } } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index b869b79e4..d57817f0e 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -1,5 +1,6 @@ package net.earthcomputer.clientcommands.features; +import com.mojang.datafixers.util.Pair; import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.interfaces.IVillager; @@ -14,6 +15,7 @@ import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; +import java.util.List; import java.util.UUID; public class VillagerCracker { @@ -28,6 +30,7 @@ public class VillagerCracker { private static GlobalPos clockPos = null; @Nullable public static VillagerCommand.Offer targetOffer = null; + public static Pair, List> surroundingOffers = null; @Nullable private static Long lastServerTick = null; private static boolean receivedClockRateWarning = false; @@ -91,7 +94,7 @@ public static void onSoundEventPlayed(ClientboundSoundPacket packet) { return; } - switch (packet.getSound().value().getLocation().toString()) { + switch (packet.getSound().value().location().toString()) { case "minecraft:entity.villager.ambient", "minecraft:entity.villager.trade" -> ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(packet.getPitch()); case "minecraft:entity.villager.no" -> ((IVillager) targetVillager).clientcommands_onNoSoundPlayed(packet.getPitch()); case "minecraft:entity.villager.yes" -> ((IVillager) targetVillager).clientcommands_onYesSoundPlayed(packet.getPitch()); diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index cea183765..c4230510d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -31,6 +31,7 @@ import java.io.DataInputStream; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Objects; import java.util.function.Predicate; @@ -182,15 +183,14 @@ public VillagerCommand.Offer anyOffersMatch(VillagerTrades.ItemListing[] listing return null; } - RandomSource rand = new LegacyRandomSource(random.getSeed() ^ 0x5deece66dL);; - + RandomSource rand = new LegacyRandomSource(random.getSeed() ^ 0x5deece66dL); ArrayList newListings = new ArrayList<>(List.of(listings)); int i = 0; while (i < 2 && !newListings.isEmpty()) { VillagerTrades.ItemListing listing = newListings.remove(rand.nextInt(newListings.size())); MerchantOffer offer = listing.getOffer(trader, rand); if (offer != null) { - VillagerCommand.Offer x = new VillagerCommand.Offer(offer.getBaseCostA(), offer.getItemCostB().map(ItemCost::itemStack).orElse(null), offer.getResult()); + VillagerCommand.Offer x = new VillagerCommand.Offer(offer); if (predicate.test(x)) { return x; } else { @@ -201,6 +201,28 @@ public VillagerCommand.Offer anyOffersMatch(VillagerTrades.ItemListing[] listing return null; } + @Nullable + public VillagerCommand.Offer[] generateOffers(VillagerTrades.ItemListing[] listings, Entity trader) { + if (!getCrackedState().isCracked()) { + return null; + } + + VillagerCommand.Offer[] offers = new VillagerCommand.Offer[Math.min(listings.length, 2)]; + + RandomSource rand = new LegacyRandomSource(random.getSeed() ^ 0x5deece66dL); + ArrayList newListings = new ArrayList<>(List.of(listings)); + + for (int i = 0; i < offers.length; i++) { + VillagerTrades.ItemListing listing = newListings.remove(rand.nextInt(newListings.size())); + MerchantOffer offer = listing.getOffer(trader, rand); + if (offer != null) { + offers[i] = new VillagerCommand.Offer(offer); + } + } + + return offers; + } + public void setCallsUntilToggleGui(int calls) { callsAtStartOfBruteForce = totalCalls; callsInBruteForce = calls; @@ -383,29 +405,60 @@ public void onXpOrbSpawned(int value) { } } - public Pair bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxCalls, Predicate predicate) { + @Nullable + public BruteForceResult bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxCalls, Predicate predicate) { Villager targetVillager = VillagerCracker.getVillager(); if (targetVillager != null && getCrackedState().isCracked()) { VillagerRngSimulator rng = this.copy(); int startingCalls = rng.getTotalCalls(); + int ticksPassed = 0; for (int i = 0; i < minTicks; i++) { rng.simulateTick(); + ticksPassed++; } while (rng.getTotalCalls() < maxCalls + startingCalls) { VillagerRngSimulator randomBranch = rng.copy(); randomBranch.simulateTick(); + ticksPassed++; VillagerCommand.Offer offer = randomBranch.anyOffersMatch(listings, targetVillager, predicate); if (offer != null) { // we do the calls before this ticks processing so that since with 0ms ping, the server reads it next tick - return Pair.of(rng.getTotalCalls() - startingCalls, offer); + return new BruteForceResult(rng.getTotalCalls() - startingCalls, ticksPassed, offer); } rng.simulateTick(); } } - return Pair.of(-1_000_000, null); + return null; + } + + public Pair, List> generateSurroundingOffers(VillagerTrades.ItemListing[] listings, int centerTicks, int radius) { + Villager targetVillager = VillagerCracker.getVillager(); + + if (targetVillager == null || !getCrackedState().isCracked()) { + return Pair.of(List.of(), List.of()); + } + + List before = new ArrayList<>(radius); + List after = new ArrayList<>(radius); + + VillagerRngSimulator rng = this.copy(); + for (int i = 0; i < Math.max(0, centerTicks - radius); i++) { + rng.simulateTick(); + } + for (int i = Math.max(0, centerTicks - radius); i < centerTicks - 1; i++) { + rng.simulateTick(); + before.add(rng.generateOffers(listings, targetVillager)); + } + rng.simulateTick(); // this would be our actual offer (at `centerTicks` ticks of advancement) + for (int i = 0; i < radius; i++) { + rng.simulateTick(); + after.add(rng.generateOffers(listings, targetVillager)); + } + + return Pair.of(before, after); } public long[] crackSeed() { @@ -489,4 +542,6 @@ public Component getMessage(boolean addColor) { }; } } + + public record BruteForceResult(int callsAtInteraction, int ticksPassed, VillagerCommand.Offer offer) {} } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index 1ec26cd3d..18ba7be67 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -59,7 +59,7 @@ public void clientcommands_onServerTick() { minecraft.screen.onClose(); } else { InteractionResult result = minecraft.gameMode.interact(minecraft.player, this, InteractionHand.MAIN_HAND); - if (result.consumesAction() && result.shouldSwing()) { + if (result instanceof InteractionResult.Success success && success.swingSource() == InteractionResult.SwingSource.CLIENT) { minecraft.player.swing(InteractionHand.MAIN_HAND); } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java index 5d11ec83d..4ccc39150 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java @@ -71,7 +71,7 @@ private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackIn @Inject(method = "handleSetTime", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) private void handleSetTime(ClientboundSetTimePacket packet, CallbackInfo ci) { - if (level.getDayTime() < 12000 && packet.getDayTime() >= 12000) { + if (level.getDayTime() < 12000 && packet.dayTime() >= 12000) { Villager targetVillager = VillagerCracker.getVillager(); if (targetVillager != null) { ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java index 8dd3adde3..77720c472 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java @@ -12,6 +12,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.MerchantMenu; @@ -21,6 +22,10 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Arrays; +import java.util.List; +import java.util.OptionalInt; + @Mixin(MerchantScreen.class) public abstract class MerchantScreenMixin extends AbstractContainerScreen { public MerchantScreenMixin(MerchantMenu menu, Inventory playerInventory, Component title) { @@ -31,7 +36,7 @@ public MerchantScreenMixin(MerchantMenu menu, Inventory playerInventory, Compone private void onRender(CallbackInfo ci) { Villager targetVillager = VillagerCracker.getVillager(); if (targetVillager != null) { - if (Minecraft.getInstance().player.distanceToSqr(targetVillager) > 2.0) { + if (Minecraft.getInstance().player.distanceTo(targetVillager) > 2.0) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.distance").withStyle(ChatFormatting.RED), 100); ((IVillager) targetVillager).clientcommands_getVillagerRngSimulator().reset(); return; @@ -42,8 +47,42 @@ private void onRender(CallbackInfo ci) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.success", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.GREEN), 100); minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); } else { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.RED), 100); - minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); + a: { + if (VillagerCracker.surroundingOffers != null) { + VillagerCommand.Offer[] availableOffers = menu.getOffers().stream().map(VillagerCommand.Offer::new).toArray(VillagerCommand.Offer[]::new); + List beforeOffers = VillagerCracker.surroundingOffers.getFirst(); + List afterOffers = VillagerCracker.surroundingOffers.getSecond(); + OptionalInt currentOfferTickIndex = OptionalInt.empty(); + for (int i = beforeOffers.size() - 1; i >= 0; i--) { + VillagerCommand.Offer[] offers = beforeOffers.get(i); + if (Arrays.equals(offers, availableOffers)) { + // we need to adjust by -1 to get it to not be 0 for the last value in `beforeOffers` + currentOfferTickIndex = OptionalInt.of(-(beforeOffers.size() - 1 - i) - 1); + break; + } + } + + for (int i = 0; i < afterOffers.size(); i++) { + VillagerCommand.Offer[] offers = afterOffers.get(i); + if (Arrays.equals(offers, availableOffers)) { + if (currentOfferTickIndex.isEmpty() || Mth.abs(currentOfferTickIndex.getAsInt()) > i + 1) { + // we need to adjust by 1 to get it to not be 0 for the first value in `afterOffers` + currentOfferTickIndex = OptionalInt.of(i + 1); + break; + } + } + } + + if (currentOfferTickIndex.isPresent()) { + // we negate the currentOfferTickIndex as adjustment because in the case that our actual offers are found + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure.detailed", Configs.villagerAdjustment * 50, -currentOfferTickIndex.getAsInt()).withStyle(ChatFormatting.RED), 100); + break a; + } + } + + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.RED), 100); + minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); + } } VillagerCracker.targetOffer = null; } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index d83b01012..8d6ca2d0c 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -252,6 +252,7 @@ "commands.cvillager.crack.failed": "Failed to crack villager seed (found %d seeds), re-cracking...", "commands.cvillager.crack.success": "Villager RNG cracked: %d", "commands.cvillager.failure": "Got the incorrect trade with correction of %dms", + "commands.cvillager.failure.detailed": "Got the incorrect trade with correction of %dms (was %d ticks ahead)", "commands.cvillager.goalAdded": "Added goal successfully.", "commands.cvillager.help.day": "Help: Villager RNG manipulation is likely to break if it's not night-time", "commands.cvillager.help.noClock": "Help: Villager RNG manipulation requires a 20 Hz clock", From ed979345d433eda13e085c2f059c19d000446291 Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 21 Nov 2024 14:40:01 -0500 Subject: [PATCH 39/78] made it auto-readjust --- .../clientcommands/mixin/rngevents/MerchantScreenMixin.java | 1 + src/main/resources/assets/clientcommands/lang/en_us.json | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java index 77720c472..5c29b55d7 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java @@ -76,6 +76,7 @@ private void onRender(CallbackInfo ci) { if (currentOfferTickIndex.isPresent()) { // we negate the currentOfferTickIndex as adjustment because in the case that our actual offers are found ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure.detailed", Configs.villagerAdjustment * 50, -currentOfferTickIndex.getAsInt()).withStyle(ChatFormatting.RED), 100); + Configs.villagerAdjustment -= -currentOfferTickIndex.getAsInt(); break a; } } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 8d6ca2d0c..ff72e4339 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -252,7 +252,7 @@ "commands.cvillager.crack.failed": "Failed to crack villager seed (found %d seeds), re-cracking...", "commands.cvillager.crack.success": "Villager RNG cracked: %d", "commands.cvillager.failure": "Got the incorrect trade with correction of %dms", - "commands.cvillager.failure.detailed": "Got the incorrect trade with correction of %dms (was %d ticks ahead)", + "commands.cvillager.failure.detailed": "Got the incorrect trade with correction of %dms (was %d ticks ahead); re-adjusting", "commands.cvillager.goalAdded": "Added goal successfully.", "commands.cvillager.help.day": "Help: Villager RNG manipulation is likely to break if it's not night-time", "commands.cvillager.help.noClock": "Help: Villager RNG manipulation requires a 20 Hz clock", From fa04bfd370e2dda4572aecd9e937867537a11565 Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 21 Nov 2024 16:03:23 -0500 Subject: [PATCH 40/78] i can negate this and make it easier to understand --- .../mixin/rngevents/MerchantScreenMixin.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java index 5c29b55d7..5ace23981 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java @@ -52,12 +52,12 @@ private void onRender(CallbackInfo ci) { VillagerCommand.Offer[] availableOffers = menu.getOffers().stream().map(VillagerCommand.Offer::new).toArray(VillagerCommand.Offer[]::new); List beforeOffers = VillagerCracker.surroundingOffers.getFirst(); List afterOffers = VillagerCracker.surroundingOffers.getSecond(); - OptionalInt currentOfferTickIndex = OptionalInt.empty(); - for (int i = beforeOffers.size() - 1; i >= 0; i--) { - VillagerCommand.Offer[] offers = beforeOffers.get(i); + OptionalInt ticksAhead = OptionalInt.empty(); + for (int i = 0; i < beforeOffers.size(); i++) { + VillagerCommand.Offer[] offers = beforeOffers.get(beforeOffers.size() - 1 - i); if (Arrays.equals(offers, availableOffers)) { // we need to adjust by -1 to get it to not be 0 for the last value in `beforeOffers` - currentOfferTickIndex = OptionalInt.of(-(beforeOffers.size() - 1 - i) - 1); + ticksAhead = OptionalInt.of(i + 1); break; } } @@ -65,18 +65,18 @@ private void onRender(CallbackInfo ci) { for (int i = 0; i < afterOffers.size(); i++) { VillagerCommand.Offer[] offers = afterOffers.get(i); if (Arrays.equals(offers, availableOffers)) { - if (currentOfferTickIndex.isEmpty() || Mth.abs(currentOfferTickIndex.getAsInt()) > i + 1) { + if (ticksAhead.isEmpty() || Mth.abs(ticksAhead.getAsInt()) > -(i + 1)) { // we need to adjust by 1 to get it to not be 0 for the first value in `afterOffers` - currentOfferTickIndex = OptionalInt.of(i + 1); + ticksAhead = OptionalInt.of(-(i + 1)); break; } } } - if (currentOfferTickIndex.isPresent()) { - // we negate the currentOfferTickIndex as adjustment because in the case that our actual offers are found - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure.detailed", Configs.villagerAdjustment * 50, -currentOfferTickIndex.getAsInt()).withStyle(ChatFormatting.RED), 100); - Configs.villagerAdjustment -= -currentOfferTickIndex.getAsInt(); + if (ticksAhead.isPresent()) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure.detailed", Configs.villagerAdjustment * 50, ticksAhead.getAsInt()).withStyle(ChatFormatting.RED), 100); + minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); + Configs.villagerAdjustment -= ticksAhead.getAsInt(); break a; } } From 43a46df8485ab7a61314df12fae1b9eada15c6a4 Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 21 Nov 2024 16:53:32 -0500 Subject: [PATCH 41/78] fixed string literal translations --- .../assets/clientcommands/lang/en_us.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index ff72e4339..12a8c0af5 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -244,22 +244,22 @@ "commands.cvar.list": "Available variables: %s", "commands.cvillager.alreadyBruteForcing": "Cannot brute-force villager RNG since your target villager is already brute forcing", - "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %d calls", - "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %d calls", + "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %s calls", + "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %s calls", "commands.cvillager.clock.cleared": "Your clock is cleared", - "commands.cvillager.clock.set": "Clock set to %d %d %d (%s)", + "commands.cvillager.clock.set": "Clock set to %s %s %s (%s)", "commands.cvillager.clock.set.cleared": "Your clock is now cleared", - "commands.cvillager.crack.failed": "Failed to crack villager seed (found %d seeds), re-cracking...", - "commands.cvillager.crack.success": "Villager RNG cracked: %d", - "commands.cvillager.failure": "Got the incorrect trade with correction of %dms", - "commands.cvillager.failure.detailed": "Got the incorrect trade with correction of %dms (was %d ticks ahead); re-adjusting", + "commands.cvillager.crack.failed": "Failed to crack villager seed (found %s seeds), re-cracking...", + "commands.cvillager.crack.success": "Villager RNG cracked: %s", + "commands.cvillager.failure": "Got the incorrect trade with correction of %sms", + "commands.cvillager.failure.detailed": "Got the incorrect trade with correction of %sms (was %s ticks ahead); re-adjusting", "commands.cvillager.goalAdded": "Added goal successfully.", "commands.cvillager.help.day": "Help: Villager RNG manipulation is likely to break if it's not night-time", "commands.cvillager.help.noClock": "Help: Villager RNG manipulation requires a 20 Hz clock", "commands.cvillager.help.tooSlow": "Help: Villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running much slower", "commands.cvillager.inSync": "Your villager's RNG is cracked", "commands.cvillager.listGoals.noGoals": "There are no villager goals", - "commands.cvillager.listGoals.success": "There are %d villager goals:", + "commands.cvillager.listGoals.success": "There are %s villager goals:", "commands.cvillager.listGoals.success.one": "There is 1 villager goal:", "commands.cvillager.noCrackedVillagerPresent": "There was no cracked villager available to use", "commands.cvillager.noProfession": "The targeted villager has no profession", @@ -272,11 +272,11 @@ "commands.cvillager.outOfSync.xpOrb": "Your villager's xp orb was incorrectly sized, re-cracking", "commands.cvillager.outOfSync.yes": "Your villager's yes sound was incorrectly pitched, re-cracking", "commands.cvillager.partiallyCracked": "Your villager's RNG is partially cracked (~83m seeds remain)", - "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %d, you only have %d goals", - "commands.cvillager.itemCountOutOfRange": "The specified item count range (%s) overlaps into an item count outside the maximum (%d)", + "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %s, you only have %s goals", + "commands.cvillager.itemCountOutOfRange": "The specified item count range (%s) overlaps into an item count outside the maximum (%s)", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", "commands.cvillager.resetCracker": "Successfully reset cracked villager RNG", - "commands.cvillager.success": "Got the correct trade with correction of %dms", + "commands.cvillager.success": "Got the correct trade with correction of %sms", "commands.cvillager.target.cleared": "Target entity cleared", "commands.cvillager.target.set": "Target entity set", From 15803a58bb918fa8b3ce2eee56b5d57c08a56bbf Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 21 Nov 2024 21:45:59 -0500 Subject: [PATCH 42/78] stuff idk --- .../earthcomputer/clientcommands/Configs.java | 2 +- .../features/VillagerCracker.java | 6 +- .../features/VillagerRngSimulator.java | 92 ++++++++++++++++--- .../clientcommands/interfaces/IVillager.java | 5 + .../commands/villager/VillagerMixin.java | 19 ++++ .../mixin/rngevents/MerchantScreenMixin.java | 66 +------------ .../assets/clientcommands/lang/en_us.json | 2 +- 7 files changed, 108 insertions(+), 84 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/Configs.java b/src/main/java/net/earthcomputer/clientcommands/Configs.java index e15b24431..f6a1af5b4 100644 --- a/src/main/java/net/earthcomputer/clientcommands/Configs.java +++ b/src/main/java/net/earthcomputer/clientcommands/Configs.java @@ -181,5 +181,5 @@ public static void setMaxVillagerBruteForceSimulationCalls(int maxVillagerBruteF } @Config(temporary = true) - public static int villagerAdjustment = 0; + public static int villagerAdjustmentTicks = 0; } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index d57817f0e..e413a564f 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -33,7 +33,7 @@ public class VillagerCracker { public static Pair, List> surroundingOffers = null; @Nullable private static Long lastServerTick = null; - private static boolean receivedClockRateWarning = false; + private static long lastClockRateWarning = 0; @Nullable public static Villager getVillager() { @@ -120,9 +120,9 @@ public static void onServerTick() { return; } - if (lastServerTick != null && now - lastServerTick > 80L && !receivedClockRateWarning) { + if (lastServerTick != null && now - lastServerTick > 80L && now - lastClockRateWarning >= 60_000L) { ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.tooSlow")); - receivedClockRateWarning = true; + lastClockRateWarning = now; } ((IVillager) targetVillager).clientcommands_onServerTick(); diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index c4230510d..28c62d41c 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -11,30 +11,31 @@ import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.minecraft.ChatFormatting; +import net.minecraft.client.Minecraft; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.VillagerTrades; -import net.minecraft.world.item.trading.ItemCost; import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.levelgen.LegacyRandomSource; import org.jetbrains.annotations.Nullable; import java.io.DataInputStream; import java.io.IOException; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.Objects; +import java.util.*; import java.util.function.Predicate; +import java.util.stream.Collectors; import java.util.stream.LongStream; public class VillagerRngSimulator { @@ -147,7 +148,7 @@ private void revertSimulatedTick() { } public boolean shouldInteractWithVillager() { - boolean shouldInteractWithVillager = totalCalls - callsAtStartOfBruteForce >= callsInBruteForce - Configs.villagerAdjustment * 2 && callsInBruteForce > 0; + boolean shouldInteractWithVillager = totalCalls - callsAtStartOfBruteForce >= callsInBruteForce - Configs.villagerAdjustmentTicks * 2 && callsInBruteForce > 0; if (shouldInteractWithVillager) { reset(); } @@ -174,7 +175,7 @@ private void simulateServerAiStep() { } public void updateProgressBar() { - ClientCommandHelper.updateOverlayProgressBar(Math.min(callsInBruteForce - Configs.villagerAdjustment * 2, totalCalls - callsAtStartOfBruteForce), callsInBruteForce - Configs.villagerAdjustment * 2, 50, 60); + ClientCommandHelper.updateOverlayProgressBar(Math.min(callsInBruteForce - Configs.villagerAdjustmentTicks * 2, totalCalls - callsAtStartOfBruteForce), callsInBruteForce - Configs.villagerAdjustmentTicks * 2, 50, 60); } @Nullable @@ -347,6 +348,8 @@ public void onNoSoundPlayed(float pitch, boolean fromGuiInteract) { if (pitch != simulatedPitch) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.no").withStyle(ChatFormatting.RED), 100); reset(); + } else { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); } } } @@ -362,6 +365,8 @@ public void onYesSoundPlayed(float pitch) { if (pitch != simulatedPitch) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.yes").withStyle(ChatFormatting.RED), 100); reset(); + } else { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); } } } @@ -375,17 +380,17 @@ public void onSplashSoundPlayed(float pitch) { totalCalls += 2; float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.4f + 1.0f; - if (pitch != simulatedPitch) { + if (pitch == simulatedPitch) { + int iterations = Mth.ceil(1.0f + EntityType.VILLAGER.getDimensions().width() * 20.0f); + totalCalls += iterations * 10; + random.advance(iterations * 10L); + simulateTick(); + + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); + } else { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.splash").withStyle(ChatFormatting.RED), 100); reset(); - return; } - - int iterations = Mth.ceil(1.0f + EntityType.VILLAGER.getDimensions().width() * 20.0f); - totalCalls += iterations * 10; - random.advance(iterations * 10L); - - simulateTick(); } } @@ -401,6 +406,8 @@ public void onXpOrbSpawned(int value) { if (value != simulatedValue) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.xpOrb").withStyle(ChatFormatting.RED), 100); reset(); + } else { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); } } } @@ -461,6 +468,61 @@ public Pair, List> genera return Pair.of(before, after); } + private int[] possibleTicksAhead(VillagerCommand.Offer[] targetOffers, List before, List after) { + List misses = new ArrayList<>(); + for (int i = 0; i < before.size(); i++) { + VillagerCommand.Offer[] offers = before.get(i); + if (Arrays.equals(offers, targetOffers)) { + // we need to adjust by 1 to get it to not be 0 for the last value in `beforeOffers` + misses.add((before.size() - 1 - i) + 1); + } + } + + for (int i = 0; i < after.size(); i++) { + VillagerCommand.Offer[] offers = after.get(i); + if (Arrays.equals(offers, targetOffers)) { + // we need to adjust by 1 to get it to not be 0 for the first value in `afterOffers` + misses.add(-(i + 1)); + } + } + return misses.stream().mapToInt(i -> i).toArray(); + } + + public void onGuiOpened(List availableOffersList, Villager villager) { + final LocalPlayer player = Minecraft.getInstance().player; + if (player.distanceTo(villager) > 2.0) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.distance").withStyle(ChatFormatting.RED), 100); + reset(); + return; + } + + if (VillagerCracker.targetOffer != null) { + if (availableOffersList.contains(VillagerCracker.targetOffer)) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.success", Configs.villagerAdjustmentTicks * 50).withStyle(ChatFormatting.GREEN), 100); + player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); + } else { + a: { + if (VillagerCracker.surroundingOffers != null) { + int[] possibleTicksAhead = possibleTicksAhead(availableOffersList.toArray(VillagerCommand.Offer[]::new), VillagerCracker.surroundingOffers.getFirst(), VillagerCracker.surroundingOffers.getSecond()); + + if (possibleTicksAhead.length > 0) { + int zeroIndex = Math.max(possibleTicksAhead.length - 1, Arrays.binarySearch(possibleTicksAhead, 0)); + int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex + 1]) <= Math.abs(possibleTicksAhead[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure.detailed", Configs.villagerAdjustmentTicks * 50, Arrays.toString(possibleTicksAhead), bestAdjustment).withStyle(ChatFormatting.RED), 100); + player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); + Configs.villagerAdjustmentTicks -= bestAdjustment; + break a; + } + } + + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure", Configs.villagerAdjustmentTicks * 50).withStyle(ChatFormatting.RED), 100); + player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); + } + } + VillagerCracker.targetOffer = null; + } + } + public long[] crackSeed() { if (!(80 <= ticksBetweenSounds && ticksBetweenSounds - 80 < LATTICES.length)) { return new long[0]; diff --git a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java index 6c10c0f19..b229290f7 100644 --- a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java +++ b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java @@ -1,7 +1,10 @@ package net.earthcomputer.clientcommands.interfaces; +import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; +import java.util.List; + public interface IVillager { VillagerRngSimulator clientcommands_getVillagerRngSimulator(); @@ -16,4 +19,6 @@ public interface IVillager { void clientcommands_onXpOrbSpawned(int value); void clientcommands_onServerTick(); + + void clientcommands_onGuiOpened(List list); } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index 18ba7be67..d060afa17 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -1,9 +1,19 @@ package net.earthcomputer.clientcommands.mixin.commands.villager; +import net.earthcomputer.clientcommands.Configs; +import net.earthcomputer.clientcommands.command.ClientCommandHelper; +import net.earthcomputer.clientcommands.command.VillagerCommand; +import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; +import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.inventory.MerchantScreen; +import net.minecraft.client.player.LocalPlayer; +import net.minecraft.network.chat.Component; +import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.util.Mth; import net.minecraft.world.InteractionHand; import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.EntityType; @@ -14,6 +24,10 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; +import java.util.Arrays; +import java.util.List; +import java.util.OptionalInt; + @Mixin(Villager.class) public abstract class VillagerMixin extends AbstractVillager implements IVillager { public VillagerMixin(EntityType entityType, Level level) { @@ -70,4 +84,9 @@ public void clientcommands_onServerTick() { public VillagerRngSimulator clientcommands_getVillagerRngSimulator() { return rng; } + + @Override + public void clientcommands_onGuiOpened(List availableOffersList) { + rng.onGuiOpened(availableOffersList, (Villager) (Object) this); + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java index 5ace23981..ed5092889 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java @@ -1,31 +1,19 @@ package net.earthcomputer.clientcommands.mixin.rngevents; -import net.earthcomputer.clientcommands.Configs; -import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.interfaces.IVillager; -import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.MerchantScreen; import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.MerchantMenu; -import net.minecraft.world.item.trading.ItemCost; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import java.util.Arrays; -import java.util.List; -import java.util.OptionalInt; - @Mixin(MerchantScreen.class) public abstract class MerchantScreenMixin extends AbstractContainerScreen { public MerchantScreenMixin(MerchantMenu menu, Inventory playerInventory, Component title) { @@ -35,58 +23,8 @@ public MerchantScreenMixin(MerchantMenu menu, Inventory playerInventory, Compone @Inject(method = "render", at = @At("HEAD")) private void onRender(CallbackInfo ci) { Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager != null) { - if (Minecraft.getInstance().player.distanceTo(targetVillager) > 2.0) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.distance").withStyle(ChatFormatting.RED), 100); - ((IVillager) targetVillager).clientcommands_getVillagerRngSimulator().reset(); - return; - } - - if (VillagerCracker.targetOffer != null) { - if (menu.getOffers().stream().map(offer -> new VillagerCommand.Offer(offer.getBaseCostA(), offer.getItemCostB().map(ItemCost::itemStack).orElse(null), offer.getResult())).anyMatch(offer -> offer.equals(VillagerCracker.targetOffer))) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.success", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.GREEN), 100); - minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); - } else { - a: { - if (VillagerCracker.surroundingOffers != null) { - VillagerCommand.Offer[] availableOffers = menu.getOffers().stream().map(VillagerCommand.Offer::new).toArray(VillagerCommand.Offer[]::new); - List beforeOffers = VillagerCracker.surroundingOffers.getFirst(); - List afterOffers = VillagerCracker.surroundingOffers.getSecond(); - OptionalInt ticksAhead = OptionalInt.empty(); - for (int i = 0; i < beforeOffers.size(); i++) { - VillagerCommand.Offer[] offers = beforeOffers.get(beforeOffers.size() - 1 - i); - if (Arrays.equals(offers, availableOffers)) { - // we need to adjust by -1 to get it to not be 0 for the last value in `beforeOffers` - ticksAhead = OptionalInt.of(i + 1); - break; - } - } - - for (int i = 0; i < afterOffers.size(); i++) { - VillagerCommand.Offer[] offers = afterOffers.get(i); - if (Arrays.equals(offers, availableOffers)) { - if (ticksAhead.isEmpty() || Mth.abs(ticksAhead.getAsInt()) > -(i + 1)) { - // we need to adjust by 1 to get it to not be 0 for the first value in `afterOffers` - ticksAhead = OptionalInt.of(-(i + 1)); - break; - } - } - } - - if (ticksAhead.isPresent()) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure.detailed", Configs.villagerAdjustment * 50, ticksAhead.getAsInt()).withStyle(ChatFormatting.RED), 100); - minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); - Configs.villagerAdjustment -= ticksAhead.getAsInt(); - break a; - } - } - - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure", Configs.villagerAdjustment * 50).withStyle(ChatFormatting.RED), 100); - minecraft.player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); - } - } - VillagerCracker.targetOffer = null; - } + if (targetVillager instanceof IVillager iVillager) { + iVillager.clientcommands_onGuiOpened(menu.getOffers().stream().map(VillagerCommand.Offer::new).toList()); } } } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 12a8c0af5..d6c051bb3 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -252,7 +252,7 @@ "commands.cvillager.crack.failed": "Failed to crack villager seed (found %s seeds), re-cracking...", "commands.cvillager.crack.success": "Villager RNG cracked: %s", "commands.cvillager.failure": "Got the incorrect trade with correction of %sms", - "commands.cvillager.failure.detailed": "Got the incorrect trade with correction of %sms (was %s ticks ahead); re-adjusting", + "commands.cvillager.failure.detailed": "Got the incorrect trade with correction of %sms (was one of %s ticks ahead); re-adjusting by %s ticks", "commands.cvillager.goalAdded": "Added goal successfully.", "commands.cvillager.help.day": "Help: Villager RNG manipulation is likely to break if it's not night-time", "commands.cvillager.help.noClock": "Help: Villager RNG manipulation requires a 20 Hz clock", From 623fee1e97f509f8330c9754a305f517d71946da Mon Sep 17 00:00:00 2001 From: RTTV Date: Fri, 22 Nov 2024 14:15:35 -0500 Subject: [PATCH 43/78] whoops --- gradle.properties | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 829d1ed78..89c47f8ed 100644 --- a/gradle.properties +++ b/gradle.properties @@ -19,7 +19,7 @@ org.gradle.jvmargs=-Xmx2G # Dependencies # also check this on https://fabricmc.net/develop/ - fabric_version=0.106.1+1.21.3 + fabric_version=0.109.0+1.21.3 clientarguments_version=1.10.1 betterconfig_version=2.1.2 seedfinding_core_version=1.200.1 @@ -27,3 +27,5 @@ org.gradle.jvmargs=-Xmx2G seedfinding_feature_version=1.171.9 seedfinding_seed_version=1.171.2 latticg_version=1.07 + + junit_version=5.11.3 From 2f6eff644a8617503b163a85a0157a1f414365c2 Mon Sep 17 00:00:00 2001 From: RTTV Date: Tue, 26 Nov 2024 16:24:57 -0500 Subject: [PATCH 44/78] whoopsie --- .../clientcommands/features/VillagerRngSimulator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 28c62d41c..f4ed774d2 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -507,7 +507,7 @@ public void onGuiOpened(List availableOffersList, Village if (possibleTicksAhead.length > 0) { int zeroIndex = Math.max(possibleTicksAhead.length - 1, Arrays.binarySearch(possibleTicksAhead, 0)); - int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex + 1]) <= Math.abs(possibleTicksAhead[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; + int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex]) > Math.abs(possibleTicksAhead[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure.detailed", Configs.villagerAdjustmentTicks * 50, Arrays.toString(possibleTicksAhead), bestAdjustment).withStyle(ChatFormatting.RED), 100); player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); Configs.villagerAdjustmentTicks -= bestAdjustment; From e534d05e8934beb0338b5e73cbd7998282fd87ce Mon Sep 17 00:00:00 2001 From: RTTV Date: Tue, 26 Nov 2024 16:25:38 -0500 Subject: [PATCH 45/78] whoopsie --- .../clientcommands/features/VillagerRngSimulator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index f4ed774d2..c1cc02feb 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -507,7 +507,7 @@ public void onGuiOpened(List availableOffersList, Village if (possibleTicksAhead.length > 0) { int zeroIndex = Math.max(possibleTicksAhead.length - 1, Arrays.binarySearch(possibleTicksAhead, 0)); - int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex]) > Math.abs(possibleTicksAhead[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; + int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex]) > Math.abs(possibleTicksA head[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure.detailed", Configs.villagerAdjustmentTicks * 50, Arrays.toString(possibleTicksAhead), bestAdjustment).withStyle(ChatFormatting.RED), 100); player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); Configs.villagerAdjustmentTicks -= bestAdjustment; From 0ea73a97a411f00f3d4efefc6fa336d52e878fbc Mon Sep 17 00:00:00 2001 From: RTTV Date: Tue, 26 Nov 2024 16:26:00 -0500 Subject: [PATCH 46/78] beruh --- .../clientcommands/features/VillagerRngSimulator.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index c1cc02feb..f4ed774d2 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -507,7 +507,7 @@ public void onGuiOpened(List availableOffersList, Village if (possibleTicksAhead.length > 0) { int zeroIndex = Math.max(possibleTicksAhead.length - 1, Arrays.binarySearch(possibleTicksAhead, 0)); - int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex]) > Math.abs(possibleTicksA head[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; + int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex]) > Math.abs(possibleTicksAhead[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure.detailed", Configs.villagerAdjustmentTicks * 50, Arrays.toString(possibleTicksAhead), bestAdjustment).withStyle(ChatFormatting.RED), 100); player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); Configs.villagerAdjustmentTicks -= bestAdjustment; From 69e04fd3c4436e309d5f2da18a58a8600995c394 Mon Sep 17 00:00:00 2001 From: RTTV Date: Tue, 26 Nov 2024 16:27:36 -0500 Subject: [PATCH 47/78] dw i moved it for ya --- .../clientcommands/features/VillagerCracker.java | 5 +++-- .../mixin/rngevents/ClientPacketListenerMixin.java | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index e413a564f..b5ca4bc56 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -12,6 +12,7 @@ import net.minecraft.network.protocol.game.ClientboundSoundPacket; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; @@ -88,9 +89,9 @@ public static void setClockPos(@Nullable GlobalPos pos) { VillagerCracker.clockPos = pos; } - public static void onSoundEventPlayed(ClientboundSoundPacket packet) { + public static void onSoundEventPlayed(ClientboundSoundPacket packet, Vec3 pos) { Villager targetVillager = getVillager(); - if (targetVillager == null || getClockPos() == null) { + if (targetVillager == null || getClockPos() == null || pos.distanceToSqr(targetVillager.position()) <= 0.1f) { return; } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java index 4ccc39150..d5a1a7889 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java @@ -37,8 +37,8 @@ private void onSendCommand(String command, CallbackInfo ci) { @Inject(method = "handleSoundEvent", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) private void onHandleSoundEvent(ClientboundSoundPacket packet, CallbackInfo ci) { Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager != null && new Vec3(packet.getX(), packet.getY(), packet.getZ()).distanceToSqr(targetVillager.position()) <= 0.1f) { - VillagerCracker.onSoundEventPlayed(packet); + if (targetVillager != null) { + VillagerCracker.onSoundEventPlayed(packet, new Vec3(packet.getX(), packet.getY(), packet.getZ())); } } From 12b4039b9c1d6461019e2e2b0e3055063a9a495c Mon Sep 17 00:00:00 2001 From: RTTV Date: Tue, 26 Nov 2024 16:29:12 -0500 Subject: [PATCH 48/78] bruh --- .../clientcommands/features/VillagerRngSimulator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index f4ed774d2..52a118d04 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -507,7 +507,8 @@ public void onGuiOpened(List availableOffersList, Village if (possibleTicksAhead.length > 0) { int zeroIndex = Math.max(possibleTicksAhead.length - 1, Arrays.binarySearch(possibleTicksAhead, 0)); - int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex]) > Math.abs(possibleTicksAhead[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; + // we go less than or equal to because the default adjustment should be to wait an amount of time, rather than to decrease it, since typically people don't have negative ping + int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex]) <= Math.abs(possibleTicksAhead[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure.detailed", Configs.villagerAdjustmentTicks * 50, Arrays.toString(possibleTicksAhead), bestAdjustment).withStyle(ChatFormatting.RED), 100); player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); Configs.villagerAdjustmentTicks -= bestAdjustment; From e50cc27c38349fbab1b7c52e02fffa7f5a88d61b Mon Sep 17 00:00:00 2001 From: joe Date: Wed, 27 Nov 2024 04:17:19 +0000 Subject: [PATCH 49/78] Cleanup and fixes, extract stuff out of fishing cracker to use for villager cracking --- .../earthcomputer/clientcommands/Configs.java | 11 +- .../command/VillagerCommand.java | 24 +- .../features/FishingCracker.java | 244 +++--------------- .../features/VillagerCracker.java | 84 ++++-- .../features/VillagerRngSimulator.java | 171 ++++++------ .../commands/villager/VillagerMixin.java | 59 ++--- .../clientcommands/util/CUtil.java | 57 ++++ .../clientcommands/util/CombinedMedianEM.java | 153 +++++++++++ .../assets/clientcommands/lang/en_us.json | 15 +- 9 files changed, 457 insertions(+), 361 deletions(-) create mode 100644 src/main/java/net/earthcomputer/clientcommands/util/CombinedMedianEM.java diff --git a/src/main/java/net/earthcomputer/clientcommands/Configs.java b/src/main/java/net/earthcomputer/clientcommands/Configs.java index f6a1af5b4..e31d84f75 100644 --- a/src/main/java/net/earthcomputer/clientcommands/Configs.java +++ b/src/main/java/net/earthcomputer/clientcommands/Configs.java @@ -174,12 +174,9 @@ public enum PacketDumpMethod { @Config public static int maximumPacketFieldDepth = 10; - @Config(temporary = true, setter = @Config.Setter("setMaxVillagerBruteForceSimulationCalls")) - public static int maxVillagerBruteForceSimulationCalls = 12000; - public static void setMaxVillagerBruteForceSimulationCalls(int maxVillagerBruteForceSimulationCalls) { - Configs.maxVillagerBruteForceSimulationCalls = Mth.clamp(maxVillagerBruteForceSimulationCalls, 0, 1_000_000); + @Config(temporary = true, setter = @Config.Setter("setMaxVillagerBruteForceSimulationTicks")) + public static int maxVillagerBruteForceSimulationTicks = 12000; + public static void setMaxVillagerBruteForceSimulationTicks(int maxVillagerBruteForceSimulationTicks) { + Configs.maxVillagerBruteForceSimulationTicks = Mth.clamp(maxVillagerBruteForceSimulationTicks, 0, 1_000_000); } - - @Config(temporary = true) - public static int villagerAdjustmentTicks = 0; } diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 63673b7d5..2f3e461f5 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -6,10 +6,8 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import com.mojang.datafixers.util.Pair; import dev.xpple.clientarguments.arguments.CRangeArgument; import net.earthcomputer.clientcommands.Configs; -import net.earthcomputer.clientcommands.features.FishingCracker; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; @@ -37,7 +35,6 @@ import org.jetbrains.annotations.Nullable; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -57,7 +54,7 @@ public class VillagerCommand { private static final SimpleCommandExceptionType NO_PROFESSION_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.noProfession")); private static final SimpleCommandExceptionType NOT_LEVEL_1_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notLevel1")); private static final SimpleCommandExceptionType NO_GOALS_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.listGoals.noGoals")); - private static final SimpleCommandExceptionType ALREADY_BRUTE_FORCING_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.alreadyBruteForcing")); + private static final SimpleCommandExceptionType ALREADY_RUNNING_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.alreadyRunning")); private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX_EXCEPTION = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); private static final Dynamic2CommandExceptionType ITEM_QUANTITY_OUT_OF_RANGE_EXCEPTION = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.itemCountOutOfRange", a, b)); private static final List goals = new ArrayList<>(); @@ -222,8 +219,8 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { throw NO_PROFESSION_EXCEPTION.create(); } - if (iVillager.clientcommands_getVillagerRngSimulator().isCracking()) { - throw ALREADY_BRUTE_FORCING_EXCEPTION.create(); + if (VillagerCracker.isRunning()) { + throw ALREADY_RUNNING_EXCEPTION.create(); } int currentLevel = targetVillager.getVillagerData().getLevel(); @@ -234,14 +231,14 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { int crackedLevel = levelUp ? currentLevel + 1 : currentLevel; VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(crackedLevel, new VillagerTrades.ItemListing[0]); - int adjustmentTicks = 1 + (levelUp ? -40 : 0); - VillagerRngSimulator.BruteForceResult result = iVillager.clientcommands_getVillagerRngSimulator().bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationCalls, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer))); + int adjustmentTicks = levelUp ? -40 : 0; + VillagerRngSimulator.BruteForceResult result = iVillager.clientcommands_getVillagerRngSimulator().bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationTicks, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer))); if (result == null) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationCalls).withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationTicks).withStyle(ChatFormatting.RED), 100); return Command.SINGLE_SUCCESS; } - Pair, List> surroundingOffers = iVillager.clientcommands_getVillagerRngSimulator().generateSurroundingOffers(listings, result.ticksPassed(), 1000); - int calls = result.callsAtInteraction() + adjustmentTicks * 2; + VillagerRngSimulator.SurroundingOffers surroundingOffers = iVillager.clientcommands_getVillagerRngSimulator().generateSurroundingOffers(listings, result.ticksPassed(), 1000); + int ticks = result.ticksPassed() + adjustmentTicks; Offer offer = result.offer(); String price; if (offer.second() == null) { @@ -249,10 +246,11 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { } else { price = displayText(offer.first(), false) + " + " + displayText(offer.second(), false); } - ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", displayText(offer.result(), false), price, calls).withStyle(ChatFormatting.GREEN)); + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", displayText(offer.result(), false), price, ticks).withStyle(ChatFormatting.GREEN)); VillagerCracker.targetOffer = offer; VillagerCracker.surroundingOffers = surroundingOffers; - iVillager.clientcommands_getVillagerRngSimulator().setCallsUntilToggleGui(calls); + VillagerCracker.hasClickedVillager = false; + iVillager.clientcommands_getVillagerRngSimulator().setTicksUntilBruteForceInteract(ticks); return Command.SINGLE_SUCCESS; } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java index 6cc75e695..a534aae39 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java @@ -11,6 +11,8 @@ import com.seedfinding.mcfeature.loot.entry.ItemEntry; import com.seedfinding.mcfeature.loot.entry.LootEntry; import com.seedfinding.mcfeature.loot.entry.TableEntry; +import it.unimi.dsi.fastutil.doubles.DoubleArrayList; +import it.unimi.dsi.fastutil.doubles.DoubleList; import net.earthcomputer.clientcommands.Configs; import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.PingCommand; @@ -22,11 +24,11 @@ import net.earthcomputer.clientcommands.task.LongTask; import net.earthcomputer.clientcommands.task.TaskManager; import net.earthcomputer.clientcommands.util.CUtil; +import net.earthcomputer.clientcommands.util.CombinedMedianEM; import net.earthcomputer.clientcommands.util.SeedfindingUtil; import net.minecraft.ChatFormatting; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; -import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.client.multiplayer.MultiPlayerGameMode; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; @@ -73,9 +75,6 @@ import java.util.OptionalLong; import java.util.Set; import java.util.UUID; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; import java.util.function.Consumer; import java.util.stream.Collectors; import java.util.stream.IntStream; @@ -106,7 +105,7 @@ public class FishingCracker { private static int serverMspt = 50; private static volatile int averageTimeToEndOfTick = 0; private static volatile int magicMillisecondsCorrection = -100; - private static final ScheduledExecutorService DELAY_EXECUTOR = Executors.newSingleThreadScheduledExecutor(); + private static final CombinedMedianEM combinedMedianEM = new CombinedMedianEM(); // state public static volatile State state = State.NOT_MANIPULATING; @@ -550,24 +549,24 @@ private static void processExperienceOrbSpawn(double x, double y, double z, int } if (!indices.isEmpty()) { - if (CombinedMedianEM.data.size() >= 10) { - CombinedMedianEM.data.removeFirst(); + if (combinedMedianEM.data.size() >= 10) { + combinedMedianEM.data.removeFirst(); } - ArrayList sample = new ArrayList<>(); + DoubleList sample = new DoubleArrayList(); for (int index : indices) { sample.add((double) (index * serverMspt) + magicMillisecondsCorrection); } - CombinedMedianEM.data.add(sample); + combinedMedianEM.data.add(sample); - CombinedMedianEM.begintime = magicMillisecondsCorrection - serverMspt / 2 - (expectedCatches.length / 2) * serverMspt; - CombinedMedianEM.endtime = magicMillisecondsCorrection + serverMspt / 2 + (expectedCatches.length / 2) * serverMspt; - CombinedMedianEM.width = serverMspt; - CombinedMedianEM.run(); - magicMillisecondsCorrection = (int) Math.round(CombinedMedianEM.mu); + combinedMedianEM.update(serverMspt, expectedCatches.length / 2, expectedCatches.length / 2); + magicMillisecondsCorrection = (int) Math.round(combinedMedianEM.getResult()); } } private static void onTimeSync() { + LocalPlayer player = Minecraft.getInstance().player; + assert player != null; + long time = System.nanoTime(); //noinspection SuspiciousSystemArraycopy System.arraycopy(timeSyncTimes, 1, timeSyncTimes, 0, timeSyncTimes.length - 1); @@ -589,50 +588,39 @@ private static void onTimeSync() { int timeToStartOfTick = serverMspt - averageTimeToEndOfTick; int delay = (totalTicksToWait - estimatedTicksElapsed) * serverMspt - magicMillisecondsCorrection - PingCommand.getLocalPing() - timeToStartOfTick + serverMspt / 2; long targetTime = (delay) * 1000000L + System.nanoTime(); - DELAY_EXECUTOR.schedule(() -> { - if (!Configs.getFishingManipulation().isEnabled() || state != State.ASYNC_WAITING_FOR_FISH) { - return; - } - LocalPlayer oldPlayer = Minecraft.getInstance().player; - if (oldPlayer != null) { - ClientPacketListener packetListener = oldPlayer.connection; - while (System.nanoTime() - targetTime < 0) { - if (state != State.ASYNC_WAITING_FOR_FISH) { - return; - } - } - FishingHook oldFishingHook = oldPlayer.fishing; - packetListener.send(new ServerboundUseItemPacket(InteractionHand.MAIN_HAND, 0, oldPlayer.getYRot(), oldPlayer.getXRot())); - synchronized (STATE_LOCK) { - state = State.WAITING_FOR_ITEM; - } - Minecraft.getInstance().schedule(() -> { - LocalPlayer player = Minecraft.getInstance().player; - if (player != null) { - ItemStack oldStack = player.getMainHandItem(); - - // If the player interaction packet gets handled before the next tick, - // then the fish hook would be null and the client would act as if the fishing rod is extending. - // Temporarily set to the previous fishing hook to fix this. - expectedFishingRodUses++; - FishingHook prevFishingHook = player.fishing; - player.fishing = oldFishingHook; - InteractionResult result = oldStack.use(player.level(), player, InteractionHand.MAIN_HAND); - player.fishing = prevFishingHook; - - if (result instanceof InteractionResult.Success successResult) { - if (oldStack != successResult.heldItemTransformedTo()) { - player.setItemInHand(InteractionHand.MAIN_HAND, successResult.heldItemTransformedTo()); - } - if (successResult.swingSource() == InteractionResult.SwingSource.CLIENT) { - player.swing(InteractionHand.MAIN_HAND); - } + FishingHook[] oldFishingHook = {null}; + CUtil.sendAtPreciseTime( + targetTime, + new ServerboundUseItemPacket(InteractionHand.MAIN_HAND, 0, player.getYRot(), player.getXRot()), + () -> { + oldFishingHook[0] = player.fishing; + return Configs.getFishingManipulation().isEnabled() && state == State.ASYNC_WAITING_FOR_FISH; + }, + () -> { + if (player == Minecraft.getInstance().player) { + ItemStack oldStack = player.getMainHandItem(); + + // If the player interaction packet gets handled before the next tick, + // then the fish hook would be null and the client would act as if the fishing rod is extending. + // Temporarily set to the previous fishing hook to fix this. + expectedFishingRodUses++; + FishingHook prevFishingHook = player.fishing; + player.fishing = oldFishingHook[0]; + InteractionResult result = oldStack.use(player.level(), player, InteractionHand.MAIN_HAND); + player.fishing = prevFishingHook; + + if (result instanceof InteractionResult.Success successResult) { + if (oldStack != successResult.heldItemTransformedTo()) { + player.setItemInHand(InteractionHand.MAIN_HAND, successResult.heldItemTransformedTo()); + } + if (successResult.swingSource() == InteractionResult.SwingSource.CLIENT) { + player.swing(InteractionHand.MAIN_HAND); } - //networkHandler.sendPacket(new PlayerInteractItemC2SPacket(Hand.MAIN_HAND)); } - }); + //networkHandler.sendPacket(new PlayerInteractItemC2SPacket(Hand.MAIN_HAND)); + } } - }, Math.max(0, delay - 100), TimeUnit.MILLISECONDS); + ); } } } @@ -730,152 +718,6 @@ public String toString() { // endregion - // region NETWORK DELAY ESTIMATION - - /** - * Taken from: https://gist.github.com/pseudogravity/294f12225c18bf319e4c1923dd664bd5 - * - * @author MC (PseudoGravity) - */ - private static class CombinedMedianEM { - - // a list of samples - // each sample is actually a list of points - // for each interval, convert it to a point by taking the median value - // or... break the 50ms intervals into 2 25ms intervals for better accuracy - static ArrayList> data = new ArrayList<>(); - - // width of the intervals - static double width = 50; - - // width of time window considered - // all of the data points for all samples are within this window - static int begintime = -1000; - static int endtime = 1000; - - // three parameters and 2 constraints - static double packetlossrate = 0.2; - static double maxpacketlossrate = 0.5; - static double minpacketlossrate = 0.01; - static double mu = 0.0; - static double sigma = 500; - static double maxsigma = 1000; - static double minsigma = 10; - - public static void run() { - ArrayList droprate = new ArrayList<>(); - - for (ArrayList sample : data) { - droprate.add(sample.size() * width / (endtime - begintime)); - } - - ArrayList times = new ArrayList<>(); - for (int i = begintime; i <= endtime; i += 10) { - times.add(i * 1.0); - } - - double besttime = 0; - double bestscore = Double.MAX_VALUE; - - for (double time : times) { - // find score for each option for time - double score = 0; - for (int i = 0; i < data.size(); i++) { - // for each sample, find the point which adds the least to the score - ArrayList sample = data.get(i); - double lambda = droprate.get(i) / width; - double bestsubscore = Double.MAX_VALUE; - for (Double x : sample) { - double absdev = Math.abs(x - time); - absdev = (1 - Math.exp(-lambda * absdev)) / lambda; // further curbing outlier effects - if (absdev < bestsubscore) { - bestsubscore = absdev; - } - } - score += bestsubscore; - } - if (score < bestscore) { - bestscore = score; - besttime = time; - } - } - - mu = besttime; - sigma = bestscore / data.size(); - sigma = Math.max(Math.min(sigma, maxsigma), minsigma); - - for (int repeat = 0; repeat < 1; repeat++) { - // E step - // calculate weights (and classifications) - var masses = new ArrayList>(); - for (int i = 0; i < data.size(); i++) { - - ArrayList sample = data.get(i); - - // process each sample - double sum = 0; - for (double x : sample) { - sum += mass(x); - } - double pXandNorm = Math.min(sum, 1) * (1 - packetlossrate); // cap at 1 - - double pXandUnif = droprate.get(i) * packetlossrate; - - double pNorm = pXandNorm / (pXandNorm + pXandUnif); - - ArrayList mass = new ArrayList<>(); - for (double x : sample) { - mass.add(mass(x) / sum * pNorm); - } - - masses.add(mass); - } - - // M step - // compute new best estimate for parameters - double weightedsum = 0; - double sumofweights = 0; - for (int i = 0; i < data.size(); i++) { - ArrayList sample = data.get(i); - ArrayList mass = masses.get(i); - for (int j = 0; j < sample.size(); j++) { - weightedsum += sample.get(j) * mass.get(j); - sumofweights += mass.get(j); - } - } - double muNext = weightedsum / sumofweights; - - double weightedsumofsquaredeviations = 0; - for (int i = 0; i < data.size(); i++) { - ArrayList sample = data.get(i); - ArrayList mass = masses.get(i); - for (int j = 0; j < sample.size(); j++) { - weightedsumofsquaredeviations += Math.pow(sample.get(j) - muNext, 2) * mass.get(j); - } - } - double sigmaNext = Math.sqrt(weightedsumofsquaredeviations / sumofweights); - sigmaNext = Math.max(Math.min(sigmaNext, maxsigma), minsigma); - - double packetlossrateNext = (data.size() - sumofweights) / data.size(); - packetlossrateNext = Math.max(Math.min(packetlossrateNext, maxpacketlossrate), minpacketlossrate); - - mu = muNext; - sigma = sigmaNext; - packetlossrate = packetlossrateNext; - } - } - - public static double mass(double x) { - // should be cdf(x+width/2)-cdf(x-width/2) but is simplified to pdf(x)*width and - // capped at 1 - // to avoid pesky erf() functions - double pdf = 1 / (sigma * Math.sqrt(2 * Math.PI)) * Math.exp(-Math.pow((x - mu) / sigma, 2) / 2); - return Math.min(pdf * width, 1); - } - } - - // endregion - // region FISHING BOBBER SIMULATION private static class SimulatedFishingBobber { diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index b5ca4bc56..3ca290f2d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -1,22 +1,26 @@ package net.earthcomputer.clientcommands.features; -import com.mojang.datafixers.util.Pair; import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; +import net.earthcomputer.clientcommands.event.ClientConnectionEvents; +import net.earthcomputer.clientcommands.event.MoreClientEvents; import net.earthcomputer.clientcommands.interfaces.IVillager; +import net.earthcomputer.clientcommands.util.CombinedMedianEM; +import net.minecraft.SharedConstants; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.core.GlobalPos; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.phys.Vec3; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; -import java.util.List; import java.util.UUID; public class VillagerCracker { @@ -29,12 +33,25 @@ public class VillagerCracker { private static WeakReference cachedVillager = null; @Nullable private static GlobalPos clockPos = null; + private static boolean isNewClock; @Nullable public static VillagerCommand.Offer targetOffer = null; - public static Pair, List> surroundingOffers = null; - @Nullable - private static Long lastServerTick = null; + public static VillagerRngSimulator.SurroundingOffers surroundingOffers = null; + private static int clockTicksSinceLastTimeSync = 0; private static long lastClockRateWarning = 0; + public static boolean hasClickedVillager = false; + + private static long lastTimeSyncTime; + public static int serverMspt = SharedConstants.MILLIS_PER_TICK; + public static int magicMillisecondCorrection = 25; + public static int maxTicksBefore = 10; + public static int maxTicksAfter = 10; + public static final CombinedMedianEM combinedMedianEM = new CombinedMedianEM(); + + static { + ClientConnectionEvents.DISCONNECT.register(VillagerCracker::stopRunning); + MoreClientEvents.TIME_SYNC.register(packet -> onTimeSync()); + } @Nullable public static Villager getVillager() { @@ -51,7 +68,7 @@ public static Villager getVillager() { ClientLevel level = Minecraft.getInstance().level; if (level != null) { for (Entity entity : level.entitiesForRendering()) { - if (entity.getUUID() == villagerUuid && entity instanceof Villager villager) { + if (villagerUuid.equals(entity.getUUID()) && entity instanceof Villager villager) { cachedVillager = new WeakReference<>(villager); return villager; } @@ -87,19 +104,26 @@ public static void setTargetVillager(@Nullable Villager villager) { public static void setClockPos(@Nullable GlobalPos pos) { VillagerCracker.clockPos = pos; + if (pos != null) { + isNewClock = true; + } } public static void onSoundEventPlayed(ClientboundSoundPacket packet, Vec3 pos) { Villager targetVillager = getVillager(); - if (targetVillager == null || getClockPos() == null || pos.distanceToSqr(targetVillager.position()) <= 0.1f) { + if (targetVillager == null || getClockPos() == null || pos.distanceToSqr(targetVillager.position()) > 0.1f) { return; } - switch (packet.getSound().value().location().toString()) { - case "minecraft:entity.villager.ambient", "minecraft:entity.villager.trade" -> ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(packet.getPitch()); - case "minecraft:entity.villager.no" -> ((IVillager) targetVillager).clientcommands_onNoSoundPlayed(packet.getPitch()); - case "minecraft:entity.villager.yes" -> ((IVillager) targetVillager).clientcommands_onYesSoundPlayed(packet.getPitch()); - case "minecraft:entity.generic.splash" -> ((IVillager) targetVillager).clientcommands_onSplashSoundPlayed(packet.getPitch()); + SoundEvent soundEvent = packet.getSound().value(); + if (soundEvent == SoundEvents.VILLAGER_AMBIENT || soundEvent == SoundEvents.VILLAGER_TRADE) { + ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(packet.getPitch()); + } else if (soundEvent == SoundEvents.VILLAGER_NO) { + ((IVillager) targetVillager).clientcommands_onNoSoundPlayed(packet.getPitch()); + } else if (soundEvent == SoundEvents.VILLAGER_YES) { + ((IVillager) targetVillager).clientcommands_onYesSoundPlayed(packet.getPitch()); + } else if (soundEvent == SoundEvents.GENERIC_SPLASH) { + ((IVillager) targetVillager).clientcommands_onSplashSoundPlayed(packet.getPitch()); } } @@ -112,22 +136,42 @@ public static void onXpOrbSpawned(ClientboundAddExperienceOrbPacket packet) { ((IVillager) targetVillager).clientcommands_onXpOrbSpawned(packet.getValue()); } + private static void onTimeSync() { + long now = System.nanoTime(); + + if (getVillager() != null && clockPos != null && !isNewClock && clockTicksSinceLastTimeSync != 20) { + if (now - lastClockRateWarning >= 60_000_000_000L) { + if (clockTicksSinceLastTimeSync < 20) { + ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.tooSlow")); + } else { + ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.tooFast")); + } + lastClockRateWarning = now; + } + } + isNewClock = false; + clockTicksSinceLastTimeSync = 0; + + serverMspt = (3 * serverMspt + (int) ((now - lastTimeSyncTime) / 20_000_000)) / 4; + lastTimeSyncTime = now; + } + public static void onServerTick() { - long now = System.currentTimeMillis(); + clockTicksSinceLastTimeSync++; Villager targetVillager = getVillager(); if (targetVillager == null) { - lastServerTick = now; return; } - if (lastServerTick != null && now - lastServerTick > 80L && now - lastClockRateWarning >= 60_000L) { - ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.tooSlow")); - lastClockRateWarning = now; - } - ((IVillager) targetVillager).clientcommands_onServerTick(); + } + + public static boolean isRunning() { + return targetOffer != null; + } - lastServerTick = now; + public static void stopRunning() { + targetOffer = null; } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 52a118d04..ff345f4d3 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -1,13 +1,15 @@ package net.earthcomputer.clientcommands.features; -import com.mojang.datafixers.util.Pair; import com.seedfinding.latticg.math.component.BigFraction; import com.seedfinding.latticg.math.component.BigMatrix; import com.seedfinding.latticg.math.component.BigVector; import com.seedfinding.latticg.math.lattice.enumerate.EnumerateRt; import com.seedfinding.latticg.math.optimize.Optimize; import com.seedfinding.mcseed.rand.JRand; -import net.earthcomputer.clientcommands.Configs; +import it.unimi.dsi.fastutil.doubles.DoubleArrayList; +import it.unimi.dsi.fastutil.doubles.DoubleList; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.minecraft.ChatFormatting; @@ -29,13 +31,13 @@ import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.levelgen.LegacyRandomSource; +import org.apache.commons.lang3.ArrayUtils; import org.jetbrains.annotations.Nullable; import java.io.DataInputStream; import java.io.IOException; import java.util.*; import java.util.function.Predicate; -import java.util.stream.Collectors; import java.util.stream.LongStream; public class VillagerRngSimulator { @@ -43,22 +45,18 @@ public class VillagerRngSimulator { private static final BigMatrix[] INVERSE_LATTICES; private static final BigVector[] OFFSETS; - @Nullable private JRand random; private long prevRandomSeed = 0; private int ambientSoundTime = -80; private int prevAmbientSoundTime = -80; private boolean madeSound = false; private int totalAmbientSounds = 0; - private int callsAtStartOfBruteForce = 0; - private int callsInBruteForce = 0; - private int totalCalls = 0; - private int prevTotalCalls = 0; + private int tickCount = 0; + private int totalTicksInBruteForce = 0; private float firstPitch = Float.NaN; private int ticksBetweenSounds = 0; private float secondPitch = Float.NaN; - @Nullable - private long[] seedsFromTwoPitches = null; + private long @Nullable [] seedsFromTwoPitches = null; static { try { @@ -116,8 +114,6 @@ public VillagerRngSimulator copy() { that.prevAmbientSoundTime = this.prevAmbientSoundTime; that.madeSound = this.madeSound; that.totalAmbientSounds = this.totalAmbientSounds; - that.totalCalls = this.totalCalls; - that.prevTotalCalls = this.prevTotalCalls; return that; } @@ -131,37 +127,33 @@ public void simulateTick() { prevRandomSeed = random.getSeed(); prevAmbientSoundTime = ambientSoundTime; - prevTotalCalls = totalCalls; simulateBaseTick(); simulateServerAiStep(); - if (callsInBruteForce > 0) { + tickCount++; + + if (totalTicksInBruteForce > 0) { + // TODO: extract outside of simulateTick updateProgressBar(); } } - private void revertSimulatedTick() { + private void untick() { random.setSeed(prevRandomSeed, false); ambientSoundTime = prevAmbientSoundTime; - totalCalls = prevTotalCalls; + tickCount--; } - public boolean shouldInteractWithVillager() { - boolean shouldInteractWithVillager = totalCalls - callsAtStartOfBruteForce >= callsInBruteForce - Configs.villagerAdjustmentTicks * 2 && callsInBruteForce > 0; - if (shouldInteractWithVillager) { - reset(); - } - return shouldInteractWithVillager; + public int getTicksRemaining() { + return totalTicksInBruteForce - tickCount; } private void simulateBaseTick() { // we have the server receiving ambient noise tell us if we have to do this to increment the random, this is so that our ambient sound time is synced up. - totalCalls += 1; if (random.nextInt(1000) < ambientSoundTime++ && totalAmbientSounds > 0) { random.nextFloat(); random.nextFloat(); - totalCalls += 2; ambientSoundTime = -80; madeSound = true; } else { @@ -171,11 +163,10 @@ private void simulateBaseTick() { private void simulateServerAiStep() { random.nextInt(100); - totalCalls += 1; } public void updateProgressBar() { - ClientCommandHelper.updateOverlayProgressBar(Math.min(callsInBruteForce - Configs.villagerAdjustmentTicks * 2, totalCalls - callsAtStartOfBruteForce), callsInBruteForce - Configs.villagerAdjustmentTicks * 2, 50, 60); + ClientCommandHelper.updateOverlayProgressBar(tickCount, totalTicksInBruteForce, 50, 60); } @Nullable @@ -224,13 +215,9 @@ public VillagerCommand.Offer[] generateOffers(VillagerTrades.ItemListing[] listi return offers; } - public void setCallsUntilToggleGui(int calls) { - callsAtStartOfBruteForce = totalCalls; - callsInBruteForce = calls; - } - - public int getTotalCalls() { - return totalCalls; + public void setTicksUntilBruteForceInteract(int ticks) { + tickCount = 0; + totalTicksInBruteForce = ticks; } public CrackedState getCrackedState() { @@ -241,19 +228,13 @@ public CrackedState getCrackedState() { return CrackedState.CRACKED; } - public boolean isCracking() { - return callsInBruteForce > 0; - } - public void reset() { random = null; prevRandomSeed = 0; prevAmbientSoundTime = 0; - prevTotalCalls = 0; totalAmbientSounds = 0; - totalCalls = 0; - callsAtStartOfBruteForce = 0; - callsInBruteForce = 0; + tickCount = 0; + totalTicksInBruteForce = 0; firstPitch = Float.NaN; ticksBetweenSounds = 0; secondPitch = Float.NaN; @@ -340,7 +321,6 @@ public void onNoSoundPlayed(float pitch, boolean fromGuiInteract) { // played both when interacting with a villager without a profession and when using the villager gui if (random != null) { - totalCalls += 2; if (fromGuiInteract) { ambientSoundTime = -80; } @@ -359,7 +339,6 @@ public void onYesSoundPlayed(float pitch) { // played when using the villager gui if (random != null) { - totalCalls += 2; ambientSoundTime = -80; float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; if (pitch != simulatedPitch) { @@ -376,13 +355,11 @@ public void onSplashSoundPlayed(float pitch) { if (random != null) { // simulateTick() was already called for this tick assuming no splash happened, so revert it and rerun it with the splash - revertSimulatedTick(); + untick(); - totalCalls += 2; float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.4f + 1.0f; if (pitch == simulatedPitch) { int iterations = Mth.ceil(1.0f + EntityType.VILLAGER.getDimensions().width() * 20.0f); - totalCalls += iterations * 10; random.advance(iterations * 10L); simulateTick(); @@ -398,7 +375,6 @@ public void onXpOrbSpawned(int value) { // the last received action before the next tick's clock if (random != null) { - totalCalls += 1; ambientSoundTime = -80; int simulatedValue = 3 + this.random.nextInt(4); boolean leveledUp = value > 3 + 3; @@ -413,11 +389,10 @@ public void onXpOrbSpawned(int value) { } @Nullable - public BruteForceResult bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxCalls, Predicate predicate) { + public BruteForceResult bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxTicks, Predicate predicate) { Villager targetVillager = VillagerCracker.getVillager(); if (targetVillager != null && getCrackedState().isCracked()) { VillagerRngSimulator rng = this.copy(); - int startingCalls = rng.getTotalCalls(); int ticksPassed = 0; for (int i = 0; i < minTicks; i++) { @@ -425,14 +400,14 @@ public BruteForceResult bruteForceOffers(VillagerTrades.ItemListing[] listings, ticksPassed++; } - while (rng.getTotalCalls() < maxCalls + startingCalls) { + while (ticksPassed < maxTicks) { VillagerRngSimulator randomBranch = rng.copy(); randomBranch.simulateTick(); ticksPassed++; VillagerCommand.Offer offer = randomBranch.anyOffersMatch(listings, targetVillager, predicate); if (offer != null) { // we do the calls before this ticks processing so that since with 0ms ping, the server reads it next tick - return new BruteForceResult(rng.getTotalCalls() - startingCalls, ticksPassed, offer); + return new BruteForceResult(ticksPassed, offer); } rng.simulateTick(); } @@ -441,11 +416,11 @@ public BruteForceResult bruteForceOffers(VillagerTrades.ItemListing[] listings, return null; } - public Pair, List> generateSurroundingOffers(VillagerTrades.ItemListing[] listings, int centerTicks, int radius) { + public SurroundingOffers generateSurroundingOffers(VillagerTrades.ItemListing[] listings, int centerTicks, int radius) { Villager targetVillager = VillagerCracker.getVillager(); if (targetVillager == null || !getCrackedState().isCracked()) { - return Pair.of(List.of(), List.of()); + return new SurroundingOffers(List.of(), List.of()); } List before = new ArrayList<>(radius); @@ -465,61 +440,85 @@ public Pair, List> genera after.add(rng.generateOffers(listings, targetVillager)); } - return Pair.of(before, after); + return new SurroundingOffers(before, after); } - private int[] possibleTicksAhead(VillagerCommand.Offer[] targetOffers, List before, List after) { - List misses = new ArrayList<>(); - for (int i = 0; i < before.size(); i++) { - VillagerCommand.Offer[] offers = before.get(i); - if (Arrays.equals(offers, targetOffers)) { + private int[] possibleTicksAhead(VillagerCommand.Offer[] actualOffers, SurroundingOffers surroundingOffers, VillagerCommand.Offer targetOffer) { + IntList ticksAhead = new IntArrayList(); + + for (int i = 0; i < surroundingOffers.before().size(); i++) { + VillagerCommand.Offer[] offers = surroundingOffers.before().get(i); + if (Arrays.equals(offers, actualOffers)) { // we need to adjust by 1 to get it to not be 0 for the last value in `beforeOffers` - misses.add((before.size() - 1 - i) + 1); + ticksAhead.add((surroundingOffers.before().size() - 1 - i) + 1); } } - for (int i = 0; i < after.size(); i++) { - VillagerCommand.Offer[] offers = after.get(i); - if (Arrays.equals(offers, targetOffers)) { + if (ArrayUtils.contains(actualOffers, targetOffer)) { + ticksAhead.add(0); + } + + for (int i = 0; i < surroundingOffers.after().size(); i++) { + VillagerCommand.Offer[] offers = surroundingOffers.after().get(i); + if (Arrays.equals(offers, actualOffers)) { // we need to adjust by 1 to get it to not be 0 for the first value in `afterOffers` - misses.add(-(i + 1)); + ticksAhead.add(-(i + 1)); } } - return misses.stream().mapToInt(i -> i).toArray(); + + return ticksAhead.toIntArray(); } - public void onGuiOpened(List availableOffersList, Villager villager) { + public void onGuiOpened(List actualOffersList, Villager villager) { final LocalPlayer player = Minecraft.getInstance().player; + assert player != null; + if (player.distanceTo(villager) > 2.0) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.distance").withStyle(ChatFormatting.RED), 100); reset(); + VillagerCracker.stopRunning(); return; } - if (VillagerCracker.targetOffer != null) { - if (availableOffersList.contains(VillagerCracker.targetOffer)) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.success", Configs.villagerAdjustmentTicks * 50).withStyle(ChatFormatting.GREEN), 100); + if (VillagerCracker.isRunning()) { + int[] possibleTicksAhead = possibleTicksAhead(actualOffersList.toArray(VillagerCommand.Offer[]::new), VillagerCracker.surroundingOffers, VillagerCracker.targetOffer); + if (Arrays.binarySearch(possibleTicksAhead, 0) >= 0) { + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.success", VillagerCracker.magicMillisecondCorrection).withStyle(ChatFormatting.GREEN)); player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); } else { - a: { - if (VillagerCracker.surroundingOffers != null) { - int[] possibleTicksAhead = possibleTicksAhead(availableOffersList.toArray(VillagerCommand.Offer[]::new), VillagerCracker.surroundingOffers.getFirst(), VillagerCracker.surroundingOffers.getSecond()); - - if (possibleTicksAhead.length > 0) { - int zeroIndex = Math.max(possibleTicksAhead.length - 1, Arrays.binarySearch(possibleTicksAhead, 0)); - // we go less than or equal to because the default adjustment should be to wait an amount of time, rather than to decrease it, since typically people don't have negative ping - int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex]) <= Math.abs(possibleTicksAhead[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure.detailed", Configs.villagerAdjustmentTicks * 50, Arrays.toString(possibleTicksAhead), bestAdjustment).withStyle(ChatFormatting.RED), 100); - player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); - Configs.villagerAdjustmentTicks -= bestAdjustment; - break a; - } + boolean foundSuitableAdjustment = false; + if (VillagerCracker.surroundingOffers != null) { + if (possibleTicksAhead.length > 0) { + int zeroIndex = Math.max(possibleTicksAhead.length - 1, Arrays.binarySearch(possibleTicksAhead, 0)); + // we go less than or equal to because the default adjustment should be to wait an amount of time, rather than to decrease it, since typically people don't have negative ping + int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex]) <= Math.abs(possibleTicksAhead[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.failure.detailed", VillagerCracker.magicMillisecondCorrection, Arrays.toString(possibleTicksAhead), bestAdjustment).withStyle(ChatFormatting.RED)); + player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); + foundSuitableAdjustment = true; } + } - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.failure", Configs.villagerAdjustmentTicks * 50).withStyle(ChatFormatting.RED), 100); + if (!foundSuitableAdjustment) { + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.failure", VillagerCracker.magicMillisecondCorrection).withStyle(ChatFormatting.RED)); player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); } } + + if (possibleTicksAhead.length > 0) { + if (VillagerCracker.combinedMedianEM.data.size() >= 10) { + VillagerCracker.combinedMedianEM.data.removeFirst(); + } + DoubleList possibleMillisecondsAhead = new DoubleArrayList(possibleTicksAhead.length); + for (int ticksAhead : possibleTicksAhead) { + possibleMillisecondsAhead.add(ticksAhead * VillagerCracker.serverMspt + VillagerCracker.magicMillisecondCorrection); + } + VillagerCracker.combinedMedianEM.data.add(possibleMillisecondsAhead); + VillagerCracker.maxTicksBefore = Math.max(VillagerCracker.maxTicksBefore, -possibleTicksAhead[0]); + VillagerCracker.maxTicksAfter = Math.max(VillagerCracker.maxTicksAfter, possibleTicksAhead[possibleTicksAhead.length - 1]); + VillagerCracker.combinedMedianEM.update(VillagerCracker.serverMspt, VillagerCracker.maxTicksBefore, VillagerCracker.maxTicksAfter); + VillagerCracker.magicMillisecondCorrection = (int) Math.round(VillagerCracker.combinedMedianEM.getResult()); + } + VillagerCracker.targetOffer = null; } } @@ -606,5 +605,9 @@ public Component getMessage(boolean addColor) { } } - public record BruteForceResult(int callsAtInteraction, int ticksPassed, VillagerCommand.Offer offer) {} + public record BruteForceResult(int ticksPassed, VillagerCommand.Offer offer) { + } + + public record SurroundingOffers(List before, List after) { + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java index d060afa17..fb6136d45 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java @@ -1,21 +1,15 @@ package net.earthcomputer.clientcommands.mixin.commands.villager; -import net.earthcomputer.clientcommands.Configs; -import net.earthcomputer.clientcommands.command.ClientCommandHelper; +import net.earthcomputer.clientcommands.command.PingCommand; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.interfaces.IVillager; -import net.minecraft.ChatFormatting; +import net.earthcomputer.clientcommands.util.CUtil; import net.minecraft.client.Minecraft; -import net.minecraft.client.gui.screens.inventory.MerchantScreen; import net.minecraft.client.player.LocalPlayer; -import net.minecraft.network.chat.Component; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; -import net.minecraft.util.Mth; +import net.minecraft.network.protocol.game.ServerboundInteractPacket; import net.minecraft.world.InteractionHand; -import net.minecraft.world.InteractionResult; import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.npc.AbstractVillager; import net.minecraft.world.entity.npc.Villager; @@ -24,9 +18,7 @@ import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; -import java.util.Arrays; import java.util.List; -import java.util.OptionalInt; @Mixin(Villager.class) public abstract class VillagerMixin extends AbstractVillager implements IVillager { @@ -35,58 +27,67 @@ public VillagerMixin(EntityType entityType, Level le } @Unique - VillagerRngSimulator rng = new VillagerRngSimulator(null); + VillagerRngSimulator simulator = new VillagerRngSimulator(null); @Override public void clientcommands_onAmbientSoundPlayed(float pitch) { - rng.onAmbientSoundPlayed(pitch); + simulator.onAmbientSoundPlayed(pitch); } @Override public void clientcommands_onNoSoundPlayed(float pitch) { VillagerProfession profession = ((Villager) (Object) this).getVillagerData().getProfession(); - rng.onNoSoundPlayed(pitch, profession != VillagerProfession.NONE && profession != VillagerProfession.NITWIT); + simulator.onNoSoundPlayed(pitch, profession != VillagerProfession.NONE && profession != VillagerProfession.NITWIT); } @Override public void clientcommands_onYesSoundPlayed(float pitch) { - rng.onYesSoundPlayed(pitch); + simulator.onYesSoundPlayed(pitch); } @Override public void clientcommands_onSplashSoundPlayed(float pitch) { - rng.onSplashSoundPlayed(pitch); + simulator.onSplashSoundPlayed(pitch); } @Override public void clientcommands_onXpOrbSpawned(int value) { - rng.onXpOrbSpawned(value); + simulator.onXpOrbSpawned(value); } @Override public void clientcommands_onServerTick() { - rng.simulateTick(); + simulator.simulateTick(); - if (rng.shouldInteractWithVillager()) { - Minecraft minecraft = Minecraft.getInstance(); - if (minecraft.screen instanceof MerchantScreen) { - minecraft.screen.onClose(); - } else { - InteractionResult result = minecraft.gameMode.interact(minecraft.player, this, InteractionHand.MAIN_HAND); - if (result instanceof InteractionResult.Success success && success.swingSource() == InteractionResult.SwingSource.CLIENT) { - minecraft.player.swing(InteractionHand.MAIN_HAND); - } + if (VillagerCracker.isRunning() && !VillagerCracker.hasClickedVillager) { + int millisecondsUntilInteract = simulator.getTicksRemaining() * VillagerCracker.serverMspt - PingCommand.getLocalPing() + VillagerCracker.magicMillisecondCorrection; + if (millisecondsUntilInteract < 200) { + LocalPlayer oldPlayer = Minecraft.getInstance().player; + assert oldPlayer != null; + CUtil.sendAtPreciseTime( + System.nanoTime() + millisecondsUntilInteract * 1_000_000L, + ServerboundInteractPacket.createInteractionPacket(this, false, InteractionHand.MAIN_HAND), + () -> true, + () -> { + LocalPlayer player = Minecraft.getInstance().player; + if (player == oldPlayer) { + player.swing(InteractionHand.MAIN_HAND); + } + } + ); + simulator.reset(); + VillagerCracker.hasClickedVillager = true; } } } @Override public VillagerRngSimulator clientcommands_getVillagerRngSimulator() { - return rng; + return simulator; } @Override public void clientcommands_onGuiOpened(List availableOffersList) { - rng.onGuiOpened(availableOffersList, (Villager) (Object) this); + simulator.onGuiOpened(availableOffersList, (Villager) (Object) this); } } diff --git a/src/main/java/net/earthcomputer/clientcommands/util/CUtil.java b/src/main/java/net/earthcomputer/clientcommands/util/CUtil.java index 77bd2efbe..40ec6757b 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/CUtil.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/CUtil.java @@ -1,12 +1,23 @@ package net.earthcomputer.clientcommands.util; +import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.DynamicCommandExceptionType; import com.mojang.datafixers.util.Either; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPipeline; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.core.Holder; import net.minecraft.core.RegistryAccess; import net.minecraft.core.registries.Registries; +import net.minecraft.network.PacketEncoder; +import net.minecraft.network.PacketListener; +import net.minecraft.network.RegistryFriendlyByteBuf; import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.Packet; import net.minecraft.resources.ResourceKey; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.LivingEntity; @@ -17,10 +28,15 @@ import java.util.Arrays; import java.util.Optional; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.function.BooleanSupplier; import java.util.function.Consumer; import java.util.regex.Pattern; public final class CUtil { + private static final ScheduledExecutorService PRECISE_PACKET_TIME_EXECUTOR = Executors.newScheduledThreadPool(1, new ThreadFactoryBuilder().setNameFormat("Clientcommands precise packet sender #%d").build()); private static final DynamicCommandExceptionType REGEX_TOO_SLOW_EXCEPTION = new DynamicCommandExceptionType(arg -> Component.translatable("commands.client.regexTooSlow", arg)); private CUtil() { @@ -66,6 +82,47 @@ public static int getEnchantmentLevel(ResourceKey enchantment, Livi return Arrays.stream(EquipmentSlot.values()).mapToInt(slot -> entity.getItemBySlot(slot).getEnchantments().getLevel(enchHolder.get())).max().orElse(0); } + public static void sendAtPreciseTime(long nanoTime, Packet packet, BooleanSupplier shouldStillSend, Runnable mainThreadCallback) { + sendAtPreciseTimeImpl(nanoTime, packet, shouldStillSend, mainThreadCallback); + } + + private static void sendAtPreciseTimeImpl(long nanoTime, Packet packet, BooleanSupplier shouldStillSend, Runnable mainThreadCallback) { + ClientPacketListener connection = Minecraft.getInstance().getConnection(); + if (connection == null) { + return; + } + + ChannelPipeline pipeline = connection.getConnection().channel.pipeline(); + @SuppressWarnings("unchecked") + PacketEncoder encoder = (PacketEncoder) pipeline.get("encoder"); + if (encoder == null) { + return; + } + ChannelHandlerContext encoderContext = pipeline.context("encoder"); + + // Pre-encode the packet with context that's safe to access from the main thread + ByteBuf buf = new RegistryFriendlyByteBuf(Unpooled.buffer(), connection.registryAccess()); + encoder.protocolInfo.codec().encode(buf, packet); + + PRECISE_PACKET_TIME_EXECUTOR.schedule(() -> { + while (System.nanoTime() - nanoTime < 0) { + if (!shouldStillSend.getAsBoolean()) { + buf.release(); + return; + } + } + + if (!shouldStillSend.getAsBoolean()) { + buf.release(); + return; + } + + encoderContext.writeAndFlush(buf); + + Minecraft.getInstance().schedule(mainThreadCallback); + }, Math.max(0, nanoTime - System.nanoTime() - 2000000), TimeUnit.NANOSECONDS); + } + private static class FusedRegexInput implements CharSequence { private static final long FUSE_LENGTH = 50_000_000; // 50ms should be more than enough for a normal regex to do its matching diff --git a/src/main/java/net/earthcomputer/clientcommands/util/CombinedMedianEM.java b/src/main/java/net/earthcomputer/clientcommands/util/CombinedMedianEM.java new file mode 100644 index 000000000..9da361c90 --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/util/CombinedMedianEM.java @@ -0,0 +1,153 @@ +package net.earthcomputer.clientcommands.util; + +import it.unimi.dsi.fastutil.doubles.DoubleArrayList; +import it.unimi.dsi.fastutil.doubles.DoubleList; +import net.minecraft.SharedConstants; +import net.minecraft.util.Mth; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Taken from PseudoGravity's code + * + * @author MC (PseudoGravity) + */ +public final class CombinedMedianEM { + // a list of samples + // each sample is actually a list of points + // for each interval, convert it to a point by taking the median value + // or... break the 50ms intervals into 2 25ms intervals for better accuracy + public final List data = new ArrayList<>(); + + // width of the intervals + private int width = SharedConstants.MILLIS_PER_TICK; + + private static final double MIN_PACKET_LOSS_RATE = 0.01; + private static final double MAX_PACKET_LOSS_RATE = 0.5; + private static final double MIN_SIGMA = 10; + private static final double MAX_SIGMA = 1000; + + // three parameters and 2 constraints + private double packetLossRate = 0.2; + private double mu = 0.0; + private double sigma = 500; + + public void update(int mspt, int maxTicksBefore, int maxTicksAfter) { + width = mspt; + + // width of time window considered + // all of the data points for all samples are within this window + int beginTime = Mth.floor(mu + 0.5) - width / 2 - maxTicksBefore * width; + int endTime = Mth.floor(mu + 0.5) + width / 2 + maxTicksAfter * width; + + double[] dropRate = new double[data.size()]; + Arrays.setAll(dropRate, i -> (double) data.get(i).size() * width / (endTime - beginTime)); + + int bestTime = 0; + double bestScore = Double.POSITIVE_INFINITY; + + for (int time = beginTime; time <= endTime; time += 10) { + // find score for each option for time + double score = 0; + for (int i = 0; i < data.size(); i++) { + // for each sample, find the point which adds the least to the score + DoubleList sample = data.get(i); + double lambda = dropRate[i] / width; + double bestSubScore = Double.POSITIVE_INFINITY; + for (int j = 0; j < sample.size(); j++) { + double x = sample.getDouble(j); + double absDev = Math.abs(x - time); + absDev = (1 - Math.exp(-lambda * absDev)) / lambda; // further curbing outlier effects + if (absDev < bestSubScore) { + bestSubScore = absDev; + } + } + score += bestSubScore; + } + if (score < bestScore) { + bestScore = score; + bestTime = time; + } + } + + mu = bestTime; + sigma = bestScore / data.size(); + sigma = Math.max(Math.min(sigma, MAX_SIGMA), MIN_SIGMA); + + for (int repeat = 0; repeat < 1; repeat++) { + // E step + // calculate weights (and classifications) + var masses = new ArrayList(); + for (int i = 0; i < data.size(); i++) { + + DoubleList sample = data.get(i); + + // process each sample + double sum = 0; + for (int j = 0; j < sample.size(); j++) { + double x = sample.getDouble(j); + sum += mass(x); + } + double pXandNorm = Math.min(sum, 1) * (1 - packetLossRate); // cap at 1 + + double pXandUnif = dropRate[i] * packetLossRate; + + double pNorm = pXandNorm / (pXandNorm + pXandUnif); + + DoubleList mass = new DoubleArrayList(); + for (int j = 0; j < sample.size(); j++) { + double x = sample.getDouble(j); + mass.add(mass(x) / sum * pNorm); + } + + masses.add(mass); + } + + // M step + // compute new best estimate for parameters + double weightedsum = 0; + double sumofweights = 0; + for (int i = 0; i < data.size(); i++) { + DoubleList sample = data.get(i); + DoubleList mass = masses.get(i); + for (int j = 0; j < sample.size(); j++) { + weightedsum += sample.getDouble(j) * mass.getDouble(j); + sumofweights += mass.getDouble(j); + } + } + double muNext = weightedsum / sumofweights; + + double weightedsumofsquaredeviations = 0; + for (int i = 0; i < data.size(); i++) { + DoubleList sample = data.get(i); + DoubleList mass = masses.get(i); + for (int j = 0; j < sample.size(); j++) { + weightedsumofsquaredeviations += Math.pow(sample.getDouble(j) - muNext, 2) * mass.getDouble(j); + } + } + double sigmaNext = Math.sqrt(weightedsumofsquaredeviations / sumofweights); + sigmaNext = Math.max(Math.min(sigmaNext, MAX_SIGMA), MIN_SIGMA); + + double packetlossrateNext = (data.size() - sumofweights) / data.size(); + packetlossrateNext = Math.max(Math.min(packetlossrateNext, MAX_PACKET_LOSS_RATE), MIN_PACKET_LOSS_RATE); + + mu = muNext; + sigma = sigmaNext; + packetLossRate = packetlossrateNext; + } + } + + private double mass(double x) { + // should be cdf(x+width/2)-cdf(x-width/2) but is simplified to pdf(x)*width and + // capped at 1 + // to avoid pesky erf() functions + double pdf = 1 / (sigma * Math.sqrt(2 * Math.PI)) * Math.exp(-Math.pow((x - mu) / sigma, 2) / 2); + return Math.min(pdf * width, 1); + } + + public double getResult() { + return mu; + } +} diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index ec535d76c..96b21e617 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -243,9 +243,9 @@ "commands.cvar.list.empty": "No available variables", "commands.cvar.list": "Available variables: %s", - "commands.cvillager.alreadyBruteForcing": "Cannot brute-force villager RNG since your target villager is already brute forcing", - "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %s calls", - "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %s calls", + "commands.cvillager.alreadyRunning": "Cannot brute-force villager RNG since villager RNG manipulation is already running", + "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %s ticks", + "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %s ticks", "commands.cvillager.clock.cleared": "Your clock is cleared", "commands.cvillager.clock.set": "Clock set to %s %s %s (%s)", "commands.cvillager.clock.set.cleared": "Your clock is now cleared", @@ -254,10 +254,12 @@ "commands.cvillager.failure": "Got the incorrect trade with correction of %sms", "commands.cvillager.failure.detailed": "Got the incorrect trade with correction of %sms (was one of %s ticks ahead); re-adjusting by %s ticks", "commands.cvillager.goalAdded": "Added goal successfully.", - "commands.cvillager.help.day": "Help: Villager RNG manipulation is likely to break if it's not night-time", - "commands.cvillager.help.noClock": "Help: Villager RNG manipulation requires a 20 Hz clock", - "commands.cvillager.help.tooSlow": "Help: Villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running much slower", + "commands.cvillager.help.day": "Help: villager RNG manipulation will break if it's not night time", + "commands.cvillager.help.noClock": "Help: villager RNG manipulation requires a 20 Hz clock", + "commands.cvillager.help.tooFast": "Help: villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running faster", + "commands.cvillager.help.tooSlow": "Help: villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running slower", "commands.cvillager.inSync": "Your villager's RNG is cracked", + "commands.cvillager.itemCountOutOfRange": "The specified item count range (%s) overlaps into an item count outside the maximum (%s)", "commands.cvillager.listGoals.noGoals": "There are no villager goals", "commands.cvillager.listGoals.success": "There are %s villager goals:", "commands.cvillager.listGoals.success.one": "There is 1 villager goal:", @@ -273,7 +275,6 @@ "commands.cvillager.outOfSync.yes": "Your villager's yes sound was incorrectly pitched, re-cracking", "commands.cvillager.partiallyCracked": "Your villager's RNG is partially cracked (~83m seeds remain)", "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %s, you only have %s goals", - "commands.cvillager.itemCountOutOfRange": "The specified item count range (%s) overlaps into an item count outside the maximum (%s)", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", "commands.cvillager.resetCracker": "Successfully reset cracked villager RNG", "commands.cvillager.success": "Got the correct trade with correction of %sms", From 5548e6164f4186dde58228d9fe88f8f92f59e1a2 Mon Sep 17 00:00:00 2001 From: RTTV Date: Tue, 26 Nov 2024 23:20:33 -0500 Subject: [PATCH 50/78] Changed failure message for villager cracking --- .../features/VillagerRngSimulator.java | 30 ++++++------------- .../assets/clientcommands/lang/en_us.json | 3 +- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index ff345f4d3..20e78ba68 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -482,27 +482,7 @@ public void onGuiOpened(List actualOffersList, Villager v if (VillagerCracker.isRunning()) { int[] possibleTicksAhead = possibleTicksAhead(actualOffersList.toArray(VillagerCommand.Offer[]::new), VillagerCracker.surroundingOffers, VillagerCracker.targetOffer); - if (Arrays.binarySearch(possibleTicksAhead, 0) >= 0) { - ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.success", VillagerCracker.magicMillisecondCorrection).withStyle(ChatFormatting.GREEN)); - player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); - } else { - boolean foundSuitableAdjustment = false; - if (VillagerCracker.surroundingOffers != null) { - if (possibleTicksAhead.length > 0) { - int zeroIndex = Math.max(possibleTicksAhead.length - 1, Arrays.binarySearch(possibleTicksAhead, 0)); - // we go less than or equal to because the default adjustment should be to wait an amount of time, rather than to decrease it, since typically people don't have negative ping - int bestAdjustment = possibleTicksAhead.length - 1 > zeroIndex && Math.abs(possibleTicksAhead[zeroIndex]) <= Math.abs(possibleTicksAhead[zeroIndex + 1]) ? possibleTicksAhead[zeroIndex + 1] : possibleTicksAhead[zeroIndex]; - ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.failure.detailed", VillagerCracker.magicMillisecondCorrection, Arrays.toString(possibleTicksAhead), bestAdjustment).withStyle(ChatFormatting.RED)); - player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); - foundSuitableAdjustment = true; - } - } - - if (!foundSuitableAdjustment) { - ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.failure", VillagerCracker.magicMillisecondCorrection).withStyle(ChatFormatting.RED)); - player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); - } - } + int firstCorrection = VillagerCracker.magicMillisecondCorrection; if (possibleTicksAhead.length > 0) { if (VillagerCracker.combinedMedianEM.data.size() >= 10) { @@ -519,6 +499,14 @@ public void onGuiOpened(List actualOffersList, Villager v VillagerCracker.magicMillisecondCorrection = (int) Math.round(VillagerCracker.combinedMedianEM.getResult()); } + if (Arrays.binarySearch(possibleTicksAhead, 0) >= 0) { + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.success", firstCorrection).withStyle(ChatFormatting.GREEN)); + player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); + } else { + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.failure", firstCorrection, VillagerCracker.magicMillisecondCorrection).withStyle(ChatFormatting.RED)); + player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); + } + VillagerCracker.targetOffer = null; } } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 96b21e617..0ddc4951c 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -251,8 +251,7 @@ "commands.cvillager.clock.set.cleared": "Your clock is now cleared", "commands.cvillager.crack.failed": "Failed to crack villager seed (found %s seeds), re-cracking...", "commands.cvillager.crack.success": "Villager RNG cracked: %s", - "commands.cvillager.failure": "Got the incorrect trade with correction of %sms", - "commands.cvillager.failure.detailed": "Got the incorrect trade with correction of %sms (was one of %s ticks ahead); re-adjusting by %s ticks", + "commands.cvillager.failure": "Got the incorrect trade with correction of %sms; re-adjusting to %sms", "commands.cvillager.goalAdded": "Added goal successfully.", "commands.cvillager.help.day": "Help: villager RNG manipulation will break if it's not night time", "commands.cvillager.help.noClock": "Help: villager RNG manipulation requires a 20 Hz clock", From 9054d8d7d2992de60975d16aa5eacf7cada6b9c6 Mon Sep 17 00:00:00 2001 From: joe Date: Wed, 27 Nov 2024 20:42:54 +0000 Subject: [PATCH 51/78] Move stuff around to be in more appropriate places --- .../command/VillagerCommand.java | 179 +++----------- .../ItemAndEnchantmentsPredicateArgument.java | 46 +--- .../features/FishingCracker.java | 2 +- .../features/VillagerCracker.java | 227 ++++++++++++++++-- .../features/VillagerRngSimulator.java | 145 +++-------- .../clientcommands/interfaces/IVillager.java | 24 -- .../villager/ClientPacketListenerMixin.java | 74 ++++++ .../villager}/MerchantScreenMixin.java | 9 +- .../commands/villager/VillagerMixin.java | 93 ------- .../rngevents/ClientPacketListenerMixin.java | 60 ----- .../clientcommands/util/CUtil.java | 9 + .../clientcommands/util/CombinedMedianEM.java | 6 +- .../assets/clientcommands/lang/en_us.json | 1 - src/main/resources/mixins.clientcommands.json | 4 +- 14 files changed, 379 insertions(+), 500 deletions(-) delete mode 100644 src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java create mode 100644 src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java rename src/main/java/net/earthcomputer/clientcommands/mixin/{rngevents => commands/villager}/MerchantScreenMixin.java (70%) delete mode 100644 src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 2f3e461f5..f0e56c9a5 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -2,23 +2,21 @@ import com.mojang.brigadier.Command; import com.mojang.brigadier.CommandDispatcher; -import com.mojang.brigadier.StringReader; import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import dev.xpple.clientarguments.arguments.CRangeArgument; import net.earthcomputer.clientcommands.Configs; +import net.earthcomputer.clientcommands.command.arguments.WithStringArgument; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; -import net.earthcomputer.clientcommands.interfaces.IVillager; +import net.earthcomputer.clientcommands.util.CUtil; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.ChatFormatting; import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.commands.CommandBuildContext; -import net.minecraft.commands.arguments.item.ItemParser; import net.minecraft.core.BlockPos; import net.minecraft.core.GlobalPos; -import net.minecraft.core.HolderLookup; import net.minecraft.network.chat.Component; import net.minecraft.resources.ResourceKey; import net.minecraft.tags.EnchantmentTags; @@ -29,12 +27,9 @@ import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.TooltipFlag; -import net.minecraft.world.item.trading.ItemCost; -import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.Level; import org.jetbrains.annotations.Nullable; -import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -57,7 +52,6 @@ public class VillagerCommand { private static final SimpleCommandExceptionType ALREADY_RUNNING_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.alreadyRunning")); private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX_EXCEPTION = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); private static final Dynamic2CommandExceptionType ITEM_QUANTITY_OUT_OF_RANGE_EXCEPTION = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.itemCountOutOfRange", a, b)); - private static final List goals = new ArrayList<>(); public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { dispatcher.register(literal("cvillager") @@ -102,21 +96,28 @@ public static void register(CommandDispatcher dispatc .executes(ctx -> setClockPos(ctx.getSource(), getBlockPos(ctx, "pos"))))) .then(literal("reset-cracker") .executes(ctx -> resetCracker())) - .then(literal("brute-force") - .executes(ctx -> bruteForce(false)) + .then(literal("start") + .executes(ctx -> start(false)) .then(literal("first-level") - .executes(ctx -> bruteForce(false))) + .executes(ctx -> start(false))) .then(literal("next-level") - .executes(ctx -> bruteForce(true))))); + .executes(ctx -> start(true))))); } - private static int addGoal(FabricClientCommandSource ctx, Result> first, MinMaxBounds.Ints firstCount, @Nullable Result> second, @Nullable MinMaxBounds.Ints secondCount, Result> result, MinMaxBounds.Ints resultCount) throws CommandSyntaxException { - HolderLookup.Provider registries = ctx.getWorld().registryAccess(); - String firstString = displayPredicate(first, firstCount, registries); - String secondString = second == null || secondCount == null ? null : displayPredicate(second, secondCount, registries); - String resultString = displayPredicate(result, resultCount, registries); - - goals.add(new Goal( + private static int addGoal( + FabricClientCommandSource ctx, + WithStringArgument.Result> first, + MinMaxBounds.Ints firstCount, + @Nullable WithStringArgument.Result> second, + @Nullable MinMaxBounds.Ints secondCount, + Result> result, + MinMaxBounds.Ints resultCount + ) { + String firstString = first.string() + " " + CUtil.boundsToString(firstCount); + String secondString = second == null || secondCount == null ? null : second.string() + " " + CUtil.boundsToString(secondCount); + String resultString = result.string() + " " + CUtil.boundsToString(resultCount); + + VillagerCracker.goals.add(new VillagerCracker.Goal( firstString, item -> first.value().test(item) && firstCount.matches(item.getCount()), @@ -124,23 +125,20 @@ private static int addGoal(FabricClientCommandSource ctx, Result second.value().test(item) && secondCount.matches(item.getCount()), resultString, - item -> result.value().test(item) && resultCount.matches(item.getCount()))); + item -> result.value().test(item) && resultCount.matches(item.getCount()) + )); ctx.sendFeedback(Component.translatable("commands.cvillager.goalAdded")); return Command.SINGLE_SUCCESS; } private static int listGoals(FabricClientCommandSource source) { - if (goals.isEmpty()) { + if (VillagerCracker.goals.isEmpty()) { source.sendFeedback(Component.translatable("commands.cvillager.listGoals.noGoals").withStyle(style -> style.withColor(ChatFormatting.RED))); } else { - if (goals.size() == 1) { - source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success.one")); - } else { - source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", goals.size() + 1)); - } - for (int i = 0; i < goals.size(); i++) { - Goal goal = goals.get(i); + source.sendFeedback(Component.translatable("commands.cvillager.listGoals.success", VillagerCracker.goals.size())); + for (int i = 0; i < VillagerCracker.goals.size(); i++) { + VillagerCracker.Goal goal = VillagerCracker.goals.get(i); source.sendFeedback(Component.literal((i + 1) + ": " + goal.toString())); } } @@ -149,11 +147,11 @@ private static int listGoals(FabricClientCommandSource source) { private static int removeGoal(FabricClientCommandSource source, int index) throws CommandSyntaxException { index = index - 1; - if (index < goals.size()) { - Goal goal = goals.remove(index); + if (index < VillagerCracker.goals.size()) { + VillagerCracker.Goal goal = VillagerCracker.goals.remove(index); source.sendFeedback(Component.translatable("commands.cvillager.removeGoal.success", goal.toString())); } else { - throw INVALID_GOAL_INDEX_EXCEPTION.create(index + 1, goals.size()); + throw INVALID_GOAL_INDEX_EXCEPTION.create(index + 1, VillagerCracker.goals.size()); } return Command.SINGLE_SUCCESS; } @@ -194,23 +192,20 @@ private static int setClockPos(FabricClientCommandSource ctx, BlockPos pos) { } private static int resetCracker() { - Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager instanceof IVillager iVillager) { - iVillager.clientcommands_getVillagerRngSimulator().reset(); - ClientCommandHelper.sendFeedback("commands.cvillager.resetCracker"); - } + VillagerCracker.simulator.reset(); + ClientCommandHelper.sendFeedback("commands.cvillager.resetCracker"); return Command.SINGLE_SUCCESS; } - private static int bruteForce(boolean levelUp) throws CommandSyntaxException { + private static int start(boolean levelUp) throws CommandSyntaxException { Villager targetVillager = VillagerCracker.getVillager(); - if (goals.isEmpty()) { + if (VillagerCracker.goals.isEmpty()) { throw NO_GOALS_EXCEPTION.create(); } - if (!(targetVillager instanceof IVillager iVillager) || !iVillager.clientcommands_getVillagerRngSimulator().getCrackedState().isCracked()) { + if (targetVillager == null || !VillagerCracker.simulator.getCrackedState().isCracked()) { throw NO_CRACKED_VILLAGER_PRESENT_EXCEPTION.create(); } @@ -232,14 +227,15 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(crackedLevel, new VillagerTrades.ItemListing[0]); int adjustmentTicks = levelUp ? -40 : 0; - VillagerRngSimulator.BruteForceResult result = iVillager.clientcommands_getVillagerRngSimulator().bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationTicks, offer -> VillagerCommand.goals.stream().anyMatch(goal -> goal.matches(offer))); + VillagerRngSimulator.BruteForceResult result = VillagerCracker.simulator.bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationTicks, offer -> VillagerCracker.goals.stream().anyMatch(goal -> goal.matches(offer))); if (result == null) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationTicks).withStyle(ChatFormatting.RED), 100); return Command.SINGLE_SUCCESS; } - VillagerRngSimulator.SurroundingOffers surroundingOffers = iVillager.clientcommands_getVillagerRngSimulator().generateSurroundingOffers(listings, result.ticksPassed(), 1000); + VillagerRngSimulator.SurroundingOffers surroundingOffers = VillagerCracker.simulator.generateSurroundingOffers(listings, result.ticksPassed(), 1000); + assert surroundingOffers != null; int ticks = result.ticksPassed() + adjustmentTicks; - Offer offer = result.offer(); + VillagerCracker.Offer offer = result.offer(); String price; if (offer.second() == null) { price = displayText(offer.first(), false); @@ -250,108 +246,11 @@ private static int bruteForce(boolean levelUp) throws CommandSyntaxException { VillagerCracker.targetOffer = offer; VillagerCracker.surroundingOffers = surroundingOffers; VillagerCracker.hasClickedVillager = false; - iVillager.clientcommands_getVillagerRngSimulator().setTicksUntilBruteForceInteract(ticks); + VillagerCracker.simulator.setTicksUntilBruteForceInteract(ticks); return Command.SINGLE_SUCCESS; } - public record Goal(String firstString, Predicate first, @Nullable String secondString, @Nullable Predicate second, String resultString, Predicate result) { - public boolean matches(Offer offer) { - return first.test(offer.first) - && ((second == null && offer.second == null) || offer.second != null && second != null && second.test(offer.second)) - && result.test(offer.result); - } - - @Override - public String toString() { - if (secondString == null) { - return String.format("%s = %s", firstString, resultString); - } else { - return String.format("%s + %s = %s", firstString, secondString, resultString); - } - } - } - - public record Offer(ItemStack first, @Nullable ItemStack second, ItemStack result) { - public Offer(MerchantOffer offer) { - this(offer.getBaseCostA(), offer.getItemCostB().map(ItemCost::itemStack).orElse(null), offer.getResult()); - } - - @Override - public boolean equals(Object obj) { - if (!(obj instanceof Offer(ItemStack offerFirst, ItemStack offerSecond, ItemStack offerResult))) { - return false; - } - return ItemStack.isSameItemSameComponents(this.first, offerFirst) && this.first.getCount() == offerFirst.getCount() - && (this.second == offerSecond || this.second != null && offerSecond != null && ItemStack.isSameItemSameComponents(this.second, offerSecond) && this.second.getCount() == offerSecond.getCount()) - && ItemStack.isSameItemSameComponents(this.result, offerResult) && this.result.getCount() == offerResult.getCount(); - } - - @Override - public String toString() { - if (second == null) { - return String.format("%s = %s", displayText(first, false), displayText(result, false)); - } else { - return String.format("%s + %s = %s", displayText(first, false), displayText(second, false), displayText(result, false)); - } - } - } - - private static String displayPredicate(Result> item, MinMaxBounds.Ints count, HolderLookup.Provider registries) throws CommandSyntaxException { - String name; - int maxCount = 64; - if (item.value() instanceof ItemAndEnchantmentsPredicate itemAndEnchantmentsPredicate) { - name = item.value().toString(); - maxCount = itemAndEnchantmentsPredicate.item().getDefaultMaxStackSize(); - } else { - try { - ItemParser.ItemResult firstItemResult = new ItemParser(registries).parse(new StringReader(item.string())); - name = displayText(new ItemStack(firstItemResult.item(), 1, firstItemResult.components()), true); - maxCount = firstItemResult.item().value().getDefaultMaxStackSize(); - } catch (CommandSyntaxException e) { - name = item.string(); - } - } - - @Nullable - String rangeString = displayRange(maxCount, count); - if (rangeString == null) { - throw ITEM_QUANTITY_OUT_OF_RANGE_EXCEPTION.create(count.min().map(Object::toString).orElse("") + ".." + count.max().map(Object::toString).orElse(""), maxCount); - } - - return rangeString + " " + name; - } - - @Nullable - public static String displayRange(int maxCount, MinMaxBounds.Ints range) { - if (range.max().isPresent() && range.max().get() > maxCount || range.min().isPresent() && range.min().get() > maxCount) { - return null; - } - - if (maxCount == 1) { - return ""; - } - - String string = ""; - if ((range.min().isEmpty() || range.min().get() == 1) && (range.max().isPresent() && range.max().get() == maxCount)) { - string = "*"; - } else if (range.min().equals(range.max()) && range.min().isPresent()) { - string = range.min().get().toString(); - } else { - if (range.min().isPresent()) { - string = string + range.min().get(); - } - if (!string.equals(" ") || range.max().isPresent()) { - string = string + ".."; - } - if (range.max().isPresent()) { - string = string + range.max().get(); - } - } - - return string; - } - public static String displayText(ItemStack stack, boolean hideCount) { String quantityPrefix = hideCount || stack.getCount() == 1 ? "" : stack.getCount() + " "; List lines = stack.getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL); diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java index 55f3ea9de..523abf68e 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java @@ -9,7 +9,6 @@ import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.util.MultiVersionCompat; import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.commands.SharedSuggestionProvider; @@ -40,8 +39,6 @@ import java.util.function.BiPredicate; import java.util.function.Consumer; import java.util.function.Predicate; -import java.util.Objects; -import java.util.stream.Collectors; import java.util.stream.Stream; public class ItemAndEnchantmentsPredicateArgument implements ArgumentType { @@ -131,7 +128,7 @@ public ItemAndEnchantmentsPredicate parse(StringReader reader) throws CommandSyn return true; }; - return new ItemAndEnchantmentsPredicate(parser.item, predicate, parser.with, parser.without, parser.exact, parser.ordered); + return new ItemAndEnchantmentsPredicate(parser.item, predicate); } @Override @@ -157,41 +154,18 @@ public Collection getExamples() { return EXAMPLES; } - public record ItemAndEnchantmentsPredicate(Item item, Predicate> predicate, List with, List without, boolean exact, boolean ordered) implements Predicate { + public record ItemAndEnchantmentsPredicate(Item item, Predicate> predicate) implements Predicate { @Override public boolean test(ItemStack stack) { if (item != stack.getItem() && (item != Items.BOOK || stack.getItem() != Items.ENCHANTED_BOOK)) { return false; } - List enchantments = Stream.concat(stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY).entrySet().stream(), stack.getOrDefault(DataComponents.STORED_ENCHANTMENTS, ItemEnchantments.EMPTY).entrySet().stream()) - .map(entry -> new EnchantmentInstance(entry.getKey(), entry.getIntValue())) - .toList(); + List enchantments = Stream.concat( + stack.getOrDefault(DataComponents.ENCHANTMENTS, ItemEnchantments.EMPTY).entrySet().stream(), + stack.getOrDefault(DataComponents.STORED_ENCHANTMENTS, ItemEnchantments.EMPTY).entrySet().stream() + ).map(entry -> new EnchantmentInstance(entry.getKey(), entry.getIntValue())).toList(); return predicate.test(enchantments); } - - @Override - public String toString() { - String itemName = item.getName(new ItemStack(item)).getString(); - - StringBuilder flagsBuilder = new StringBuilder(); - if (exact) { - flagsBuilder.append("Exactly"); - } - if (ordered) { - flagsBuilder.append("Ordered"); - } - String flags = flagsBuilder.isEmpty() ? "" : " [" + flagsBuilder + ')'; - - String enchantments = Stream.concat( - with.stream().filter(enchantment -> enchantment.enchantment().unwrapKey().isPresent()).map(EnchantmentInstancePredicate::toString), - without.stream().filter(enchantment -> enchantment.enchantment().unwrapKey().isPresent()).map(enchantment -> "!" + enchantment) - ).collect(Collectors.joining(", ")); - if (!enchantments.isEmpty()) { - enchantments = '(' + enchantments + ')'; - } - - return String.format("%s%s %s", itemName, flags, enchantments); - } } private class Parser { @@ -485,16 +459,10 @@ private void suggestOption() { } } - public record EnchantmentInstancePredicate(Holder enchantment, MinMaxBounds.Ints level) implements Predicate { + private record EnchantmentInstancePredicate(Holder enchantment, MinMaxBounds.Ints level) implements Predicate { @Override public boolean test(EnchantmentInstance enchInstance) { return enchantment.equals(enchInstance.enchantment) && level.matches(enchInstance.level); } - - @Override - public String toString() { - String quantity = VillagerCommand.displayRange(enchantment.value().getMaxLevel(), level); - return Component.translatable(enchantment.unwrapKey().get().location().toLanguageKey("enchantment")).getString() + " " + (quantity == null || quantity.isEmpty() ? "*" : quantity); - } } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java index a534aae39..e9cf639c5 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java @@ -558,7 +558,7 @@ private static void processExperienceOrbSpawn(double x, double y, double z, int } combinedMedianEM.data.add(sample); - combinedMedianEM.update(serverMspt, expectedCatches.length / 2, expectedCatches.length / 2); + combinedMedianEM.update(serverMspt, expectedCatches.length); magicMillisecondsCorrection = (int) Math.round(combinedMedianEM.getResult()); } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 3ca290f2d..5fb0f868d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -1,27 +1,46 @@ package net.earthcomputer.clientcommands.features; +import it.unimi.dsi.fastutil.doubles.DoubleArrayList; +import it.unimi.dsi.fastutil.doubles.DoubleList; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; import net.earthcomputer.clientcommands.command.ClientCommandHelper; +import net.earthcomputer.clientcommands.command.PingCommand; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.event.ClientConnectionEvents; import net.earthcomputer.clientcommands.event.MoreClientEvents; -import net.earthcomputer.clientcommands.interfaces.IVillager; +import net.earthcomputer.clientcommands.util.CUtil; import net.earthcomputer.clientcommands.util.CombinedMedianEM; +import net.minecraft.ChatFormatting; import net.minecraft.SharedConstants; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.GlobalPos; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.network.protocol.game.ServerboundInteractPacket; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; +import net.minecraft.sounds.SoundSource; +import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.trading.ItemCost; +import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.phys.Vec3; +import org.apache.commons.lang3.ArrayUtils; import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; import java.util.UUID; +import java.util.function.Predicate; public class VillagerCracker { // This value was computed by brute forcing all seeds @@ -31,11 +50,13 @@ public class VillagerCracker { private static UUID villagerUuid = null; @Nullable private static WeakReference cachedVillager = null; + public static final VillagerRngSimulator simulator = new VillagerRngSimulator(null); @Nullable private static GlobalPos clockPos = null; private static boolean isNewClock; + public static final List goals = new ArrayList<>(); @Nullable - public static VillagerCommand.Offer targetOffer = null; + public static Offer targetOffer = null; public static VillagerRngSimulator.SurroundingOffers surroundingOffers = null; private static int clockTicksSinceLastTimeSync = 0; private static long lastClockRateWarning = 0; @@ -49,29 +70,31 @@ public class VillagerCracker { public static final CombinedMedianEM combinedMedianEM = new CombinedMedianEM(); static { - ClientConnectionEvents.DISCONNECT.register(VillagerCracker::stopRunning); + ClientConnectionEvents.DISCONNECT.register(VillagerCracker::onDisconnect); MoreClientEvents.TIME_SYNC.register(packet -> onTimeSync()); } @Nullable public static Villager getVillager() { + ClientLevel level = Minecraft.getInstance().level; + if (level == null) { + return null; + } + if (villagerUuid == null) { cachedVillager = null; return null; } if (cachedVillager != null) { Villager villager = cachedVillager.get(); - if (villager != null && !villager.isRemoved()) { + if (villager != null && !villager.isRemoved() && villager.level() == level) { return villager; } } - ClientLevel level = Minecraft.getInstance().level; - if (level != null) { - for (Entity entity : level.entitiesForRendering()) { - if (villagerUuid.equals(entity.getUUID()) && entity instanceof Villager villager) { - cachedVillager = new WeakReference<>(villager); - return villager; - } + for (Entity entity : level.entitiesForRendering()) { + if (villagerUuid.equals(entity.getUUID()) && entity instanceof Villager villager) { + cachedVillager = new WeakReference<>(villager); + return villager; } } return null; @@ -85,7 +108,7 @@ public static GlobalPos getClockPos() { public static void setTargetVillager(@Nullable Villager villager) { Villager oldVillager = getVillager(); if (oldVillager != null) { - ((IVillager) oldVillager).clientcommands_getVillagerRngSimulator().reset(); + simulator.reset(); } if (clockPos == null) { @@ -117,13 +140,14 @@ public static void onSoundEventPlayed(ClientboundSoundPacket packet, Vec3 pos) { SoundEvent soundEvent = packet.getSound().value(); if (soundEvent == SoundEvents.VILLAGER_AMBIENT || soundEvent == SoundEvents.VILLAGER_TRADE) { - ((IVillager) targetVillager).clientcommands_onAmbientSoundPlayed(packet.getPitch()); + simulator.onAmbientSoundPlayed(packet.getPitch()); } else if (soundEvent == SoundEvents.VILLAGER_NO) { - ((IVillager) targetVillager).clientcommands_onNoSoundPlayed(packet.getPitch()); + VillagerProfession profession = targetVillager.getVillagerData().getProfession(); + simulator.onNoSoundPlayed(packet.getPitch(), profession != VillagerProfession.NONE && profession != VillagerProfession.NITWIT); } else if (soundEvent == SoundEvents.VILLAGER_YES) { - ((IVillager) targetVillager).clientcommands_onYesSoundPlayed(packet.getPitch()); + simulator.onYesSoundPlayed(packet.getPitch()); } else if (soundEvent == SoundEvents.GENERIC_SPLASH) { - ((IVillager) targetVillager).clientcommands_onSplashSoundPlayed(packet.getPitch()); + simulator.onSplashSoundPlayed(packet.getPitch()); } } @@ -133,7 +157,7 @@ public static void onXpOrbSpawned(ClientboundAddExperienceOrbPacket packet) { return; } - ((IVillager) targetVillager).clientcommands_onXpOrbSpawned(packet.getValue()); + simulator.onXpOrbSpawned(packet.getValue()); } private static void onTimeSync() { @@ -164,7 +188,132 @@ public static void onServerTick() { return; } - ((IVillager) targetVillager).clientcommands_onServerTick(); + simulator.simulateTick(); + if (isRunning()) { + simulator.updateProgressBar(); + } + + if (isRunning() && !hasClickedVillager) { + int millisecondsUntilInteract = simulator.getTicksRemaining() * serverMspt - PingCommand.getLocalPing() + magicMillisecondCorrection; + if (millisecondsUntilInteract < 200) { + LocalPlayer oldPlayer = Minecraft.getInstance().player; + assert oldPlayer != null; + CUtil.sendAtPreciseTime( + System.nanoTime() + millisecondsUntilInteract * 1_000_000L, + ServerboundInteractPacket.createInteractionPacket(targetVillager, false, InteractionHand.MAIN_HAND), + () -> true, + () -> { + LocalPlayer player = Minecraft.getInstance().player; + if (player == oldPlayer) { + player.swing(InteractionHand.MAIN_HAND); + } + } + ); + simulator.reset(); + hasClickedVillager = true; + } + } + } + + private static void onDisconnect() { + if (Relogger.isRelogging) { + UUID prevVillagerUuid = villagerUuid; + GlobalPos prevClockPos = clockPos; + Relogger.relogSuccessTasks.add(() -> { + villagerUuid = prevVillagerUuid; + setClockPos(prevClockPos); + }); + } + + clockPos = null; + villagerUuid = null; + VillagerCracker.stopRunning(); + } + + private static int[] possibleTicksAhead(Offer[] actualOffers, VillagerRngSimulator.SurroundingOffers surroundingOffers) { + IntList ticksAhead = new IntArrayList(); + + for (int i = 0; i < surroundingOffers.before().size(); i++) { + Offer[] offers = surroundingOffers.before().get(i); + if (Arrays.equals(offers, actualOffers)) { + // we need to adjust by 1 to get it to not be 0 for the last value in `beforeOffers` + ticksAhead.add((surroundingOffers.before().size() - 1 - i) + 1); + } + } + + if (Arrays.equals(surroundingOffers.middle(), actualOffers)) { + ticksAhead.add(0); + } + + for (int i = 0; i < surroundingOffers.after().size(); i++) { + Offer[] offers = surroundingOffers.after().get(i); + if (Arrays.equals(offers, actualOffers)) { + // we need to adjust by 1 to get it to not be 0 for the first value in `afterOffers` + ticksAhead.add(-(i + 1)); + } + } + + int[] result = ticksAhead.toIntArray(); + ArrayUtils.reverse(result); + return result; + } + + public static void onGuiOpened(List actualOffersList) { + final LocalPlayer player = Minecraft.getInstance().player; + assert player != null; + + Villager villager = getVillager(); + if (villager == null) { + return; + } + + if (player.distanceTo(villager) > 2.0) { + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.distance").withStyle(ChatFormatting.RED), 100); + simulator.reset(); + stopRunning(); + return; + } + + if (VillagerCracker.isRunning()) { + int[] possibleTicksAhead = possibleTicksAhead(actualOffersList.toArray(Offer[]::new), VillagerCracker.surroundingOffers); + // chop possible ticks ahead into a limited reasonable range + final int consideredTickRange = 21; + int lowerIndex = Arrays.binarySearch(possibleTicksAhead, -consideredTickRange / 2); + if (lowerIndex < 0) { + lowerIndex = -lowerIndex - 1; + } + int upperIndex = Arrays.binarySearch(possibleTicksAhead, consideredTickRange / 2); + if (upperIndex < 0) { + upperIndex = -upperIndex - 2; + } + possibleTicksAhead = Arrays.copyOfRange(possibleTicksAhead, lowerIndex, upperIndex + 1); + + int prevCorrection = VillagerCracker.magicMillisecondCorrection; + if (possibleTicksAhead.length > 0) { + if (VillagerCracker.combinedMedianEM.data.size() >= 10) { + VillagerCracker.combinedMedianEM.data.removeFirst(); + } + DoubleList possibleMillisecondsAhead = new DoubleArrayList(possibleTicksAhead.length); + for (int ticksAhead : possibleTicksAhead) { + possibleMillisecondsAhead.add(ticksAhead * VillagerCracker.serverMspt + VillagerCracker.magicMillisecondCorrection); + } + VillagerCracker.combinedMedianEM.data.add(possibleMillisecondsAhead); + VillagerCracker.maxTicksBefore = Math.max(VillagerCracker.maxTicksBefore, -possibleTicksAhead[0]); + VillagerCracker.maxTicksAfter = Math.max(VillagerCracker.maxTicksAfter, possibleTicksAhead[possibleTicksAhead.length - 1]); + VillagerCracker.combinedMedianEM.update(VillagerCracker.serverMspt, consideredTickRange); + VillagerCracker.magicMillisecondCorrection = (int) Math.round(VillagerCracker.combinedMedianEM.getResult()); + } + + if (actualOffersList.contains(VillagerCracker.targetOffer)) { + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.success", prevCorrection).withStyle(ChatFormatting.GREEN)); + player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); + } else { + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.failure", prevCorrection, VillagerCracker.magicMillisecondCorrection).withStyle(ChatFormatting.RED)); + player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); + } + + stopRunning(); + } } public static boolean isRunning() { @@ -174,4 +323,46 @@ public static boolean isRunning() { public static void stopRunning() { targetOffer = null; } + + public record Goal(String firstString, Predicate first, @Nullable String secondString, @Nullable Predicate second, String resultString, Predicate result) { + public boolean matches(Offer offer) { + return first.test(offer.first) + && ((second == null && offer.second == null) || offer.second != null && second != null && second.test(offer.second)) + && result.test(offer.result); + } + + @Override + public String toString() { + if (secondString == null) { + return String.format("%s = %s", firstString, resultString); + } else { + return String.format("%s + %s = %s", firstString, secondString, resultString); + } + } + } + + public record Offer(ItemStack first, @Nullable ItemStack second, ItemStack result) { + public Offer(MerchantOffer offer) { + this(offer.getBaseCostA(), offer.getItemCostB().map(ItemCost::itemStack).orElse(null), offer.getResult()); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof Offer(ItemStack offerFirst, ItemStack offerSecond, ItemStack offerResult))) { + return false; + } + return ItemStack.isSameItemSameComponents(this.first, offerFirst) && this.first.getCount() == offerFirst.getCount() + && (this.second == offerSecond || this.second != null && offerSecond != null && ItemStack.isSameItemSameComponents(this.second, offerSecond) && this.second.getCount() == offerSecond.getCount()) + && ItemStack.isSameItemSameComponents(this.result, offerResult) && this.result.getCount() == offerResult.getCount(); + } + + @Override + public String toString() { + if (second == null) { + return String.format("%s = %s", VillagerCommand.displayText(first, false), VillagerCommand.displayText(result, false)); + } else { + return String.format("%s + %s = %s", VillagerCommand.displayText(first, false), VillagerCommand.displayText(second, false), VillagerCommand.displayText(result, false)); + } + } + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 20e78ba68..d6e97143e 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -6,23 +6,14 @@ import com.seedfinding.latticg.math.lattice.enumerate.EnumerateRt; import com.seedfinding.latticg.math.optimize.Optimize; import com.seedfinding.mcseed.rand.JRand; -import it.unimi.dsi.fastutil.doubles.DoubleArrayList; -import it.unimi.dsi.fastutil.doubles.DoubleList; -import it.unimi.dsi.fastutil.ints.IntArrayList; -import it.unimi.dsi.fastutil.ints.IntList; import net.earthcomputer.clientcommands.command.ClientCommandHelper; -import net.earthcomputer.clientcommands.command.VillagerCommand; import net.minecraft.ChatFormatting; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.ListTag; import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.Tag; import net.minecraft.network.chat.Component; import net.minecraft.network.chat.MutableComponent; -import net.minecraft.sounds.SoundEvents; -import net.minecraft.sounds.SoundSource; import net.minecraft.util.Mth; import net.minecraft.util.RandomSource; import net.minecraft.world.entity.Entity; @@ -31,12 +22,13 @@ import net.minecraft.world.entity.npc.VillagerTrades; import net.minecraft.world.item.trading.MerchantOffer; import net.minecraft.world.level.levelgen.LegacyRandomSource; -import org.apache.commons.lang3.ArrayUtils; import org.jetbrains.annotations.Nullable; import java.io.DataInputStream; import java.io.IOException; -import java.util.*; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; import java.util.function.Predicate; import java.util.stream.LongStream; @@ -63,7 +55,7 @@ public class VillagerRngSimulator { CompoundTag root = NbtIo.read(new DataInputStream(Objects.requireNonNull(VillagerRngSimulator.class.getResourceAsStream("/villager_lattice_data.nbt")))); ListTag lattices = root.getList("lattices", Tag.TAG_LONG_ARRAY); LATTICES = new BigMatrix[lattices.size()]; - ListTag lattice_inverses = root.getList("lattice_inverses", Tag.TAG_LONG_ARRAY); + ListTag latticeInverses = root.getList("lattice_inverses", Tag.TAG_LONG_ARRAY); INVERSE_LATTICES = new BigMatrix[lattices.size()]; ListTag offsets = root.getList("offsets", Tag.TAG_LONG_ARRAY); OFFSETS = new BigVector[offsets.size()]; @@ -81,8 +73,8 @@ public class VillagerRngSimulator { matrix.set(2, 2, new BigFraction(lattice[8])); LATTICES[i] = matrix; } - for (int i = 0; i < lattice_inverses.size(); i++) { - long[] lattice_inverse = lattice_inverses.getLongArray(i); + for (int i = 0; i < latticeInverses.size(); i++) { + long[] lattice_inverse = latticeInverses.getLongArray(i); BigMatrix matrix = new BigMatrix(3, 3); matrix.set(0, 0, new BigFraction(lattice_inverse[0], 1L << 48)); matrix.set(0, 1, new BigFraction(lattice_inverse[1], 1L << 48)); @@ -132,11 +124,6 @@ public void simulateTick() { simulateServerAiStep(); tickCount++; - - if (totalTicksInBruteForce > 0) { - // TODO: extract outside of simulateTick - updateProgressBar(); - } } private void untick() { @@ -170,7 +157,7 @@ public void updateProgressBar() { } @Nullable - public VillagerCommand.Offer anyOffersMatch(VillagerTrades.ItemListing[] listings, Entity trader, Predicate predicate) { + public VillagerCracker.Offer anyOffersMatch(VillagerTrades.ItemListing[] listings, Entity trader, Predicate predicate) { if (!getCrackedState().isCracked()) { return null; } @@ -182,7 +169,7 @@ public VillagerCommand.Offer anyOffersMatch(VillagerTrades.ItemListing[] listing VillagerTrades.ItemListing listing = newListings.remove(rand.nextInt(newListings.size())); MerchantOffer offer = listing.getOffer(trader, rand); if (offer != null) { - VillagerCommand.Offer x = new VillagerCommand.Offer(offer); + VillagerCracker.Offer x = new VillagerCracker.Offer(offer); if (predicate.test(x)) { return x; } else { @@ -194,12 +181,12 @@ public VillagerCommand.Offer anyOffersMatch(VillagerTrades.ItemListing[] listing } @Nullable - public VillagerCommand.Offer[] generateOffers(VillagerTrades.ItemListing[] listings, Entity trader) { + public VillagerCracker.Offer[] generateOffers(VillagerTrades.ItemListing[] listings, Entity trader) { if (!getCrackedState().isCracked()) { return null; } - VillagerCommand.Offer[] offers = new VillagerCommand.Offer[Math.min(listings.length, 2)]; + VillagerCracker.Offer[] offers = new VillagerCracker.Offer[Math.min(listings.length, 2)]; RandomSource rand = new LegacyRandomSource(random.getSeed() ^ 0x5deece66dL); ArrayList newListings = new ArrayList<>(List.of(listings)); @@ -208,7 +195,7 @@ public VillagerCommand.Offer[] generateOffers(VillagerTrades.ItemListing[] listi VillagerTrades.ItemListing listing = newListings.remove(rand.nextInt(newListings.size())); MerchantOffer offer = listing.getOffer(trader, rand); if (offer != null) { - offers[i] = new VillagerCommand.Offer(offer); + offers[i] = new VillagerCracker.Offer(offer); } } @@ -389,126 +376,60 @@ public void onXpOrbSpawned(int value) { } @Nullable - public BruteForceResult bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxTicks, Predicate predicate) { + public BruteForceResult bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxTicks, Predicate predicate) { Villager targetVillager = VillagerCracker.getVillager(); if (targetVillager != null && getCrackedState().isCracked()) { - VillagerRngSimulator rng = this.copy(); + VillagerRngSimulator branchedSimulator = this.copy(); int ticksPassed = 0; for (int i = 0; i < minTicks; i++) { - rng.simulateTick(); + branchedSimulator.simulateTick(); ticksPassed++; } while (ticksPassed < maxTicks) { - VillagerRngSimulator randomBranch = rng.copy(); - randomBranch.simulateTick(); + VillagerRngSimulator offerSimulator = branchedSimulator.copy(); + offerSimulator.simulateTick(); ticksPassed++; - VillagerCommand.Offer offer = randomBranch.anyOffersMatch(listings, targetVillager, predicate); + VillagerCracker.Offer offer = offerSimulator.anyOffersMatch(listings, targetVillager, predicate); if (offer != null) { // we do the calls before this ticks processing so that since with 0ms ping, the server reads it next tick return new BruteForceResult(ticksPassed, offer); } - rng.simulateTick(); + branchedSimulator.simulateTick(); } } return null; } + @Nullable public SurroundingOffers generateSurroundingOffers(VillagerTrades.ItemListing[] listings, int centerTicks, int radius) { Villager targetVillager = VillagerCracker.getVillager(); if (targetVillager == null || !getCrackedState().isCracked()) { - return new SurroundingOffers(List.of(), List.of()); + return null; } - List before = new ArrayList<>(radius); - List after = new ArrayList<>(radius); + List before = new ArrayList<>(radius); + List after = new ArrayList<>(radius); - VillagerRngSimulator rng = this.copy(); + VillagerRngSimulator branchedSimulator = this.copy(); for (int i = 0; i < Math.max(0, centerTicks - radius); i++) { - rng.simulateTick(); + branchedSimulator.simulateTick(); } for (int i = Math.max(0, centerTicks - radius); i < centerTicks - 1; i++) { - rng.simulateTick(); - before.add(rng.generateOffers(listings, targetVillager)); + branchedSimulator.simulateTick(); + before.add(branchedSimulator.generateOffers(listings, targetVillager)); } - rng.simulateTick(); // this would be our actual offer (at `centerTicks` ticks of advancement) + branchedSimulator.simulateTick(); + VillagerCracker.Offer[] middle = branchedSimulator.generateOffers(listings, targetVillager); for (int i = 0; i < radius; i++) { - rng.simulateTick(); - after.add(rng.generateOffers(listings, targetVillager)); - } - - return new SurroundingOffers(before, after); - } - - private int[] possibleTicksAhead(VillagerCommand.Offer[] actualOffers, SurroundingOffers surroundingOffers, VillagerCommand.Offer targetOffer) { - IntList ticksAhead = new IntArrayList(); - - for (int i = 0; i < surroundingOffers.before().size(); i++) { - VillagerCommand.Offer[] offers = surroundingOffers.before().get(i); - if (Arrays.equals(offers, actualOffers)) { - // we need to adjust by 1 to get it to not be 0 for the last value in `beforeOffers` - ticksAhead.add((surroundingOffers.before().size() - 1 - i) + 1); - } - } - - if (ArrayUtils.contains(actualOffers, targetOffer)) { - ticksAhead.add(0); + branchedSimulator.simulateTick(); + after.add(branchedSimulator.generateOffers(listings, targetVillager)); } - for (int i = 0; i < surroundingOffers.after().size(); i++) { - VillagerCommand.Offer[] offers = surroundingOffers.after().get(i); - if (Arrays.equals(offers, actualOffers)) { - // we need to adjust by 1 to get it to not be 0 for the first value in `afterOffers` - ticksAhead.add(-(i + 1)); - } - } - - return ticksAhead.toIntArray(); - } - - public void onGuiOpened(List actualOffersList, Villager villager) { - final LocalPlayer player = Minecraft.getInstance().player; - assert player != null; - - if (player.distanceTo(villager) > 2.0) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.distance").withStyle(ChatFormatting.RED), 100); - reset(); - VillagerCracker.stopRunning(); - return; - } - - if (VillagerCracker.isRunning()) { - int[] possibleTicksAhead = possibleTicksAhead(actualOffersList.toArray(VillagerCommand.Offer[]::new), VillagerCracker.surroundingOffers, VillagerCracker.targetOffer); - int firstCorrection = VillagerCracker.magicMillisecondCorrection; - - if (possibleTicksAhead.length > 0) { - if (VillagerCracker.combinedMedianEM.data.size() >= 10) { - VillagerCracker.combinedMedianEM.data.removeFirst(); - } - DoubleList possibleMillisecondsAhead = new DoubleArrayList(possibleTicksAhead.length); - for (int ticksAhead : possibleTicksAhead) { - possibleMillisecondsAhead.add(ticksAhead * VillagerCracker.serverMspt + VillagerCracker.magicMillisecondCorrection); - } - VillagerCracker.combinedMedianEM.data.add(possibleMillisecondsAhead); - VillagerCracker.maxTicksBefore = Math.max(VillagerCracker.maxTicksBefore, -possibleTicksAhead[0]); - VillagerCracker.maxTicksAfter = Math.max(VillagerCracker.maxTicksAfter, possibleTicksAhead[possibleTicksAhead.length - 1]); - VillagerCracker.combinedMedianEM.update(VillagerCracker.serverMspt, VillagerCracker.maxTicksBefore, VillagerCracker.maxTicksAfter); - VillagerCracker.magicMillisecondCorrection = (int) Math.round(VillagerCracker.combinedMedianEM.getResult()); - } - - if (Arrays.binarySearch(possibleTicksAhead, 0) >= 0) { - ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.success", firstCorrection).withStyle(ChatFormatting.GREEN)); - player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); - } else { - ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.failure", firstCorrection, VillagerCracker.magicMillisecondCorrection).withStyle(ChatFormatting.RED)); - player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); - } - - VillagerCracker.targetOffer = null; - } + return new SurroundingOffers(before, middle, after); } public long[] crackSeed() { @@ -593,9 +514,9 @@ public Component getMessage(boolean addColor) { } } - public record BruteForceResult(int ticksPassed, VillagerCommand.Offer offer) { + public record BruteForceResult(int ticksPassed, VillagerCracker.Offer offer) { } - public record SurroundingOffers(List before, List after) { + public record SurroundingOffers(List before, VillagerCracker.Offer[] middle, List after) { } } diff --git a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java b/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java deleted file mode 100644 index b229290f7..000000000 --- a/src/main/java/net/earthcomputer/clientcommands/interfaces/IVillager.java +++ /dev/null @@ -1,24 +0,0 @@ -package net.earthcomputer.clientcommands.interfaces; - -import net.earthcomputer.clientcommands.command.VillagerCommand; -import net.earthcomputer.clientcommands.features.VillagerRngSimulator; - -import java.util.List; - -public interface IVillager { - VillagerRngSimulator clientcommands_getVillagerRngSimulator(); - - void clientcommands_onAmbientSoundPlayed(float pitch); - - void clientcommands_onNoSoundPlayed(float pitch); - - void clientcommands_onYesSoundPlayed(float pitch); - - void clientcommands_onSplashSoundPlayed(float pitch); - - void clientcommands_onXpOrbSpawned(int value); - - void clientcommands_onServerTick(); - - void clientcommands_onGuiOpened(List list); -} diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java new file mode 100644 index 000000000..58779f6bf --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java @@ -0,0 +1,74 @@ +package net.earthcomputer.clientcommands.mixin.commands.villager; + +import net.earthcomputer.clientcommands.command.ClientCommandHelper; +import net.earthcomputer.clientcommands.features.VillagerCracker; +import net.minecraft.client.Minecraft; +import net.minecraft.client.multiplayer.ClientLevel; +import net.minecraft.client.multiplayer.ClientPacketListener; +import net.minecraft.core.GlobalPos; +import net.minecraft.network.chat.Component; +import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; +import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; +import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; +import net.minecraft.network.protocol.game.ClientboundSetTimePacket; +import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.resources.ResourceKey; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.level.Level; +import net.minecraft.world.phys.Vec3; +import org.spongepowered.asm.mixin.Mixin; +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(ClientPacketListener.class) +public class ClientPacketListenerMixin { + @Shadow + private ClientLevel level; + + @Inject(method = "handleSoundEvent", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void onHandleSoundEvent(ClientboundSoundPacket packet, CallbackInfo ci) { + Villager targetVillager = VillagerCracker.getVillager(); + if (targetVillager != null) { + VillagerCracker.onSoundEventPlayed(packet, new Vec3(packet.getX(), packet.getY(), packet.getZ())); + } + } + + @Inject(method = "handleChunkBlocksUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void onHandleChunkBlocksUpdate(ClientboundSectionBlocksUpdatePacket packet, CallbackInfo ci) { + if (Minecraft.getInstance().level != null) { + ResourceKey key = Minecraft.getInstance().level.dimension(); + packet.runUpdates((pos, state) -> { + if (new GlobalPos(key, pos).equals(VillagerCracker.getClockPos())) { + VillagerCracker.onServerTick(); + } + }); + } + } + + @Inject(method = "handleAddExperienceOrb", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void onHandleAddExperienceOrb(ClientboundAddExperienceOrbPacket packet, CallbackInfo ci) { + Villager targetVillager = VillagerCracker.getVillager(); + if (targetVillager != null && new Vec3(packet.getX(), packet.getY() - 0.5, packet.getZ()).distanceToSqr(targetVillager.position()) <= 0.1f) { + VillagerCracker.onXpOrbSpawned(packet); + } + } + + @Inject(method = "handleBlockUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackInfo ci) { + if (Minecraft.getInstance().level != null && new GlobalPos(Minecraft.getInstance().level.dimension(), packet.getPos()).equals(VillagerCracker.getClockPos())) { + VillagerCracker.onServerTick(); + } + } + + @Inject(method = "handleSetTime", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) + private void handleSetTime(ClientboundSetTimePacket packet, CallbackInfo ci) { + if (level.getDayTime() < 12000 && packet.dayTime() >= 12000) { + Villager targetVillager = VillagerCracker.getVillager(); + if (targetVillager != null) { + ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); + } + } + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/MerchantScreenMixin.java similarity index 70% rename from src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java rename to src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/MerchantScreenMixin.java index ed5092889..0a5288a32 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/MerchantScreenMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/MerchantScreenMixin.java @@ -1,12 +1,10 @@ -package net.earthcomputer.clientcommands.mixin.rngevents; +package net.earthcomputer.clientcommands.mixin.commands.villager; import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerCracker; -import net.earthcomputer.clientcommands.interfaces.IVillager; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.MerchantScreen; import net.minecraft.network.chat.Component; -import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.inventory.MerchantMenu; import org.spongepowered.asm.mixin.Mixin; @@ -22,9 +20,6 @@ public MerchantScreenMixin(MerchantMenu menu, Inventory playerInventory, Compone @Inject(method = "render", at = @At("HEAD")) private void onRender(CallbackInfo ci) { - Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager instanceof IVillager iVillager) { - iVillager.clientcommands_onGuiOpened(menu.getOffers().stream().map(VillagerCommand.Offer::new).toList()); - } + VillagerCracker.onGuiOpened(menu.getOffers().stream().map(VillagerCracker.Offer::new).toList()); } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java deleted file mode 100644 index fb6136d45..000000000 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/VillagerMixin.java +++ /dev/null @@ -1,93 +0,0 @@ -package net.earthcomputer.clientcommands.mixin.commands.villager; - -import net.earthcomputer.clientcommands.command.PingCommand; -import net.earthcomputer.clientcommands.command.VillagerCommand; -import net.earthcomputer.clientcommands.features.VillagerCracker; -import net.earthcomputer.clientcommands.features.VillagerRngSimulator; -import net.earthcomputer.clientcommands.interfaces.IVillager; -import net.earthcomputer.clientcommands.util.CUtil; -import net.minecraft.client.Minecraft; -import net.minecraft.client.player.LocalPlayer; -import net.minecraft.network.protocol.game.ServerboundInteractPacket; -import net.minecraft.world.InteractionHand; -import net.minecraft.world.entity.EntityType; -import net.minecraft.world.entity.npc.AbstractVillager; -import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.entity.npc.VillagerProfession; -import net.minecraft.world.level.Level; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Unique; - -import java.util.List; - -@Mixin(Villager.class) -public abstract class VillagerMixin extends AbstractVillager implements IVillager { - public VillagerMixin(EntityType entityType, Level level) { - super(entityType, level); - } - - @Unique - VillagerRngSimulator simulator = new VillagerRngSimulator(null); - - @Override - public void clientcommands_onAmbientSoundPlayed(float pitch) { - simulator.onAmbientSoundPlayed(pitch); - } - - @Override - public void clientcommands_onNoSoundPlayed(float pitch) { - VillagerProfession profession = ((Villager) (Object) this).getVillagerData().getProfession(); - simulator.onNoSoundPlayed(pitch, profession != VillagerProfession.NONE && profession != VillagerProfession.NITWIT); - } - - @Override - public void clientcommands_onYesSoundPlayed(float pitch) { - simulator.onYesSoundPlayed(pitch); - } - - @Override - public void clientcommands_onSplashSoundPlayed(float pitch) { - simulator.onSplashSoundPlayed(pitch); - } - - @Override - public void clientcommands_onXpOrbSpawned(int value) { - simulator.onXpOrbSpawned(value); - } - - @Override - public void clientcommands_onServerTick() { - simulator.simulateTick(); - - if (VillagerCracker.isRunning() && !VillagerCracker.hasClickedVillager) { - int millisecondsUntilInteract = simulator.getTicksRemaining() * VillagerCracker.serverMspt - PingCommand.getLocalPing() + VillagerCracker.magicMillisecondCorrection; - if (millisecondsUntilInteract < 200) { - LocalPlayer oldPlayer = Minecraft.getInstance().player; - assert oldPlayer != null; - CUtil.sendAtPreciseTime( - System.nanoTime() + millisecondsUntilInteract * 1_000_000L, - ServerboundInteractPacket.createInteractionPacket(this, false, InteractionHand.MAIN_HAND), - () -> true, - () -> { - LocalPlayer player = Minecraft.getInstance().player; - if (player == oldPlayer) { - player.swing(InteractionHand.MAIN_HAND); - } - } - ); - simulator.reset(); - VillagerCracker.hasClickedVillager = true; - } - } - } - - @Override - public VillagerRngSimulator clientcommands_getVillagerRngSimulator() { - return simulator; - } - - @Override - public void clientcommands_onGuiOpened(List availableOffersList) { - simulator.onGuiOpened(availableOffersList, (Villager) (Object) this); - } -} diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java index d5a1a7889..cd0ff704f 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/rngevents/ClientPacketListenerMixin.java @@ -1,30 +1,15 @@ package net.earthcomputer.clientcommands.mixin.rngevents; import com.mojang.brigadier.StringReader; -import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.features.PlayerRandCracker; -import net.earthcomputer.clientcommands.features.VillagerCracker; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientPacketListener; -import net.minecraft.core.GlobalPos; -import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.*; -import net.minecraft.resources.ResourceKey; -import net.minecraft.world.entity.npc.Villager; -import net.minecraft.world.level.Level; -import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; -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(ClientPacketListener.class) public abstract class ClientPacketListenerMixin { - @Shadow - private ClientLevel level; - @Inject(method = "sendCommand", at = @At("HEAD")) private void onSendCommand(String command, CallbackInfo ci) { StringReader reader = new StringReader(command); @@ -33,49 +18,4 @@ private void onSendCommand(String command, CallbackInfo ci) { PlayerRandCracker.onGiveCommand(); } } - - @Inject(method = "handleSoundEvent", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) - private void onHandleSoundEvent(ClientboundSoundPacket packet, CallbackInfo ci) { - Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager != null) { - VillagerCracker.onSoundEventPlayed(packet, new Vec3(packet.getX(), packet.getY(), packet.getZ())); - } - } - - @Inject(method = "handleChunkBlocksUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) - private void onHandleChunkBlocksUpdate(ClientboundSectionBlocksUpdatePacket packet, CallbackInfo ci) { - if (Minecraft.getInstance().level != null) { - ResourceKey key = Minecraft.getInstance().level.dimension(); - packet.runUpdates((pos, state) -> { - if (new GlobalPos(key, pos).equals(VillagerCracker.getClockPos())) { - VillagerCracker.onServerTick(); - } - }); - } - } - - @Inject(method = "handleAddExperienceOrb", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) - private void onHandleAddExperienceOrb(ClientboundAddExperienceOrbPacket packet, CallbackInfo ci) { - Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager != null && new Vec3(packet.getX(), packet.getY() - 0.5, packet.getZ()).distanceToSqr(targetVillager.position()) <= 0.1f) { - VillagerCracker.onXpOrbSpawned(packet); - } - } - - @Inject(method = "handleBlockUpdate", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) - private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackInfo ci) { - if (Minecraft.getInstance().level != null && new GlobalPos(Minecraft.getInstance().level.dimension(), packet.getPos()).equals(VillagerCracker.getClockPos())) { - VillagerCracker.onServerTick(); - } - } - - @Inject(method = "handleSetTime", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) - private void handleSetTime(ClientboundSetTimePacket packet, CallbackInfo ci) { - if (level.getDayTime() < 12000 && packet.dayTime() >= 12000) { - Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager != null) { - ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); - } - } - } } diff --git a/src/main/java/net/earthcomputer/clientcommands/util/CUtil.java b/src/main/java/net/earthcomputer/clientcommands/util/CUtil.java index 40ec6757b..f3cc0c971 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/CUtil.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/CUtil.java @@ -8,6 +8,7 @@ import io.netty.buffer.Unpooled; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelPipeline; +import net.minecraft.advancements.critereon.MinMaxBounds; import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.core.Holder; @@ -67,6 +68,14 @@ public static void forEither(Either either, Consumer lef }); } + public static String boundsToString(MinMaxBounds bounds) { + StringBuilder sb = new StringBuilder(); + bounds.min().ifPresent(sb::append); + sb.append(".."); + bounds.max().ifPresent(sb::append); + return sb.toString(); + } + /** @noinspection OptionalIsPresent - no boxing! */ public static int getEnchantmentLevel(RegistryAccess registryAccess, ResourceKey enchantment, ItemStack stack) { Optional> enchHolder = registryAccess.lookupOrThrow(Registries.ENCHANTMENT).get(enchantment); diff --git a/src/main/java/net/earthcomputer/clientcommands/util/CombinedMedianEM.java b/src/main/java/net/earthcomputer/clientcommands/util/CombinedMedianEM.java index 9da361c90..f39396011 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/CombinedMedianEM.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/CombinedMedianEM.java @@ -34,13 +34,13 @@ public final class CombinedMedianEM { private double mu = 0.0; private double sigma = 500; - public void update(int mspt, int maxTicksBefore, int maxTicksAfter) { + public void update(int mspt, int consideredTickRange) { width = mspt; // width of time window considered // all of the data points for all samples are within this window - int beginTime = Mth.floor(mu + 0.5) - width / 2 - maxTicksBefore * width; - int endTime = Mth.floor(mu + 0.5) + width / 2 + maxTicksAfter * width; + int beginTime = Mth.floor(mu + 0.5) - width / 2 - (consideredTickRange / 2) * width; + int endTime = Mth.floor(mu + 0.5) + width / 2 + (consideredTickRange / 2) * width; double[] dropRate = new double[data.size()]; Arrays.setAll(dropRate, i -> (double) data.get(i).size() * width / (endTime - beginTime)); diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 0ddc4951c..f9de2c32c 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -261,7 +261,6 @@ "commands.cvillager.itemCountOutOfRange": "The specified item count range (%s) overlaps into an item count outside the maximum (%s)", "commands.cvillager.listGoals.noGoals": "There are no villager goals", "commands.cvillager.listGoals.success": "There are %s villager goals:", - "commands.cvillager.listGoals.success.one": "There is 1 villager goal:", "commands.cvillager.noCrackedVillagerPresent": "There was no cracked villager available to use", "commands.cvillager.noProfession": "The targeted villager has no profession", "commands.cvillager.notAVillager": "Target was not a villager", diff --git a/src/main/resources/mixins.clientcommands.json b/src/main/resources/mixins.clientcommands.json index a8e628645..837f75010 100644 --- a/src/main/resources/mixins.clientcommands.json +++ b/src/main/resources/mixins.clientcommands.json @@ -18,7 +18,6 @@ "commands.relog.ClientPacketListenerMixin", "commands.render.EntityRendererDispatcherMixin", "commands.time.ClientLevelDataMixin", - "commands.villager.VillagerMixin", "commands.weather.LevelMixin", "debug.EntityMixin", "debug.ServerLevelMixin", @@ -70,11 +69,12 @@ "commands.generic.CommandSuggestionsMixin", "commands.glow.LivingEntityRenderStateMixin", "commands.snap.MinecraftMixin", + "commands.villager.ClientPacketListenerMixin", + "commands.villager.MerchantScreenMixin", "dataqueryhandler.ClientPacketListenerMixin", "events.ClientPacketListenerMixin", "lengthextender.ChatScreenMixin", "rngevents.ClientLevelMixin", - "rngevents.MerchantScreenMixin", "scrambletitle.MinecraftMixin", "serverbrand.ClientCommonPacketListenerImplMixin", "suggestionshook.ClientPacketListenerMixin" From 40cec5b639263becaef059a5e6284e8dffdcfd14 Mon Sep 17 00:00:00 2001 From: joe Date: Wed, 27 Nov 2024 20:47:36 +0000 Subject: [PATCH 52/78] Fix compile --- .../arguments/ItemAndEnchantmentsPredicateArgument.java | 4 ++-- .../earthcomputer/clientcommands/features/FishingCracker.java | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java index 523abf68e..98f9ca55a 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java @@ -128,7 +128,7 @@ public ItemAndEnchantmentsPredicate parse(StringReader reader) throws CommandSyn return true; }; - return new ItemAndEnchantmentsPredicate(parser.item, predicate); + return new ItemAndEnchantmentsPredicate(parser.item, predicate, parser.with.size()); } @Override @@ -154,7 +154,7 @@ public Collection getExamples() { return EXAMPLES; } - public record ItemAndEnchantmentsPredicate(Item item, Predicate> predicate) implements Predicate { + public record ItemAndEnchantmentsPredicate(Item item, Predicate> predicate, int numEnchantments) implements Predicate { @Override public boolean test(ItemStack stack) { if (item != stack.getItem() && (item != Items.BOOK || stack.getItem() != Items.ENCHANTED_BOOK)) { diff --git a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java index e9cf639c5..ea9490801 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/FishingCracker.java @@ -424,7 +424,7 @@ record ErrorEntry(int tick, boolean isBox) {} LootTable fishingLootTable = MCLootTables.FISHING.get().apply(SeedfindingUtil.getMCVersion()); for (var goal : goals) { if (goal.value() instanceof ClientItemPredicateArgument.EnchantedItemPredicate predicate) { - if (predicate.isEnchantedBook() && predicate.predicate.with().size() >= 2) { + if (predicate.isEnchantedBook() && predicate.predicate.numEnchantments() >= 2) { if (!hasWarnedMultipleEnchants) { ClientCommandHelper.sendHelp(Component.translatable("commands.cfish.help.tooManyEnchants")); hasWarnedMultipleEnchants = true; From 8daca5be99177805c01f4a15b4eba1c00095febb Mon Sep 17 00:00:00 2001 From: joe Date: Wed, 27 Nov 2024 22:43:29 +0000 Subject: [PATCH 53/78] Improvements to cvillager command --- .../command/VillagerCommand.java | 104 ++++++++++-------- .../ItemAndEnchantmentsPredicateArgument.java | 17 ++- .../command/arguments/WithStringArgument.java | 8 +- .../features/VillagerCracker.java | 19 +++- .../assets/clientcommands/lang/en_us.json | 1 - 5 files changed, 96 insertions(+), 53 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index f0e56c9a5..cdbac1e48 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -5,8 +5,9 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType; import com.mojang.brigadier.exceptions.SimpleCommandExceptionType; -import dev.xpple.clientarguments.arguments.CRangeArgument; import net.earthcomputer.clientcommands.Configs; +import net.earthcomputer.clientcommands.command.arguments.ClientItemPredicateArgument; +import net.earthcomputer.clientcommands.command.arguments.ItemAndEnchantmentsPredicateArgument; import net.earthcomputer.clientcommands.command.arguments.WithStringArgument; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; @@ -31,14 +32,13 @@ import org.jetbrains.annotations.Nullable; import java.util.List; -import java.util.function.Predicate; import java.util.stream.Collectors; import static com.mojang.brigadier.arguments.IntegerArgumentType.*; import static dev.xpple.clientarguments.arguments.CBlockPosArgument.*; import static dev.xpple.clientarguments.arguments.CEntityArgument.*; -import static dev.xpple.clientarguments.arguments.CItemPredicateArgument.*; import static dev.xpple.clientarguments.arguments.CRangeArgument.*; +import static net.earthcomputer.clientcommands.command.arguments.ClientItemPredicateArgument.*; import static net.earthcomputer.clientcommands.command.arguments.ItemAndEnchantmentsPredicateArgument.*; import static net.earthcomputer.clientcommands.command.arguments.WithStringArgument.*; import static net.fabricmc.fabric.api.client.command.v2.ClientCommandManager.*; @@ -50,37 +50,35 @@ public class VillagerCommand { private static final SimpleCommandExceptionType NOT_LEVEL_1_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notLevel1")); private static final SimpleCommandExceptionType NO_GOALS_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.listGoals.noGoals")); private static final SimpleCommandExceptionType ALREADY_RUNNING_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.alreadyRunning")); - private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX_EXCEPTION = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", a, b)); - private static final Dynamic2CommandExceptionType ITEM_QUANTITY_OUT_OF_RANGE_EXCEPTION = new Dynamic2CommandExceptionType((a, b) -> Component.translatable("commands.cvillager.itemCountOutOfRange", a, b)); + private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX_EXCEPTION = new Dynamic2CommandExceptionType((index, length) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", index, length)); + private static final Dynamic2CommandExceptionType ITEM_OVERSTACKED_EXCEPTION = new Dynamic2CommandExceptionType((item, stackSize) -> Component.translatable("arguments.item.overstacked", item, stackSize)); public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { dispatcher.register(literal("cvillager") - .then(literal("add-two-item-goal") - .then(argument("first-item", withString(itemPredicate(context))) - .then(argument("first-count", intRange()) - .then(argument("result-item", withString(itemPredicate(context))) - .then(argument("result-count", intRange()) - .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "first-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "first-count"), null, null, getWithString(ctx, "result-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "result-count")))))))) - .then(literal("add-three-item-goal") - .then(argument("first-item", withString(itemPredicate(context))) - .then(argument("first-count", intRange()) - .then(argument("second-item", withString(itemPredicate(context))) - .then(argument("second-count", intRange()) - .then(argument("result-item", withString(itemPredicate(context))) - .then(argument("result-count", intRange()) - .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "first-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "first-count"), getWithString(ctx, "second-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "second-count"), getWithString(ctx, "result-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "result-count")))))))))) - .then(literal("add-two-item-enchanted-goal") - .then(argument("first-item", withString(itemPredicate(context))) - .then(argument("first-count", intRange()) - .then(argument("result-item", withString(itemAndEnchantmentsPredicate(context).withEnchantmentPredicate((item, enchantment) -> enchantment.is(EnchantmentTags.TRADEABLE)))) - .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "first-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "first-count"), null, null, getWithString(ctx, "result-item", ItemAndEnchantmentsPredicate.class), MinMaxBounds.Ints.between(1, 1))))))) - .then(literal("add-three-item-enchanted-goal") - .then(argument("first-item", withString(itemPredicate(context))) - .then(argument("first-count", intRange()) - .then(argument("second-item", withString(itemPredicate(context))) - .then(argument("second-count", intRange()) - .then(argument("result-item", withString(itemAndEnchantmentsPredicate(context).withEnchantmentPredicate((item, enchantment) -> enchantment.is(EnchantmentTags.TRADEABLE)))) - .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "first-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "first-count"), getWithString(ctx, "second-item", CItemStackPredicateArgument.class), CRangeArgument.Ints.getRangeArgument(ctx, "second-count"), getWithString(ctx, "result-item", ItemAndEnchantmentsPredicate.class), MinMaxBounds.Ints.between(1, 1))))))))) + .then(literal("add-goal") + .then(argument("result", withString(clientItemPredicate(context))) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "result", ClientItemPredicateArgument.ClientItemPredicate.class), MinMaxBounds.Ints.ANY, null, MinMaxBounds.Ints.ANY, null, MinMaxBounds.Ints.ANY)) + .then(argument("result-count", intRange()) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "result", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "result-count"), null, MinMaxBounds.Ints.ANY, null, MinMaxBounds.Ints.ANY)) + .then(argument("input", withString(clientItemPredicate(context))) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "result", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "result-count"), getWithString(ctx, "input", ClientItemPredicateArgument.ClientItemPredicate.class), MinMaxBounds.Ints.ANY, null, MinMaxBounds.Ints.ANY)) + .then(argument("input-count", intRange()) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "result", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "result-count"), getWithString(ctx, "input", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "input-count"), null, MinMaxBounds.Ints.ANY)) + .then(argument("second-input", withString(clientItemPredicate(context))) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "result", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "result-count"), getWithString(ctx, "input", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "input-count"), getWithString(ctx, "second-input", ClientItemPredicateArgument.ClientItemPredicate.class), MinMaxBounds.Ints.ANY)) + .then(argument("second-input-count", intRange()) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "result", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "result-count"), getWithString(ctx, "input", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "input-count"), getWithString(ctx, "second-input", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "second-input-count")))))))))) + .then(literal("add-enchanted-goal") + .then(argument("result", withString(itemAndEnchantmentsPredicate(context).withSuffix("from").withEnchantmentPredicate((item, ench) -> ench.is(EnchantmentTags.TRADEABLE)))) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "result", ItemAndEnchantmentsPredicateArgument.ItemAndEnchantmentsPredicate.class).map(ClientItemPredicateArgument.EnchantedItemPredicate::new), MinMaxBounds.Ints.ANY, null, MinMaxBounds.Ints.ANY, null, MinMaxBounds.Ints.ANY)) + .then(argument("input", withString(clientItemPredicate(context))) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "result", ItemAndEnchantmentsPredicateArgument.ItemAndEnchantmentsPredicate.class).map(ClientItemPredicateArgument.EnchantedItemPredicate::new), MinMaxBounds.Ints.ANY, getWithString(ctx, "input", ClientItemPredicateArgument.ClientItemPredicate.class), MinMaxBounds.Ints.ANY, null, MinMaxBounds.Ints.ANY)) + .then(argument("input-count", intRange()) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "result", ItemAndEnchantmentsPredicateArgument.ItemAndEnchantmentsPredicate.class).map(ClientItemPredicateArgument.EnchantedItemPredicate::new), MinMaxBounds.Ints.ANY, getWithString(ctx, "input", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "input-count"), null, MinMaxBounds.Ints.ANY)) + .then(argument("second-input", withString(clientItemPredicate(context))) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "result", ItemAndEnchantmentsPredicateArgument.ItemAndEnchantmentsPredicate.class).map(ClientItemPredicateArgument.EnchantedItemPredicate::new), MinMaxBounds.Ints.ANY, getWithString(ctx, "input", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "input-count"), getWithString(ctx, "second-input", ClientItemPredicateArgument.ClientItemPredicate.class), MinMaxBounds.Ints.ANY)) + .then(argument("second-input-count", intRange()) + .executes(ctx -> addGoal(ctx.getSource(), getWithString(ctx, "result", ItemAndEnchantmentsPredicateArgument.ItemAndEnchantmentsPredicate.class).map(ClientItemPredicateArgument.EnchantedItemPredicate::new), MinMaxBounds.Ints.ANY, getWithString(ctx, "input", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "input-count"), getWithString(ctx, "second-input", ClientItemPredicateArgument.ClientItemPredicate.class), Ints.getRangeArgument(ctx, "second-input-count"))))))))) .then(literal("list-goals") .executes(ctx -> listGoals(ctx.getSource()))) .then(literal("remove-goal") @@ -106,32 +104,50 @@ public static void register(CommandDispatcher dispatc private static int addGoal( FabricClientCommandSource ctx, - WithStringArgument.Result> first, + Result result, + MinMaxBounds.Ints resultCount, + @Nullable WithStringArgument.Result first, MinMaxBounds.Ints firstCount, - @Nullable WithStringArgument.Result> second, - @Nullable MinMaxBounds.Ints secondCount, - Result> result, - MinMaxBounds.Ints resultCount - ) { - String firstString = first.string() + " " + CUtil.boundsToString(firstCount); - String secondString = second == null || secondCount == null ? null : second.string() + " " + CUtil.boundsToString(secondCount); + @Nullable WithStringArgument.Result second, + MinMaxBounds.Ints secondCount + ) throws CommandSyntaxException { + checkStackSize(result, resultCount); + if (first != null) { + checkStackSize(first, firstCount); + } + if (second != null) { + checkStackSize(second, secondCount); + } + + String firstString = first == null ? null : first.string() + " " + CUtil.boundsToString(firstCount); + String secondString = second == null ? null : second.string() + " " + CUtil.boundsToString(secondCount); String resultString = result.string() + " " + CUtil.boundsToString(resultCount); VillagerCracker.goals.add(new VillagerCracker.Goal( + resultString, + item -> result.value().test(item) && resultCount.matches(item.getCount()), + firstString, - item -> first.value().test(item) && firstCount.matches(item.getCount()), + first == null ? null : item -> first.value().test(item) && firstCount.matches(item.getCount()), secondString, - second == null || secondCount == null ? null : item -> second.value().test(item) && secondCount.matches(item.getCount()), - - resultString, - item -> result.value().test(item) && resultCount.matches(item.getCount()) + second == null ? null : item -> second.value().test(item) && secondCount.matches(item.getCount()) )); ctx.sendFeedback(Component.translatable("commands.cvillager.goalAdded")); return Command.SINGLE_SUCCESS; } + private static void checkStackSize(WithStringArgument.Result itemPredicate, MinMaxBounds.Ints count) throws CommandSyntaxException { + int maxCount = itemPredicate.value().getPossibleItems().stream().mapToInt(Item::getDefaultMaxStackSize).max().orElse(Item.DEFAULT_MAX_STACK_SIZE); + if (count.min().isPresent() && count.min().get() > maxCount) { + throw ITEM_OVERSTACKED_EXCEPTION.create(itemPredicate.string(), maxCount); + } + if (count.max().isPresent() && count.max().get() > maxCount) { + throw ITEM_OVERSTACKED_EXCEPTION.create(itemPredicate.string(), maxCount); + } + } + private static int listGoals(FabricClientCommandSource source) { if (VillagerCracker.goals.isEmpty()) { source.sendFeedback(Component.translatable("commands.cvillager.listGoals.noGoals").withStyle(style -> style.withColor(ChatFormatting.RED))); diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java index 98f9ca55a..d9a13dc69 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/ItemAndEnchantmentsPredicateArgument.java @@ -52,6 +52,8 @@ public class ItemAndEnchantmentsPredicateArgument implements ArgumentType itemPredicate = item -> true; private BiPredicate> enchantmentPredicate = (item, ench) -> true; private boolean constrainMaxLevel = false; + @Nullable + private String suffix; private ItemAndEnchantmentsPredicateArgument(HolderLookup.Provider holderLookupProvider) { this.enchantmentLookup = holderLookupProvider.lookupOrThrow(Registries.ENCHANTMENT); @@ -76,6 +78,11 @@ public ItemAndEnchantmentsPredicateArgument constrainMaxLevel() { return this; } + public ItemAndEnchantmentsPredicateArgument withSuffix(String suffix) { + this.suffix = suffix; + return this; + } + public static ItemAndEnchantmentsPredicate getItemAndEnchantmentsPredicate(CommandContext context, String name) { return context.getArgument(name, ItemAndEnchantmentsPredicate.class); } @@ -222,6 +229,10 @@ private boolean parseEnchantmentInstancePredicate() throws CommandSyntaxExceptio return false; } + if (option == Option.SUFFIX) { + return false; + } + boolean suggest = reader.canRead(); if (option == Option.EXACT) { exact = true; @@ -258,6 +269,7 @@ private enum Option { WITHOUT, EXACT, ORDERED, + SUFFIX, } @Nullable @@ -269,7 +281,7 @@ private Option parseOption() { case "without" -> Option.WITHOUT; case "exactly" -> exact ? null : Option.EXACT; case "ordered" -> ordered || MultiVersionCompat.INSTANCE.getProtocolVersion() >= MultiVersionCompat.V1_21 ? null : Option.ORDERED; - default -> null; + default -> option.equals(suffix) ? Option.SUFFIX : null; }; } @@ -453,6 +465,9 @@ private void suggestOption() { if (!ordered && MultiVersionCompat.INSTANCE.getProtocolVersion() < MultiVersionCompat.V1_21) { validOptions.add("ordered"); } + if (suffix != null) { + validOptions.add(suffix); + } SharedSuggestionProvider.suggest(validOptions, builder); suggestions.add(builder); }; diff --git a/src/main/java/net/earthcomputer/clientcommands/command/arguments/WithStringArgument.java b/src/main/java/net/earthcomputer/clientcommands/command/arguments/WithStringArgument.java index 614decfb0..23a36643e 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/arguments/WithStringArgument.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/arguments/WithStringArgument.java @@ -6,10 +6,10 @@ import com.mojang.brigadier.exceptions.CommandSyntaxException; import com.mojang.brigadier.suggestion.Suggestions; import com.mojang.brigadier.suggestion.SuggestionsBuilder; -import org.apache.commons.lang3.tuple.Pair; import java.util.Collection; import java.util.concurrent.CompletableFuture; +import java.util.function.Function; public class WithStringArgument implements ArgumentType> { @@ -46,5 +46,9 @@ public Collection getExamples() { return delegate.getExamples(); } - public record Result(String string, T value) {} + public record Result(String string, T value) { + public Result map(Function mapper) { + return new Result<>(string, mapper.apply(value)); + } + } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 5fb0f868d..79cb833db 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -324,16 +324,25 @@ public static void stopRunning() { targetOffer = null; } - public record Goal(String firstString, Predicate first, @Nullable String secondString, @Nullable Predicate second, String resultString, Predicate result) { + public record Goal( + String resultString, + Predicate result, + @Nullable String firstString, + @Nullable Predicate first, + @Nullable String secondString, + @Nullable Predicate second + ) { public boolean matches(Offer offer) { - return first.test(offer.first) - && ((second == null && offer.second == null) || offer.second != null && second != null && second.test(offer.second)) - && result.test(offer.result); + return result.test(offer.result) + && (first == null || first.test(offer.first)) + && (second == null || (offer.second != null && second.test(offer.second))); } @Override public String toString() { - if (secondString == null) { + if (firstString == null) { + return resultString; + } else if (secondString == null) { return String.format("%s = %s", firstString, resultString); } else { return String.format("%s + %s = %s", firstString, secondString, resultString); diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index f9de2c32c..f275bca14 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -258,7 +258,6 @@ "commands.cvillager.help.tooFast": "Help: villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running faster", "commands.cvillager.help.tooSlow": "Help: villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running slower", "commands.cvillager.inSync": "Your villager's RNG is cracked", - "commands.cvillager.itemCountOutOfRange": "The specified item count range (%s) overlaps into an item count outside the maximum (%s)", "commands.cvillager.listGoals.noGoals": "There are no villager goals", "commands.cvillager.listGoals.success": "There are %s villager goals:", "commands.cvillager.noCrackedVillagerPresent": "There was no cracked villager available to use", From 31837d427d88b2731ee6e402701e50c61952c0da Mon Sep 17 00:00:00 2001 From: joe Date: Wed, 27 Nov 2024 23:03:48 +0000 Subject: [PATCH 54/78] Add fishingManipulation config --- .../earthcomputer/clientcommands/Configs.java | 17 ++++++- .../command/VillagerCommand.java | 48 ++++++++++++++----- .../features/VillagerCracker.java | 14 ++++-- .../assets/clientcommands/lang/en_us.json | 1 + 4 files changed, 63 insertions(+), 17 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/Configs.java b/src/main/java/net/earthcomputer/clientcommands/Configs.java index e31d84f75..c99d8c77f 100644 --- a/src/main/java/net/earthcomputer/clientcommands/Configs.java +++ b/src/main/java/net/earthcomputer/clientcommands/Configs.java @@ -6,6 +6,7 @@ import net.earthcomputer.clientcommands.features.FishingCracker; import net.earthcomputer.clientcommands.features.PlayerRandCracker; import net.earthcomputer.clientcommands.features.ServerBrandManager; +import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.util.MultiVersionCompat; import net.minecraft.util.Mth; import net.minecraft.util.StringRepresentable; @@ -174,7 +175,21 @@ public enum PacketDumpMethod { @Config public static int maximumPacketFieldDepth = 10; - @Config(temporary = true, setter = @Config.Setter("setMaxVillagerBruteForceSimulationTicks")) + @Config(setter = @Config.Setter("setVillagerManipulation"), temporary = true) + private static boolean villagerManipulation = false; + public static boolean getVillagerManipulation() { + return villagerManipulation; + } + public static void setVillagerManipulation(boolean villagerManipulation) { + Configs.villagerManipulation = villagerManipulation; + if (villagerManipulation) { + ServerBrandManager.rngWarning(); + } else { + VillagerCracker.reset(); + } + } + + @Config(setter = @Config.Setter("setMaxVillagerBruteForceSimulationTicks"), temporary = true) public static int maxVillagerBruteForceSimulationTicks = 12000; public static void setMaxVillagerBruteForceSimulationTicks(int maxVillagerBruteForceSimulationTicks) { Configs.maxVillagerBruteForceSimulationTicks = Mth.clamp(maxVillagerBruteForceSimulationTicks, 0, 1_000_000); diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index cdbac1e48..9d80a1282 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -38,6 +38,7 @@ import static dev.xpple.clientarguments.arguments.CBlockPosArgument.*; import static dev.xpple.clientarguments.arguments.CEntityArgument.*; import static dev.xpple.clientarguments.arguments.CRangeArgument.*; +import static net.earthcomputer.clientcommands.command.ClientCommandHelper.*; import static net.earthcomputer.clientcommands.command.arguments.ClientItemPredicateArgument.*; import static net.earthcomputer.clientcommands.command.arguments.ItemAndEnchantmentsPredicateArgument.*; import static net.earthcomputer.clientcommands.command.arguments.WithStringArgument.*; @@ -52,6 +53,10 @@ public class VillagerCommand { private static final SimpleCommandExceptionType ALREADY_RUNNING_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.alreadyRunning")); private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX_EXCEPTION = new Dynamic2CommandExceptionType((index, length) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", index, length)); private static final Dynamic2CommandExceptionType ITEM_OVERSTACKED_EXCEPTION = new Dynamic2CommandExceptionType((item, stackSize) -> Component.translatable("arguments.item.overstacked", item, stackSize)); + private static final SimpleCommandExceptionType NEED_VILLAGER_MANIPULATION_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.needVillagerManipulation") + .withStyle(ChatFormatting.RED) + .append(" ") + .append(getCommandTextComponent("commands.client.enable", "/cconfig clientcommands villagerManipulation set true"))); public static void register(CommandDispatcher dispatcher, CommandBuildContext context) { dispatcher.register(literal("cvillager") @@ -92,8 +97,6 @@ public static void register(CommandDispatcher dispatc .executes(ctx -> getClockPos()) .then(argument("pos", blockPos()) .executes(ctx -> setClockPos(ctx.getSource(), getBlockPos(ctx, "pos"))))) - .then(literal("reset-cracker") - .executes(ctx -> resetCracker())) .then(literal("start") .executes(ctx -> start(false)) .then(literal("first-level") @@ -119,6 +122,10 @@ private static int addGoal( checkStackSize(second, secondCount); } + if (!Configs.getVillagerManipulation()) { + throw NEED_VILLAGER_MANIPULATION_EXCEPTION.create(); + } + String firstString = first == null ? null : first.string() + " " + CUtil.boundsToString(firstCount); String secondString = second == null ? null : second.string() + " " + CUtil.boundsToString(secondCount); String resultString = result.string() + " " + CUtil.boundsToString(resultCount); @@ -148,7 +155,11 @@ private static void checkStackSize(WithStringArgument.Result style.withColor(ChatFormatting.RED))); } else { @@ -162,6 +173,10 @@ private static int listGoals(FabricClientCommandSource source) { } private static int removeGoal(FabricClientCommandSource source, int index) throws CommandSyntaxException { + if (!Configs.getVillagerManipulation()) { + throw NEED_VILLAGER_MANIPULATION_EXCEPTION.create(); + } + index = index - 1; if (index < VillagerCracker.goals.size()) { VillagerCracker.Goal goal = VillagerCracker.goals.remove(index); @@ -173,6 +188,10 @@ private static int removeGoal(FabricClientCommandSource source, int index) throw } private static int setVillagerTarget(@Nullable Entity target) throws CommandSyntaxException { + if (!Configs.getVillagerManipulation()) { + throw NEED_VILLAGER_MANIPULATION_EXCEPTION.create(); + } + if (target instanceof Villager villager) { VillagerCracker.setTargetVillager(villager); ClientCommandHelper.sendFeedback("commands.cvillager.target.set"); @@ -186,7 +205,11 @@ private static int setVillagerTarget(@Nullable Entity target) throws CommandSynt return Command.SINGLE_SUCCESS; } - private static int getClockPos() { + private static int getClockPos() throws CommandSyntaxException { + if (!Configs.getVillagerManipulation()) { + throw NEED_VILLAGER_MANIPULATION_EXCEPTION.create(); + } + GlobalPos pos = VillagerCracker.getClockPos(); if (pos == null) { ClientCommandHelper.sendFeedback("commands.cvillager.clock.cleared"); @@ -196,7 +219,11 @@ private static int getClockPos() { return Command.SINGLE_SUCCESS; } - private static int setClockPos(FabricClientCommandSource ctx, BlockPos pos) { + private static int setClockPos(FabricClientCommandSource ctx, BlockPos pos) throws CommandSyntaxException { + if (!Configs.getVillagerManipulation()) { + throw NEED_VILLAGER_MANIPULATION_EXCEPTION.create(); + } + ResourceKey dimension = ctx.getWorld().dimension(); VillagerCracker.setClockPos(pos == null ? null : new GlobalPos(dimension, pos)); if (pos == null) { @@ -207,14 +234,11 @@ private static int setClockPos(FabricClientCommandSource ctx, BlockPos pos) { return Command.SINGLE_SUCCESS; } - private static int resetCracker() { - VillagerCracker.simulator.reset(); - ClientCommandHelper.sendFeedback("commands.cvillager.resetCracker"); - - return Command.SINGLE_SUCCESS; - } - private static int start(boolean levelUp) throws CommandSyntaxException { + if (!Configs.getVillagerManipulation()) { + throw NEED_VILLAGER_MANIPULATION_EXCEPTION.create(); + } + Villager targetVillager = VillagerCracker.getVillager(); if (VillagerCracker.goals.isEmpty()) { diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 79cb833db..ae9effaa1 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -4,6 +4,7 @@ import it.unimi.dsi.fastutil.doubles.DoubleList; import it.unimi.dsi.fastutil.ints.IntArrayList; import it.unimi.dsi.fastutil.ints.IntList; +import net.earthcomputer.clientcommands.Configs; import net.earthcomputer.clientcommands.command.ClientCommandHelper; import net.earthcomputer.clientcommands.command.PingCommand; import net.earthcomputer.clientcommands.command.VillagerCommand; @@ -163,7 +164,7 @@ public static void onXpOrbSpawned(ClientboundAddExperienceOrbPacket packet) { private static void onTimeSync() { long now = System.nanoTime(); - if (getVillager() != null && clockPos != null && !isNewClock && clockTicksSinceLastTimeSync != 20) { + if (Configs.getVillagerManipulation() && clockPos != null && !isNewClock && clockTicksSinceLastTimeSync != 20) { if (now - lastClockRateWarning >= 60_000_000_000L) { if (clockTicksSinceLastTimeSync < 20) { ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.tooSlow")); @@ -225,9 +226,7 @@ private static void onDisconnect() { }); } - clockPos = null; - villagerUuid = null; - VillagerCracker.stopRunning(); + reset(); } private static int[] possibleTicksAhead(Offer[] actualOffers, VillagerRngSimulator.SurroundingOffers surroundingOffers) { @@ -316,6 +315,13 @@ public static void onGuiOpened(List actualOffersList) { } } + public static void reset() { + simulator.reset(); + clockPos = null; + villagerUuid = null; + stopRunning(); + } + public static boolean isRunning() { return targetOffer != null; } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index f275bca14..f7c93511e 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -260,6 +260,7 @@ "commands.cvillager.inSync": "Your villager's RNG is cracked", "commands.cvillager.listGoals.noGoals": "There are no villager goals", "commands.cvillager.listGoals.success": "There are %s villager goals:", + "commands.cvillager.needVillagerManipulation": "Villager manipulation is not enabled", "commands.cvillager.noCrackedVillagerPresent": "There was no cracked villager available to use", "commands.cvillager.noProfession": "The targeted villager has no profession", "commands.cvillager.notAVillager": "Target was not a villager", From 0119a5268bc2c851a146d28faaa649082b7d85d8 Mon Sep 17 00:00:00 2001 From: RTTV Date: Wed, 27 Nov 2024 19:00:20 -0500 Subject: [PATCH 55/78] added faux task for villager cracking --- .../command/VillagerCommand.java | 31 ++++++++++++++ .../features/VillagerCracker.java | 41 +++++++++---------- .../features/VillagerRngSimulator.java | 9 +++- 3 files changed, 58 insertions(+), 23 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 9d80a1282..58d8366d1 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -11,6 +11,8 @@ import net.earthcomputer.clientcommands.command.arguments.WithStringArgument; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; +import net.earthcomputer.clientcommands.task.LongTask; +import net.earthcomputer.clientcommands.task.TaskManager; import net.earthcomputer.clientcommands.util.CUtil; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.ChatFormatting; @@ -287,6 +289,35 @@ private static int start(boolean levelUp) throws CommandSyntaxException { VillagerCracker.surroundingOffers = surroundingOffers; VillagerCracker.hasClickedVillager = false; VillagerCracker.simulator.setTicksUntilBruteForceInteract(ticks); + TaskManager.addTask("cvillagerBruteForce", new LongTask() { + @Override + public void initialize() { + } + + @Override + public boolean condition() { + return VillagerCracker.isRunning() && VillagerCracker.simulator.getTicksRemaining() > 0; + } + + @Override + public void increment() { + } + + @Override + public void body() { + VillagerCracker.simulator.updateProgressBar(); + scheduleDelay(); + } + + @Override + public void onCompleted() { + // check if `onCompleted` was cancelled + if (condition()) { + VillagerCracker.stopRunning(); + ClientCommandHelper.addOverlayMessage(Component.empty(), 0); + } + } + }); return Command.SINGLE_SUCCESS; } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index ae9effaa1..f8f338daa 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -118,16 +118,16 @@ public static void setTargetVillager(@Nullable Villager villager) { ClientLevel level = Minecraft.getInstance().level; - if (level.getDayTime() % 24000 < 12000) { + if (level.getDayTime() % 24000 < 12000) { // todo, double check this works ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); } - VillagerCracker.cachedVillager = new WeakReference<>(villager); - VillagerCracker.villagerUuid = villager == null ? null : villager.getUUID(); + cachedVillager = new WeakReference<>(villager); + villagerUuid = villager == null ? null : villager.getUUID(); } public static void setClockPos(@Nullable GlobalPos pos) { - VillagerCracker.clockPos = pos; + clockPos = pos; if (pos != null) { isNewClock = true; } @@ -190,9 +190,6 @@ public static void onServerTick() { } simulator.simulateTick(); - if (isRunning()) { - simulator.updateProgressBar(); - } if (isRunning() && !hasClickedVillager) { int millisecondsUntilInteract = simulator.getTicksRemaining() * serverMspt - PingCommand.getLocalPing() + magicMillisecondCorrection; @@ -210,7 +207,7 @@ public static void onServerTick() { } } ); - simulator.reset(); + simulator.resetBruteForceState(); hasClickedVillager = true; } } @@ -273,8 +270,8 @@ public static void onGuiOpened(List actualOffersList) { return; } - if (VillagerCracker.isRunning()) { - int[] possibleTicksAhead = possibleTicksAhead(actualOffersList.toArray(Offer[]::new), VillagerCracker.surroundingOffers); + if (isRunning()) { + int[] possibleTicksAhead = possibleTicksAhead(actualOffersList.toArray(Offer[]::new), surroundingOffers); // chop possible ticks ahead into a limited reasonable range final int consideredTickRange = 21; int lowerIndex = Arrays.binarySearch(possibleTicksAhead, -consideredTickRange / 2); @@ -287,30 +284,32 @@ public static void onGuiOpened(List actualOffersList) { } possibleTicksAhead = Arrays.copyOfRange(possibleTicksAhead, lowerIndex, upperIndex + 1); - int prevCorrection = VillagerCracker.magicMillisecondCorrection; + int prevCorrection = magicMillisecondCorrection; if (possibleTicksAhead.length > 0) { - if (VillagerCracker.combinedMedianEM.data.size() >= 10) { - VillagerCracker.combinedMedianEM.data.removeFirst(); + if (combinedMedianEM.data.size() >= 10) { + combinedMedianEM.data.removeFirst(); } DoubleList possibleMillisecondsAhead = new DoubleArrayList(possibleTicksAhead.length); for (int ticksAhead : possibleTicksAhead) { - possibleMillisecondsAhead.add(ticksAhead * VillagerCracker.serverMspt + VillagerCracker.magicMillisecondCorrection); + possibleMillisecondsAhead.add(ticksAhead * serverMspt + magicMillisecondCorrection); } - VillagerCracker.combinedMedianEM.data.add(possibleMillisecondsAhead); - VillagerCracker.maxTicksBefore = Math.max(VillagerCracker.maxTicksBefore, -possibleTicksAhead[0]); - VillagerCracker.maxTicksAfter = Math.max(VillagerCracker.maxTicksAfter, possibleTicksAhead[possibleTicksAhead.length - 1]); - VillagerCracker.combinedMedianEM.update(VillagerCracker.serverMspt, consideredTickRange); - VillagerCracker.magicMillisecondCorrection = (int) Math.round(VillagerCracker.combinedMedianEM.getResult()); + combinedMedianEM.data.add(possibleMillisecondsAhead); + maxTicksBefore = Math.max(maxTicksBefore, -possibleTicksAhead[0]); + maxTicksAfter = Math.max(maxTicksAfter, possibleTicksAhead[possibleTicksAhead.length - 1]); + combinedMedianEM.update(serverMspt, consideredTickRange); + magicMillisecondCorrection = (int) Math.round(combinedMedianEM.getResult()); } - if (actualOffersList.contains(VillagerCracker.targetOffer)) { + if (actualOffersList.contains(targetOffer)) { ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.success", prevCorrection).withStyle(ChatFormatting.GREEN)); player.playNotifySound(SoundEvents.NOTE_BLOCK_PLING.value(), SoundSource.PLAYERS, 1.0f, 2.0f); } else { - ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.failure", prevCorrection, VillagerCracker.magicMillisecondCorrection).withStyle(ChatFormatting.RED)); + ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.failure", prevCorrection, magicMillisecondCorrection).withStyle(ChatFormatting.RED)); player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); } + ClientCommandHelper.addOverlayMessage(Component.empty(), 0); + simulator.reset(); stopRunning(); } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index d6e97143e..1f2eaf93c 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -228,6 +228,11 @@ public void reset() { seedsFromTwoPitches = null; } + public void resetBruteForceState() { + totalTicksInBruteForce = 0; + tickCount = 0; + } + @Override public String toString() { return "VillagerRngSimulator[seed=" + (random == null ? "null" : random.getSeed()) + ']'; @@ -246,7 +251,7 @@ public void onAmbientSoundPlayed(float pitch) { firstPitch = pitch; ambientSoundTime = -80; if (!justReset) { - ClientCommandHelper.addOverlayMessage(((MutableComponent) getCrackedState().getMessage(false)).withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(getCrackedState().getMessage(false).withStyle(ChatFormatting.RED), 100); } return; } @@ -506,7 +511,7 @@ public boolean isCracked() { return this == CRACKED; } - public Component getMessage(boolean addColor) { + public MutableComponent getMessage(boolean addColor) { return switch (this) { case UNCRACKED -> Component.translatable("commands.cvillager.partiallyCracked").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); case CRACKED -> Component.translatable("commands.cvillager.inSync").withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); From b3345f043df08ef0eba4d622ec370de0f1bbec7b Mon Sep 17 00:00:00 2001 From: RTTV Date: Wed, 27 Nov 2024 19:01:25 -0500 Subject: [PATCH 56/78] fine then earth --- .../earthcomputer/clientcommands/command/VillagerCommand.java | 1 - .../earthcomputer/clientcommands/features/VillagerCracker.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 58d8366d1..21e7b1868 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -314,7 +314,6 @@ public void onCompleted() { // check if `onCompleted` was cancelled if (condition()) { VillagerCracker.stopRunning(); - ClientCommandHelper.addOverlayMessage(Component.empty(), 0); } } }); diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index f8f338daa..05e08bee8 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -308,7 +308,6 @@ public static void onGuiOpened(List actualOffersList) { player.playNotifySound(SoundEvents.NOTE_BLOCK_BASS.value(), SoundSource.PLAYERS, 1.0f, 1.0f); } - ClientCommandHelper.addOverlayMessage(Component.empty(), 0); simulator.reset(); stopRunning(); } From 94e2b5d53bc585c4b9ca75dd4f9b5be98437be8a Mon Sep 17 00:00:00 2001 From: RTTV Date: Wed, 27 Nov 2024 19:02:12 -0500 Subject: [PATCH 57/78] safer choice --- .../earthcomputer/clientcommands/command/VillagerCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 21e7b1868..6ca249e33 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -296,7 +296,7 @@ public void initialize() { @Override public boolean condition() { - return VillagerCracker.isRunning() && VillagerCracker.simulator.getTicksRemaining() > 0; + return VillagerCracker.isRunning(); } @Override From abcb7bd7584c20c0ed4addfd4aa22fff223bd237 Mon Sep 17 00:00:00 2001 From: RTTV Date: Wed, 27 Nov 2024 19:03:41 -0500 Subject: [PATCH 58/78] oh thats handy --- .../clientcommands/command/VillagerCommand.java | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 6ca249e33..21c2f5afb 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -12,6 +12,7 @@ import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; import net.earthcomputer.clientcommands.task.LongTask; +import net.earthcomputer.clientcommands.task.SimpleTask; import net.earthcomputer.clientcommands.task.TaskManager; import net.earthcomputer.clientcommands.util.CUtil; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; @@ -289,24 +290,15 @@ private static int start(boolean levelUp) throws CommandSyntaxException { VillagerCracker.surroundingOffers = surroundingOffers; VillagerCracker.hasClickedVillager = false; VillagerCracker.simulator.setTicksUntilBruteForceInteract(ticks); - TaskManager.addTask("cvillagerBruteForce", new LongTask() { - @Override - public void initialize() { - } - + TaskManager.addTask("cvillagerBruteForce", new SimpleTask() { @Override public boolean condition() { return VillagerCracker.isRunning(); } @Override - public void increment() { - } - - @Override - public void body() { + protected void onTick() { VillagerCracker.simulator.updateProgressBar(); - scheduleDelay(); } @Override From 8277f6f015680b645e4993b4080a4d53dbaefcd7 Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 28 Nov 2024 16:21:03 -0500 Subject: [PATCH 59/78] removed usages of the term brute force where it wasn't applicable --- .../earthcomputer/clientcommands/Configs.java | 8 +++---- .../command/VillagerCommand.java | 9 ++++---- .../features/VillagerCracker.java | 2 +- .../features/VillagerRngSimulator.java | 22 +++++++++---------- 4 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/Configs.java b/src/main/java/net/earthcomputer/clientcommands/Configs.java index 995d02aed..9cdc1ef1f 100644 --- a/src/main/java/net/earthcomputer/clientcommands/Configs.java +++ b/src/main/java/net/earthcomputer/clientcommands/Configs.java @@ -192,9 +192,9 @@ public static void setVillagerManipulation(boolean villagerManipulation) { } } - @Config(setter = @Config.Setter("setMaxVillagerBruteForceSimulationTicks"), temporary = true) - public static int maxVillagerBruteForceSimulationTicks = 12000; - public static void setMaxVillagerBruteForceSimulationTicks(int maxVillagerBruteForceSimulationTicks) { - Configs.maxVillagerBruteForceSimulationTicks = Mth.clamp(maxVillagerBruteForceSimulationTicks, 0, 1_000_000); + @Config(setter = @Config.Setter("setMaxVillagerSimulationTicks"), temporary = true) + public static int maxVillagerSimulationTicks = 12000; + public static void setMaxVillagerSimulationTicks(int maxVillagerSimulationTicks) { + Configs.maxVillagerSimulationTicks = Mth.clamp(maxVillagerSimulationTicks, 0, 1_000_000); } } diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 21c2f5afb..65de5f994 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -11,7 +11,6 @@ import net.earthcomputer.clientcommands.command.arguments.WithStringArgument; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.earthcomputer.clientcommands.features.VillagerRngSimulator; -import net.earthcomputer.clientcommands.task.LongTask; import net.earthcomputer.clientcommands.task.SimpleTask; import net.earthcomputer.clientcommands.task.TaskManager; import net.earthcomputer.clientcommands.util.CUtil; @@ -270,9 +269,9 @@ private static int start(boolean levelUp) throws CommandSyntaxException { VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(crackedLevel, new VillagerTrades.ItemListing[0]); int adjustmentTicks = levelUp ? -40 : 0; - VillagerRngSimulator.BruteForceResult result = VillagerCracker.simulator.bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerBruteForceSimulationTicks, offer -> VillagerCracker.goals.stream().anyMatch(goal -> goal.matches(offer))); + VillagerRngSimulator.OfferWaitingResult result = VillagerCracker.simulator.bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerSimulationTicks, offer -> VillagerCracker.goals.stream().anyMatch(goal -> goal.matches(offer))); if (result == null) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerBruteForceSimulationTicks).withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerSimulationTicks).withStyle(ChatFormatting.RED), 100); return Command.SINGLE_SUCCESS; } VillagerRngSimulator.SurroundingOffers surroundingOffers = VillagerCracker.simulator.generateSurroundingOffers(listings, result.ticksPassed(), 1000); @@ -289,8 +288,8 @@ private static int start(boolean levelUp) throws CommandSyntaxException { VillagerCracker.targetOffer = offer; VillagerCracker.surroundingOffers = surroundingOffers; VillagerCracker.hasClickedVillager = false; - VillagerCracker.simulator.setTicksUntilBruteForceInteract(ticks); - TaskManager.addTask("cvillagerBruteForce", new SimpleTask() { + VillagerCracker.simulator.setTicksUntilInteract(ticks); + TaskManager.addTask("cvillagerWaiting", new SimpleTask() { @Override public boolean condition() { return VillagerCracker.isRunning(); diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 05e08bee8..ed5d9418b 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -207,7 +207,7 @@ public static void onServerTick() { } } ); - simulator.resetBruteForceState(); + simulator.resetWaitingState(); hasClickedVillager = true; } } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 1f2eaf93c..f20e47599 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -44,7 +44,7 @@ public class VillagerRngSimulator { private boolean madeSound = false; private int totalAmbientSounds = 0; private int tickCount = 0; - private int totalTicksInBruteForce = 0; + private int totalTicksWaiting = 0; private float firstPitch = Float.NaN; private int ticksBetweenSounds = 0; private float secondPitch = Float.NaN; @@ -133,7 +133,7 @@ private void untick() { } public int getTicksRemaining() { - return totalTicksInBruteForce - tickCount; + return totalTicksWaiting - tickCount; } private void simulateBaseTick() { @@ -153,7 +153,7 @@ private void simulateServerAiStep() { } public void updateProgressBar() { - ClientCommandHelper.updateOverlayProgressBar(tickCount, totalTicksInBruteForce, 50, 60); + ClientCommandHelper.updateOverlayProgressBar(tickCount, totalTicksWaiting, 50, 60); } @Nullable @@ -202,9 +202,9 @@ public VillagerCracker.Offer[] generateOffers(VillagerTrades.ItemListing[] listi return offers; } - public void setTicksUntilBruteForceInteract(int ticks) { + public void setTicksUntilInteract(int ticks) { tickCount = 0; - totalTicksInBruteForce = ticks; + totalTicksWaiting = ticks; } public CrackedState getCrackedState() { @@ -221,15 +221,15 @@ public void reset() { prevAmbientSoundTime = 0; totalAmbientSounds = 0; tickCount = 0; - totalTicksInBruteForce = 0; + totalTicksWaiting = 0; firstPitch = Float.NaN; ticksBetweenSounds = 0; secondPitch = Float.NaN; seedsFromTwoPitches = null; } - public void resetBruteForceState() { - totalTicksInBruteForce = 0; + public void resetWaitingState() { + totalTicksWaiting = 0; tickCount = 0; } @@ -381,7 +381,7 @@ public void onXpOrbSpawned(int value) { } @Nullable - public BruteForceResult bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxTicks, Predicate predicate) { + public VillagerRngSimulator.OfferWaitingResult bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxTicks, Predicate predicate) { Villager targetVillager = VillagerCracker.getVillager(); if (targetVillager != null && getCrackedState().isCracked()) { VillagerRngSimulator branchedSimulator = this.copy(); @@ -399,7 +399,7 @@ public BruteForceResult bruteForceOffers(VillagerTrades.ItemListing[] listings, VillagerCracker.Offer offer = offerSimulator.anyOffersMatch(listings, targetVillager, predicate); if (offer != null) { // we do the calls before this ticks processing so that since with 0ms ping, the server reads it next tick - return new BruteForceResult(ticksPassed, offer); + return new OfferWaitingResult(ticksPassed, offer); } branchedSimulator.simulateTick(); } @@ -519,7 +519,7 @@ public MutableComponent getMessage(boolean addColor) { } } - public record BruteForceResult(int ticksPassed, VillagerCracker.Offer offer) { + public record OfferWaitingResult(int ticksPassed, VillagerCracker.Offer offer) { } public record SurroundingOffers(List before, VillagerCracker.Offer[] middle, List after) { From a62b7d0c1a45a07cb256d6d7651421b0f793a9ae Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 28 Nov 2024 16:23:11 -0500 Subject: [PATCH 60/78] fixed null pointer exception --- .../earthcomputer/clientcommands/features/VillagerCracker.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index ed5d9418b..98cd13867 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -117,6 +117,7 @@ public static void setTargetVillager(@Nullable Villager villager) { } ClientLevel level = Minecraft.getInstance().level; + assert level != null; if (level.getDayTime() % 24000 < 12000) { // todo, double check this works ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); From d6e284193e52a925efda15840609f46e3fcfb26b Mon Sep 17 00:00:00 2001 From: RTTV Date: Thu, 28 Nov 2024 16:27:41 -0500 Subject: [PATCH 61/78] wiser choice in case `setTargetVillager(null)` is called --- .../earthcomputer/clientcommands/features/VillagerCracker.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 98cd13867..97347f3dd 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -117,9 +117,8 @@ public static void setTargetVillager(@Nullable Villager villager) { } ClientLevel level = Minecraft.getInstance().level; - assert level != null; - if (level.getDayTime() % 24000 < 12000) { // todo, double check this works + if (level != null && level.getDayTime() % 24000 < 12000) { // todo, double check this works ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); } From f9a453056d595199003d07a296d3a3b06a085fa3 Mon Sep 17 00:00:00 2001 From: joe Date: Fri, 29 Nov 2024 23:10:45 +0000 Subject: [PATCH 62/78] Add villager random hierarchy regression test --- .../villagerRandomHierarchy.regressiontest | 127 ++++++++++++++++++ .../test/CallHierarchyWalker.java | 21 ++- .../test/EntityRandomCallHierarchyTest.java | 81 ++++++++++- .../clientcommands/test/ReferencesFinder.java | 8 ++ 4 files changed, 231 insertions(+), 6 deletions(-) create mode 100644 regressionTests/villagerRandomHierarchy.regressiontest diff --git a/regressionTests/villagerRandomHierarchy.regressiontest b/regressionTests/villagerRandomHierarchy.regressiontest new file mode 100644 index 000000000..284c3c17c --- /dev/null +++ b/regressionTests/villagerRandomHierarchy.regressiontest @@ -0,0 +1,127 @@ +net/minecraft/world/entity/Entity. (Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/level/Level;)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity. (Lnet/minecraft/world/entity/EntityType;Lnet/minecraft/world/level/Level;)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.doWaterSplashEffect ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.doWaterSplashEffect ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.doWaterSplashEffect ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.doWaterSplashEffect ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.doWaterSplashEffect ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.doWaterSplashEffect ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.doWaterSplashEffect ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.doWaterSplashEffect ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.doWaterSplashEffect ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/effect/InfestedMobEffect.onMobHurt (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;ILnet/minecraft/world/damagesource/DamageSource;F)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/effect/InfestedMobEffect.onMobHurt (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;ILnet/minecraft/world/damagesource/DamageSource;F)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/effect/InfestedMobEffect.spawnSilverfish (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;DDD)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/effect/OozingMobEffect.onMobRemoved (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;ILnet/minecraft/world/entity/Entity$RemovalReason;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/effect/WeavingMobEffect.onMobRemoved (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;ILnet/minecraft/world/entity/Entity$RemovalReason;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/effect/WindChargedMobEffect.onMobRemoved (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;ILnet/minecraft/world/entity/Entity$RemovalReason;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/behavior/CelebrateVillagersSurvivedRaid.tick (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/npc/Villager;J)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/behavior/CrossbowAttack.crossbowAttack (Lnet/minecraft/world/entity/Mob;Lnet/minecraft/world/entity/LivingEntity;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/behavior/LocateHidingPlace.create (IFI)Lnet/minecraft/world/entity/ai/behavior/OneShot; <- net/minecraft/world/entity/ai/behavior/LocateHidingPlace.lambda$create$10 <- net/minecraft/world/entity/ai/behavior/LocateHidingPlace.lambda$create$9 <- net/minecraft/world/entity/ai/behavior/LocateHidingPlace.lambda$create$8 <- net/minecraft/world/entity/ai/behavior/LocateHidingPlace.lambda$create$5 <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/behavior/LongJumpToPreferredBlock.start (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Mob;J)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/behavior/MoveToSkySeeingSpot.getOutdoorPosition (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;)Lnet/minecraft/world/phys/Vec3; <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/behavior/RandomLookAround.start (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Mob;J)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/behavior/Swim.tick (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/Mob;J)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/behavior/VillagerMakeLove.start (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/npc/Villager;J)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/behavior/VillagerMakeLove.tick (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/npc/Villager;J)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/util/AirAndWaterRandomPos.generateRandomPos (Lnet/minecraft/world/entity/PathfinderMob;IIIDDDZ)Lnet/minecraft/core/BlockPos; <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/util/AirAndWaterRandomPos.generateRandomPos (Lnet/minecraft/world/entity/PathfinderMob;IIIDDDZ)Lnet/minecraft/core/BlockPos; <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/util/DefaultRandomPos.generateRandomPosTowardDirection (Lnet/minecraft/world/entity/PathfinderMob;IZLnet/minecraft/core/BlockPos;)Lnet/minecraft/core/BlockPos; <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/util/DefaultRandomPos.getPos (Lnet/minecraft/world/entity/PathfinderMob;II)Lnet/minecraft/world/phys/Vec3; <- net/minecraft/world/entity/ai/util/DefaultRandomPos.lambda$getPos$0 <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/util/DefaultRandomPos.getPosAway (Lnet/minecraft/world/entity/PathfinderMob;IILnet/minecraft/world/phys/Vec3;)Lnet/minecraft/world/phys/Vec3; <- net/minecraft/world/entity/ai/util/DefaultRandomPos.lambda$getPosAway$2 <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/util/DefaultRandomPos.getPosTowards (Lnet/minecraft/world/entity/PathfinderMob;IILnet/minecraft/world/phys/Vec3;D)Lnet/minecraft/world/phys/Vec3; <- net/minecraft/world/entity/ai/util/DefaultRandomPos.lambda$getPosTowards$1 <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/util/HoverRandomPos.getPos (Lnet/minecraft/world/entity/PathfinderMob;IIDDFII)Lnet/minecraft/world/phys/Vec3; <- net/minecraft/world/entity/ai/util/HoverRandomPos.lambda$getPos$1 <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/util/LandRandomPos.generateRandomPosTowardDirection (Lnet/minecraft/world/entity/PathfinderMob;IZLnet/minecraft/core/BlockPos;)Lnet/minecraft/core/BlockPos; <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/util/LandRandomPos.getPos (Lnet/minecraft/world/entity/PathfinderMob;IILjava/util/function/ToDoubleFunction;)Lnet/minecraft/world/phys/Vec3; <- net/minecraft/world/entity/ai/util/LandRandomPos.lambda$getPos$0 <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/util/LandRandomPos.getPosInDirection (Lnet/minecraft/world/entity/PathfinderMob;IILnet/minecraft/world/phys/Vec3;Z)Lnet/minecraft/world/phys/Vec3; <- net/minecraft/world/entity/ai/util/LandRandomPos.lambda$getPosInDirection$1 <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/food/FoodProperties.onConsume (Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/component/Consumable;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/CrossbowItem.shootProjectile (Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/entity/projectile/Projectile;IFFFLnet/minecraft/world/entity/LivingEntity;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/ItemStack.onUseTick (Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;I)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/component/Consumable.onConsume (Lnet/minecraft/world/level/Level;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/item/ItemStack; <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/consume_effects/ApplyStatusEffectsConsumeEffect.apply (Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;)Z <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffect.apply (Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;)Z <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffect.apply (Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;)Z <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/consume_effects/TeleportRandomlyConsumeEffect.apply (Lnet/minecraft/world/level/Level;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;)Z <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/Enchantment.modifyDamageFilteredValue (Lnet/minecraft/core/component/DataComponentType;Lnet/minecraft/server/level/ServerLevel;ILnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lorg/apache/commons/lang3/mutable/MutableFloat;)V <- net/minecraft/world/item/enchantment/Enchantment.lambda$modifyDamageFilteredValue$7 <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/Enchantment.modifyEntityFilteredValue (Lnet/minecraft/core/component/DataComponentType;Lnet/minecraft/server/level/ServerLevel;ILnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/Entity;Lorg/apache/commons/lang3/mutable/MutableFloat;)V <- net/minecraft/world/item/enchantment/Enchantment.lambda$modifyEntityFilteredValue$6 <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/Enchantment.modifyDamageProtection (Lnet/minecraft/server/level/ServerLevel;ILnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/damagesource/DamageSource;Lorg/apache/commons/lang3/mutable/MutableFloat;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/EnchantmentHelper.getRandomItemWith (Lnet/minecraft/core/component/DataComponentType;Lnet/minecraft/world/entity/LivingEntity;Ljava/util/function/Predicate;)Ljava/util/Optional; <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/EnchantmentHelper.getTridentSpinAttackStrength (Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;)F <- net/minecraft/world/item/enchantment/EnchantmentHelper.lambda$getTridentSpinAttackStrength$36 <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/EnchantmentHelper.modifyCrossbowChargingTime (Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/entity/LivingEntity;F)F <- net/minecraft/world/item/enchantment/EnchantmentHelper.lambda$modifyCrossbowChargingTime$35 <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/EnchantmentHelper.processEquipmentDropChance (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/damagesource/DamageSource;F)F <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/effects/ApplyMobEffect.apply (Lnet/minecraft/server/level/ServerLevel;ILnet/minecraft/world/item/enchantment/EnchantedItemInUse;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/effects/DamageEntity.apply (Lnet/minecraft/server/level/ServerLevel;ILnet/minecraft/world/item/enchantment/EnchantedItemInUse;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/effects/PlaySoundEffect.apply (Lnet/minecraft/server/level/ServerLevel;ILnet/minecraft/world/item/enchantment/EnchantedItemInUse;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/effects/ReplaceBlock.apply (Lnet/minecraft/server/level/ServerLevel;ILnet/minecraft/world/item/enchantment/EnchantedItemInUse;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/effects/ReplaceDisk.apply (Lnet/minecraft/server/level/ServerLevel;ILnet/minecraft/world/item/enchantment/EnchantedItemInUse;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/enchantment/effects/SpawnParticlesEffect.apply (Lnet/minecraft/server/level/ServerLevel;ILnet/minecraft/world/item/enchantment/EnchantedItemInUse;Lnet/minecraft/world/entity/Entity;Lnet/minecraft/world/phys/Vec3;)V <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/level/pathfinder/FlyNodeEvaluator.iteratePathfindingStartNodeCandidatePositions (Lnet/minecraft/world/entity/Mob;)Ljava/lang/Iterable; <- net/minecraft/world/entity/Entity.getRandom <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/AgeableMob.aiStep ()V <- net/minecraft/world/entity/Entity.getRandomX <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.makePoofParticles ()V <- net/minecraft/world/entity/Entity.getRandomX <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.tickEffects ()V <- net/minecraft/world/entity/Entity.getRandomX <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/Villager.handleEntityEvent (B)V <- net/minecraft/world/entity/npc/AbstractVillager.addParticlesAroundSelf <- net/minecraft/world/entity/Entity.getRandomX <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/Villager.handleEntityEvent (B)V <- net/minecraft/world/entity/npc/AbstractVillager.addParticlesAroundSelf <- net/minecraft/world/entity/Entity.getRandomX <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/Villager.handleEntityEvent (B)V <- net/minecraft/world/entity/npc/AbstractVillager.addParticlesAroundSelf <- net/minecraft/world/entity/Entity.getRandomX <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/Villager.handleEntityEvent (B)V <- net/minecraft/world/entity/npc/AbstractVillager.addParticlesAroundSelf <- net/minecraft/world/entity/Entity.getRandomX <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/AgeableMob.aiStep ()V <- net/minecraft/world/entity/Entity.getRandomY <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.makePoofParticles ()V <- net/minecraft/world/entity/Entity.getRandomY <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.tickEffects ()V <- net/minecraft/world/entity/Entity.getRandomY <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/AgeableMob.aiStep ()V <- net/minecraft/world/entity/Entity.getRandomZ <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.makePoofParticles ()V <- net/minecraft/world/entity/Entity.getRandomZ <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.tickEffects ()V <- net/minecraft/world/entity/Entity.getRandomZ <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.lavaHurt ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.moveTowardsClosestSpace (DDD)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.playAmethystStepSound ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.playEntityOnFireExtinguishedSound ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.playEntityOnFireExtinguishedSound ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.playSwimSound (F)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.playSwimSound (F)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.spawnSprintParticle ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Entity.spawnSprintParticle ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.decreaseAirSupply (I)I <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.getVoicePitch ()F <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.getVoicePitch ()F <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.getVoicePitch ()F <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.getVoicePitch ()F <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.handleDamageEvent (Lnet/minecraft/world/damagesource/DamageSource;)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.handleDamageEvent (Lnet/minecraft/world/damagesource/DamageSource;)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.handleEntityEvent (B)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.handleEntityEvent (B)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.handleEntityEvent (B)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.handleEntityEvent (B)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.handleEntityEvent (B)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.handleEntityEvent (B)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.handleEntityEvent (B)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.handleEntityEvent (B)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.makePoofParticles ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.makePoofParticles ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.makePoofParticles ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.onEquipItem (Lnet/minecraft/world/entity/EquipmentSlot;Lnet/minecraft/world/item/ItemStack;Lnet/minecraft/world/item/ItemStack;)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.pushEntities ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.breakItem (Lnet/minecraft/world/item/ItemStack;)V <- net/minecraft/world/entity/LivingEntity.spawnItemParticles <- net/minecraft/world/entity/Entity.random +net/minecraft/world/item/component/Consumable.emitParticlesAndSounds (Lnet/minecraft/util/RandomSource;Lnet/minecraft/world/entity/LivingEntity;Lnet/minecraft/world/item/ItemStack;I)V <- net/minecraft/world/entity/LivingEntity.spawnItemParticles <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.tickEffects ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.tickEffects ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.updateFallFlying ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Mob.baseTick ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Mob.checkDespawn ()V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Mob.dropCustomDeathLoot (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;Z)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Mob.dropCustomDeathLoot (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;Z)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Mob.dropCustomDeathLoot (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;Z)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Mob.equipItemIfPossible (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/item/ItemStack;)Lnet/minecraft/world/item/ItemStack; <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Mob.getBaseExperienceReward (Lnet/minecraft/server/level/ServerLevel;)I <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Mob.getBaseExperienceReward (Lnet/minecraft/server/level/ServerLevel;)I <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Mob.getBaseExperienceReward (Lnet/minecraft/server/level/ServerLevel;)I <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Mob.isSunBurnTick ()Z <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/AbstractVillager.addOffersFromItemListings (Lnet/minecraft/world/item/trading/MerchantOffers;[Lnet/minecraft/world/entity/npc/VillagerTrades$ItemListing;I)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/AbstractVillager.addOffersFromItemListings (Lnet/minecraft/world/item/trading/MerchantOffers;[Lnet/minecraft/world/entity/npc/VillagerTrades$ItemListing;I)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/Villager.customServerAiStep (Lnet/minecraft/server/level/ServerLevel;)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/Villager.getBreedOffspring (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/AgeableMob;)Lnet/minecraft/world/entity/npc/Villager; <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/Villager.gossip (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/npc/Villager;J)V <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/Villager.rewardTradeXp (Lnet/minecraft/world/item/trading/MerchantOffer;)V <- net/minecraft/world/entity/Entity.random diff --git a/src/test/java/net/earthcomputer/clientcommands/test/CallHierarchyWalker.java b/src/test/java/net/earthcomputer/clientcommands/test/CallHierarchyWalker.java index 4d1ae5680..52d67cb66 100644 --- a/src/test/java/net/earthcomputer/clientcommands/test/CallHierarchyWalker.java +++ b/src/test/java/net/earthcomputer/clientcommands/test/CallHierarchyWalker.java @@ -33,14 +33,18 @@ public abstract sealed class CallHierarchyWalker { private final Set methodsToRecurseThrough = new HashSet<>(); // the reference <- referenced-from edges that have already been visited, used to prevent infinite recursion private final Set> visitedEdges = new HashSet<>(); - private String runtimeOwnerType = "java/lang/Object"; + String runtimeOwnerType = "java/lang/Object"; public static CallHierarchyWalker fromField(String owner, String name, String desc) { return new Field(owner, name, desc); } public static CallHierarchyWalker fromMethod(String owner, String name, String desc) { - return new Method(owner, name, desc); + return new Method(owner, name, desc, -1); + } + + public static CallHierarchyWalker fromMethod(String owner, String name, String desc, int ownerArgIndex) { + return new Method(owner, name, desc, ownerArgIndex); } public CallHierarchyWalker recurseThrough(String owner, String name, String desc) { @@ -239,21 +243,28 @@ private static final class Method extends CallHierarchyWalker { private final String owner; private final String name; private final String desc; + private final int ownerArgIndex; - private Method(String owner, String name, String desc) { + private Method(String owner, String name, String desc, int ownerArgIndex) { this.owner = owner; this.name = name; this.desc = desc; + this.ownerArgIndex = ownerArgIndex; } @Override public void walk(ReferenceConsumer referenceConsumer) { int argumentCount = Type.getArgumentCount(desc); + if (ownerArgIndex >= argumentCount) { + throw new IllegalArgumentException("ownerArgIndex (" + ownerArgIndex + ") >= argumentCount (" + argumentCount + ")"); + } + int stackDepth = argumentCount - 1 - ownerArgIndex; + handleReferences( List.of(new ReferencesFinder.OwnerNameAndDesc(owner, name, desc)), finder.findMethodReferences(owner, name, desc), - insn -> ((MethodInsnNode) insn).owner, - insn -> insn.getOpcode() == Opcodes.INVOKESTATIC ? -1 : argumentCount, + insn -> ownerArgIndex == -1 ? ((MethodInsnNode) insn).owner : runtimeOwnerType, + insn -> ownerArgIndex == -1 && insn.getOpcode() == Opcodes.INVOKESTATIC ? -1 : stackDepth, (containingClass, method) -> finder.findCallsToMethodInMethod(containingClass, method, owner, name, desc), referenceConsumer ); diff --git a/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java b/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java index c2c9afee2..0e68adde6 100644 --- a/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java +++ b/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java @@ -1,9 +1,15 @@ package net.earthcomputer.clientcommands.test; import org.junit.jupiter.api.Test; +import org.objectweb.asm.Type; +import org.objectweb.asm.tree.ClassNode; +import org.objectweb.asm.tree.MethodNode; import java.io.PrintWriter; +import java.util.HashSet; import java.util.List; +import java.util.Objects; +import java.util.Set; import java.util.stream.Collectors; public final class EntityRandomCallHierarchyTest { @@ -30,6 +36,25 @@ public void testPlayer() { }); } + @Test + public void testVillager() { + TestUtil.regressionTest("villagerRandomHierarchy", out -> { + CallHierarchyWalker.fromField("net/minecraft/world/entity/Entity", "random", "Lnet/minecraft/util/RandomSource;") + .runtimeOwnerType("net/minecraft/world/entity/npc/Villager") + .recurseThrough("net/minecraft/world/entity/Entity", "getRandom", "()Lnet/minecraft/util/RandomSource;") + .recurseThrough("net/minecraft/world/entity/Entity", "getRandomX", "(D)D") + .recurseThrough("net/minecraft/world/entity/Entity", "getRandomY", "()D") + .recurseThrough("net/minecraft/world/entity/Entity", "getRandomZ", "(D)D") + .recurseThrough("net/minecraft/world/entity/LivingEntity", "spawnItemParticles", "(Lnet/minecraft/world/item/ItemStack;I)V") + .recurseThrough("net/minecraft/world/entity/npc/AbstractVillager", "addParticlesAroundSelf", "(Lnet/minecraft/core/particles/ParticleOptions;)V") + .walk((reference, callStack) -> { + if (filterAiGoal(reference.owner(), "net/minecraft/world/entity/npc/Villager")) { + printReference(out, reference, callStack); + } + }); + }); + } + @Test public void testTeleportRandomly() { TestUtil.regressionTest("teleportRandomlyHierarchy", out -> { @@ -79,7 +104,61 @@ public void testEnchantmentSpawnParticlesEffect() { }); } - private void printReference(PrintWriter out, ReferencesFinder.OwnerNameAndDesc reference, List callStack) { + private static void printReference(PrintWriter out, ReferencesFinder.OwnerNameAndDesc reference, List callStack) { out.printf("%s.%s %s <- %s%n", reference.owner(), reference.name(), reference.desc(), callStack.reversed().stream().map(method -> method.owner() + "." + method.name()).collect(Collectors.joining(" <- "))); } + + // TODO: add a way to filter AI behaviors too + private static boolean filterAiGoal(String owner, String entityClass) { + return filterAiGoal(owner, entityClass, new HashSet<>()); + } + + private static boolean filterAiGoal(String owner, String entityClass, Set alreadyChecked) { + ReferencesFinder finder = ReferencesFinder.getInstance(); + if (!finder.isAssignable("net/minecraft/world/entity/ai/goal/Goal", owner)) { + return true; + } + + if (!alreadyChecked.add(owner)) { + return false; + } + + ClassNode clazz = finder.getClassNode(owner); + Objects.requireNonNull(clazz); + for (MethodNode method : clazz.methods) { + if (!"".equals(method.name)) { + continue; + } + + Type[] argumentTypes = Type.getArgumentTypes(method.desc); + int ownerIndex = -1; + for (int i = 0; i < argumentTypes.length; i++) { + Type argType = argumentTypes[i]; + if (argType.getSort() == Type.OBJECT && finder.isAssignable("net/minecraft/world/entity/Entity", argType.getInternalName())) { + ownerIndex = i; + break; + } + } + if (ownerIndex == -1) { + continue; + } + if (!finder.isAssignable(argumentTypes[ownerIndex].getInternalName(), entityClass) && !finder.isAssignable(entityClass, argumentTypes[ownerIndex].getInternalName())) { + continue; + } + + boolean[] foundAnyReferences = { false }; + CallHierarchyWalker.fromMethod(owner, "", method.desc, ownerIndex) + .runtimeOwnerType(entityClass) + .walk((reference, callStack) -> { + if (filterAiGoal(reference.owner(), entityClass, alreadyChecked)) { + foundAnyReferences[0] = true; + } + }); + if (foundAnyReferences[0]) { + return true; + } + } + + return false; + } } diff --git a/src/test/java/net/earthcomputer/clientcommands/test/ReferencesFinder.java b/src/test/java/net/earthcomputer/clientcommands/test/ReferencesFinder.java index 379e0a7cf..f099bc796 100644 --- a/src/test/java/net/earthcomputer/clientcommands/test/ReferencesFinder.java +++ b/src/test/java/net/earthcomputer/clientcommands/test/ReferencesFinder.java @@ -15,6 +15,7 @@ import org.objectweb.asm.Opcodes; import org.objectweb.asm.Type; import org.objectweb.asm.tree.AbstractInsnNode; +import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.FieldInsnNode; import org.objectweb.asm.tree.InvokeDynamicInsnNode; import org.objectweb.asm.tree.MethodInsnNode; @@ -106,6 +107,13 @@ private boolean getClassData(String className, ClassVisitor classVisitor, int re return false; } + @Nullable + public ClassNode getClassNode(String className) { + ClassNode classNode = new ClassNode(); + boolean exists = getClassData(className, classNode, ClassReader.SKIP_FRAMES); + return exists ? classNode : null; + } + // should only be called while indexing! @Nullable private ClassInfo getOrCreateClassInfo(Interner interner, String className) { From 51a47ac7cd59c7719bbb9dd3917ca16bd9c0b6dd Mon Sep 17 00:00:00 2001 From: RTTV Date: Fri, 29 Nov 2024 18:58:12 -0500 Subject: [PATCH 63/78] changed some names --- .../java/net/earthcomputer/clientcommands/Configs.java | 8 ++++---- .../clientcommands/command/VillagerCommand.java | 4 ++-- .../clientcommands/features/VillagerRngSimulator.java | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/Configs.java b/src/main/java/net/earthcomputer/clientcommands/Configs.java index 9cdc1ef1f..7acf0e7d0 100644 --- a/src/main/java/net/earthcomputer/clientcommands/Configs.java +++ b/src/main/java/net/earthcomputer/clientcommands/Configs.java @@ -192,9 +192,9 @@ public static void setVillagerManipulation(boolean villagerManipulation) { } } - @Config(setter = @Config.Setter("setMaxVillagerSimulationTicks"), temporary = true) - public static int maxVillagerSimulationTicks = 12000; - public static void setMaxVillagerSimulationTicks(int maxVillagerSimulationTicks) { - Configs.maxVillagerSimulationTicks = Mth.clamp(maxVillagerSimulationTicks, 0, 1_000_000); + @Config(setter = @Config.Setter("setMaxVillagerManipulationWaitTicks"), temporary = true) + public static int maxVillagerManipulationWaitTicks = 12000; + public static void setMaxVillagerManipulationWaitTicks(int maxVillagerManipulationWaitTicks) { + Configs.maxVillagerManipulationWaitTicks = Mth.clamp(maxVillagerManipulationWaitTicks, 0, 1_000_000); } } diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 65de5f994..174271462 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -269,9 +269,9 @@ private static int start(boolean levelUp) throws CommandSyntaxException { VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(crackedLevel, new VillagerTrades.ItemListing[0]); int adjustmentTicks = levelUp ? -40 : 0; - VillagerRngSimulator.OfferWaitingResult result = VillagerCracker.simulator.bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerSimulationTicks, offer -> VillagerCracker.goals.stream().anyMatch(goal -> goal.matches(offer))); + VillagerRngSimulator.BruteForceResult result = VillagerCracker.simulator.bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerManipulationWaitTicks, offer -> VillagerCracker.goals.stream().anyMatch(goal -> goal.matches(offer))); if (result == null) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerSimulationTicks).withStyle(ChatFormatting.RED), 100); + ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerManipulationWaitTicks).withStyle(ChatFormatting.RED), 100); return Command.SINGLE_SUCCESS; } VillagerRngSimulator.SurroundingOffers surroundingOffers = VillagerCracker.simulator.generateSurroundingOffers(listings, result.ticksPassed(), 1000); diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index f20e47599..75a362908 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -381,7 +381,7 @@ public void onXpOrbSpawned(int value) { } @Nullable - public VillagerRngSimulator.OfferWaitingResult bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxTicks, Predicate predicate) { + public VillagerRngSimulator.BruteForceResult bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxTicks, Predicate predicate) { Villager targetVillager = VillagerCracker.getVillager(); if (targetVillager != null && getCrackedState().isCracked()) { VillagerRngSimulator branchedSimulator = this.copy(); @@ -399,7 +399,7 @@ public VillagerRngSimulator.OfferWaitingResult bruteForceOffers(VillagerTrades.I VillagerCracker.Offer offer = offerSimulator.anyOffersMatch(listings, targetVillager, predicate); if (offer != null) { // we do the calls before this ticks processing so that since with 0ms ping, the server reads it next tick - return new OfferWaitingResult(ticksPassed, offer); + return new BruteForceResult(ticksPassed, offer); } branchedSimulator.simulateTick(); } @@ -519,7 +519,7 @@ public MutableComponent getMessage(boolean addColor) { } } - public record OfferWaitingResult(int ticksPassed, VillagerCracker.Offer offer) { + public record BruteForceResult(int ticksPassed, VillagerCracker.Offer offer) { } public record SurroundingOffers(List before, VillagerCracker.Offer[] middle, List after) { From 612b84b8846b9a09dffbe78e9d37acdb827096c8 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sat, 30 Nov 2024 17:20:34 -0500 Subject: [PATCH 64/78] added error messages for breaking villager manipulation --- .../features/VillagerCracker.java | 33 +++++++++++++++++-- .../features/VillagerRngSimulator.java | 21 ++++++------ .../villager/ClientPacketListenerMixin.java | 22 ++++--------- .../assets/clientcommands/lang/en_us.json | 21 ++++++++---- .../test/EntityRandomCallHierarchyTest.java | 1 + 5 files changed, 63 insertions(+), 35 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 97347f3dd..2c2b00e0d 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -18,6 +18,7 @@ import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.GlobalPos; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; @@ -25,6 +26,7 @@ import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; +import net.minecraft.tags.FluidTags; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; @@ -32,6 +34,8 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.trading.ItemCost; import net.minecraft.world.item.trading.MerchantOffer; +import net.minecraft.world.level.entity.EntityTypeTest; +import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; import org.apache.commons.lang3.ArrayUtils; import org.jetbrains.annotations.Nullable; @@ -119,7 +123,7 @@ public static void setTargetVillager(@Nullable Villager villager) { ClientLevel level = Minecraft.getInstance().level; if (level != null && level.getDayTime() % 24000 < 12000) { // todo, double check this works - ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); + simulator.onBadRNG("day"); } cachedVillager = new WeakReference<>(villager); @@ -149,6 +153,8 @@ public static void onSoundEventPlayed(ClientboundSoundPacket packet, Vec3 pos) { simulator.onYesSoundPlayed(packet.getPitch()); } else if (soundEvent == SoundEvents.GENERIC_SPLASH) { simulator.onSplashSoundPlayed(packet.getPitch()); + } else if (BuiltInRegistries.SOUND_EVENT.getKey(soundEvent).getPath().startsWith("item.armor.equip_")) { + simulator.onBadRNG("itemEquipped"); } } @@ -189,6 +195,23 @@ public static void onServerTick() { return; } + if (simulator.getCrackedState().isCracked()) { + if (!isResting(targetVillager.level().dayTime())) { + simulator.onBadRNG("day"); + } else if (targetVillager.isInWater() && targetVillager.getFluidHeight(FluidTags.WATER) > targetVillager.getFluidJumpThreshold() || targetVillager.isInLava()) { + simulator.onBadRNG("swim"); + } else if (!targetVillager.getActiveEffects().isEmpty()) { + simulator.onBadRNG("potion"); + } else { + Vec3 pos = targetVillager.position(); + int villagersNearVillager = targetVillager.level().getEntities(EntityTypeTest.forExactClass(Villager.class), AABB.ofSize(pos, 10.0, 10.0, 10.0), entity -> entity.position().distanceToSqr(pos) <= 5.0 * 5.0).size(); + if (villagersNearVillager > 1) { + simulator.onBadRNG("gossip"); + } + } + } + + simulator.simulateTick(); if (isRunning() && !hasClickedVillager) { @@ -264,8 +287,7 @@ public static void onGuiOpened(List actualOffersList) { } if (player.distanceTo(villager) > 2.0) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.distance").withStyle(ChatFormatting.RED), 100); - simulator.reset(); + simulator.onBadRNG("distance"); stopRunning(); return; } @@ -328,6 +350,11 @@ public static void stopRunning() { targetOffer = null; } + public static boolean isResting(long dayTime) { + long timeOfDay = dayTime % 24_000; + return timeOfDay < 10 || timeOfDay >= 12_000; + } + public record Goal( String resultString, Predicate result, diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 75a362908..d9fa0f370 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -1,5 +1,6 @@ package net.earthcomputer.clientcommands.features; +import com.demonwav.mcdev.annotations.Translatable; import com.seedfinding.latticg.math.component.BigFraction; import com.seedfinding.latticg.math.component.BigMatrix; import com.seedfinding.latticg.math.component.BigVector; @@ -241,8 +242,7 @@ public String toString() { public void onAmbientSoundPlayed(float pitch) { boolean justReset = false; if (totalAmbientSounds == 2 && !madeSound) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.ambient").withStyle(ChatFormatting.RED), 100); - reset(); + onBadRNG("ambient"); justReset = true; } @@ -308,6 +308,11 @@ public void onAmbientSoundPlayed(float pitch) { } } + public void onBadRNG(@Translatable(prefix = "villagerManip.reset.") String reason) { + ClientCommandHelper.sendFeedback(Component.translatable("villagerManip.reset", Component.translatable("villagerManip.reset." + reason)).withStyle(ChatFormatting.RED)); + reset(); + } + public void onNoSoundPlayed(float pitch, boolean fromGuiInteract) { // the last received action before the next tick's clock // played both when interacting with a villager without a profession and when using the villager gui @@ -318,8 +323,7 @@ public void onNoSoundPlayed(float pitch, boolean fromGuiInteract) { } float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; if (pitch != simulatedPitch) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.no").withStyle(ChatFormatting.RED), 100); - reset(); + onBadRNG("no"); } else { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); } @@ -334,8 +338,7 @@ public void onYesSoundPlayed(float pitch) { ambientSoundTime = -80; float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; if (pitch != simulatedPitch) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.yes").withStyle(ChatFormatting.RED), 100); - reset(); + onBadRNG("yes"); } else { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); } @@ -357,8 +360,7 @@ public void onSplashSoundPlayed(float pitch) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); } else { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.splash").withStyle(ChatFormatting.RED), 100); - reset(); + onBadRNG("splash"); } } } @@ -372,8 +374,7 @@ public void onXpOrbSpawned(int value) { boolean leveledUp = value > 3 + 3; if (leveledUp) simulatedValue += 5; if (value != simulatedValue) { - ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.outOfSync.xpOrb").withStyle(ChatFormatting.RED), 100); - reset(); + onBadRNG("xpOrb"); } else { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java index 58779f6bf..c4dfe9226 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java @@ -1,32 +1,27 @@ package net.earthcomputer.clientcommands.mixin.commands.villager; -import net.earthcomputer.clientcommands.command.ClientCommandHelper; +import com.llamalad7.mixinextras.sugar.Local; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.multiplayer.ClientPacketListener; import net.minecraft.core.GlobalPos; -import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundBlockUpdatePacket; +import net.minecraft.network.protocol.game.ClientboundDamageEventPacket; import net.minecraft.network.protocol.game.ClientboundSectionBlocksUpdatePacket; -import net.minecraft.network.protocol.game.ClientboundSetTimePacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; import net.minecraft.resources.ResourceKey; +import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.level.Level; import net.minecraft.world.phys.Vec3; import org.spongepowered.asm.mixin.Mixin; -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(ClientPacketListener.class) public class ClientPacketListenerMixin { - @Shadow - private ClientLevel level; - @Inject(method = "handleSoundEvent", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) private void onHandleSoundEvent(ClientboundSoundPacket packet, CallbackInfo ci) { Villager targetVillager = VillagerCracker.getVillager(); @@ -62,13 +57,10 @@ private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackIn } } - @Inject(method = "handleSetTime", at = @At(value = "INVOKE", shift = At.Shift.AFTER, target = "Lnet/minecraft/network/protocol/PacketUtils;ensureRunningOnSameThread(Lnet/minecraft/network/protocol/Packet;Lnet/minecraft/network/PacketListener;Lnet/minecraft/util/thread/BlockableEventLoop;)V")) - private void handleSetTime(ClientboundSetTimePacket packet, CallbackInfo ci) { - if (level.getDayTime() < 12000 && packet.dayTime() >= 12000) { - Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager != null) { - ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); - } + @Inject(method = "handleDamageEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;handleDamageEvent(Lnet/minecraft/world/damagesource/DamageSource;)V")) + private void onHandleDamageEvent(ClientboundDamageEventPacket packet, CallbackInfo ci, @Local Entity entity) { + if (entity == VillagerCracker.getVillager() && VillagerCracker.simulator.getCrackedState().isCracked()) { + VillagerCracker.simulator.onBadRNG("mobHurt"); } } } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index b041cae5c..9f68cd9c6 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -255,7 +255,6 @@ "commands.cvillager.crack.success": "Villager RNG cracked: %s", "commands.cvillager.failure": "Got the incorrect trade with correction of %sms; re-adjusting to %sms", "commands.cvillager.goalAdded": "Added goal successfully.", - "commands.cvillager.help.day": "Help: villager RNG manipulation will break if it's not night time", "commands.cvillager.help.noClock": "Help: villager RNG manipulation requires a 20 Hz clock", "commands.cvillager.help.tooFast": "Help: villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running faster", "commands.cvillager.help.tooSlow": "Help: villager RNG manipulation requires a 20 Hz clock, please be advised that your clock seems to be running slower", @@ -267,12 +266,6 @@ "commands.cvillager.noProfession": "The targeted villager has no profession", "commands.cvillager.notAVillager": "Target was not a villager", "commands.cvillager.notLevel1": "The targeted villager has level above 1", - "commands.cvillager.outOfSync.ambient": "Your villager's hrmm sound was incorrectly timed and or incorrectly pitched, re-cracking", - "commands.cvillager.outOfSync.distance": "Your villager was too far away from you, re-cracking", - "commands.cvillager.outOfSync.no": "Your villager's no sound was incorrectly pitched, re-cracking", - "commands.cvillager.outOfSync.splash": "Your villager's splash sound was incorrectly pitched, re-cracking", - "commands.cvillager.outOfSync.xpOrb": "Your villager's xp orb was incorrectly sized, re-cracking", - "commands.cvillager.outOfSync.yes": "Your villager's yes sound was incorrectly pitched, re-cracking", "commands.cvillager.partiallyCracked": "Your villager's RNG is partially cracked (~83m seeds remain)", "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %s, you only have %s goals", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", @@ -281,6 +274,20 @@ "commands.cvillager.target.cleared": "Target entity cleared", "commands.cvillager.target.set": "Target entity set", + "villagerManip.reset": "Restarting villager RNG manipulation. Reason: %s", + "villagerManip.reset.mobHurt": "Mob Hurt", + "villagerManip.reset.day": "Daytime", + "villagerManip.reset.swim": "Swum", + "villagerManip.reset.potion": "Potion Effect Active", + "villagerManip.reset.itemEquipped": "Item Equipped", + "villagerManip.reset.gossip": "Gossip", + "villagerManip.reset.distance": "Too far from villager", + "villagerManip.reset.ambient": "Bad Ambient Noise", + "villagerManip.reset.no": "Bad Unhappy Noise", + "villagerManip.reset.splash": "Bad Splash Noise", + "villagerManip.reset.xpOrb": "Bad XP Orb Size", + "villagerManip.reset.yes": "Bad Happy Noise", + "commands.cwe.playerNotFound": "Player not found", "commands.cweather.reset": "Stopped overriding weather", diff --git a/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java b/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java index 0e68adde6..9a062acff 100644 --- a/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java +++ b/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java @@ -46,6 +46,7 @@ public void testVillager() { .recurseThrough("net/minecraft/world/entity/Entity", "getRandomY", "()D") .recurseThrough("net/minecraft/world/entity/Entity", "getRandomZ", "(D)D") .recurseThrough("net/minecraft/world/entity/LivingEntity", "spawnItemParticles", "(Lnet/minecraft/world/item/ItemStack;I)V") + .recurseThrough("net/minecraft/world/entity/LivingEntity", "makeSound", "(Lnet/minecraft/sounds/SoundEvent;)V") .recurseThrough("net/minecraft/world/entity/npc/AbstractVillager", "addParticlesAroundSelf", "(Lnet/minecraft/core/particles/ParticleOptions;)V") .walk((reference, callStack) -> { if (filterAiGoal(reference.owner(), "net/minecraft/world/entity/npc/Villager")) { From 11fcc1fc286ac2a3e0b58fc6a8227eb048084ae0 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sat, 30 Nov 2024 19:55:16 -0500 Subject: [PATCH 65/78] fixed failure of tests --- regressionTests/villagerRandomHierarchy.regressiontest | 6 ++---- .../clientcommands/test/EntityRandomCallHierarchyTest.java | 3 ++- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/regressionTests/villagerRandomHierarchy.regressiontest b/regressionTests/villagerRandomHierarchy.regressiontest index 284c3c17c..b11b8f172 100644 --- a/regressionTests/villagerRandomHierarchy.regressiontest +++ b/regressionTests/villagerRandomHierarchy.regressiontest @@ -85,10 +85,8 @@ net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/enti net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/entity/Entity.random net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/entity/Entity.random net/minecraft/world/entity/LivingEntity.decreaseAirSupply (I)I <- net/minecraft/world/entity/Entity.random -net/minecraft/world/entity/LivingEntity.getVoicePitch ()F <- net/minecraft/world/entity/Entity.random -net/minecraft/world/entity/LivingEntity.getVoicePitch ()F <- net/minecraft/world/entity/Entity.random -net/minecraft/world/entity/LivingEntity.getVoicePitch ()F <- net/minecraft/world/entity/Entity.random -net/minecraft/world/entity/LivingEntity.getVoicePitch ()F <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.makeSound (Lnet/minecraft/sounds/SoundEvent;)V <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.tick (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/PathfinderMob;J)V <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random net/minecraft/world/entity/LivingEntity.handleDamageEvent (Lnet/minecraft/world/damagesource/DamageSource;)V <- net/minecraft/world/entity/Entity.random net/minecraft/world/entity/LivingEntity.handleDamageEvent (Lnet/minecraft/world/damagesource/DamageSource;)V <- net/minecraft/world/entity/Entity.random net/minecraft/world/entity/LivingEntity.handleEntityEvent (B)V <- net/minecraft/world/entity/Entity.random diff --git a/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java b/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java index 9a062acff..b6dbeecd3 100644 --- a/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java +++ b/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java @@ -46,7 +46,8 @@ public void testVillager() { .recurseThrough("net/minecraft/world/entity/Entity", "getRandomY", "()D") .recurseThrough("net/minecraft/world/entity/Entity", "getRandomZ", "(D)D") .recurseThrough("net/minecraft/world/entity/LivingEntity", "spawnItemParticles", "(Lnet/minecraft/world/item/ItemStack;I)V") - .recurseThrough("net/minecraft/world/entity/LivingEntity", "makeSound", "(Lnet/minecraft/sounds/SoundEvent;)V") + .recurseThrough("net/minecraft/world/entity/LivingEntity", "getSoundVolume", "()F") + .recurseThrough("net/minecraft/world/entity/LivingEntity", "getVoicePitch", "()F") .recurseThrough("net/minecraft/world/entity/npc/AbstractVillager", "addParticlesAroundSelf", "(Lnet/minecraft/core/particles/ParticleOptions;)V") .walk((reference, callStack) -> { if (filterAiGoal(reference.owner(), "net/minecraft/world/entity/npc/Villager")) { From e9fd0b74242df974d0eb030621faebacc5147dda Mon Sep 17 00:00:00 2001 From: RTTV Date: Sat, 30 Nov 2024 21:43:57 -0500 Subject: [PATCH 66/78] added checks to spawn area --- .../villagerRandomHierarchy.regressiontest | 10 ++- .../command/VillagerCommand.java | 2 +- .../features/VillagerCracker.java | 78 +++++++++++++++--- .../features/VillagerRngSimulator.java | 28 +++++-- .../villager/ClientPacketListenerMixin.java | 2 +- .../assets/clientcommands/lang/en_us.json | 9 ++ .../test/EntityRandomCallHierarchyTest.java | 2 + villager_rng_setup.png | Bin 0 -> 265777 bytes 8 files changed, 108 insertions(+), 23 deletions(-) create mode 100644 villager_rng_setup.png diff --git a/regressionTests/villagerRandomHierarchy.regressiontest b/regressionTests/villagerRandomHierarchy.regressiontest index b11b8f172..f2a0ca71b 100644 --- a/regressionTests/villagerRandomHierarchy.regressiontest +++ b/regressionTests/villagerRandomHierarchy.regressiontest @@ -85,7 +85,15 @@ net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/enti net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/entity/Entity.random net/minecraft/world/entity/LivingEntity.baseTick ()V <- net/minecraft/world/entity/Entity.random net/minecraft/world/entity/LivingEntity.decreaseAirSupply (I)I <- net/minecraft/world/entity/Entity.random -net/minecraft/world/entity/LivingEntity.makeSound (Lnet/minecraft/sounds/SoundEvent;)V <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.hurtServer (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/damagesource/DamageSource;F)Z <- net/minecraft/world/entity/LivingEntity.makeSound <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/LivingEntity.playHurtSound (Lnet/minecraft/world/damagesource/DamageSource;)V <- net/minecraft/world/entity/LivingEntity.makeSound <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/Mob.playAmbientSound ()V <- net/minecraft/world/entity/LivingEntity.makeSound <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/monster/hoglin/HoglinAi.updateActivity (Lnet/minecraft/world/entity/monster/hoglin/Hoglin;)V <- net/minecraft/world/entity/LivingEntity.makeSound <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/monster/piglin/PiglinAi.updateActivity (Lnet/minecraft/world/entity/monster/piglin/Piglin;)V <- net/minecraft/world/entity/LivingEntity.makeSound <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/AbstractVillager.notifyTradeUpdated (Lnet/minecraft/world/item/ItemStack;)V <- net/minecraft/world/entity/LivingEntity.makeSound <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/AbstractVillager.playCelebrateSound ()V <- net/minecraft/world/entity/LivingEntity.makeSound <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/Villager.playWorkSound ()V <- net/minecraft/world/entity/LivingEntity.makeSound <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random +net/minecraft/world/entity/npc/Villager.setUnhappy ()V <- net/minecraft/world/entity/LivingEntity.makeSound <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random net/minecraft/world/entity/ai/behavior/PrepareRamNearestTarget.tick (Lnet/minecraft/server/level/ServerLevel;Lnet/minecraft/world/entity/PathfinderMob;J)V <- net/minecraft/world/entity/LivingEntity.getVoicePitch <- net/minecraft/world/entity/Entity.random net/minecraft/world/entity/LivingEntity.handleDamageEvent (Lnet/minecraft/world/damagesource/DamageSource;)V <- net/minecraft/world/entity/Entity.random net/minecraft/world/entity/LivingEntity.handleDamageEvent (Lnet/minecraft/world/damagesource/DamageSource;)V <- net/minecraft/world/entity/Entity.random diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 174271462..41f8e9950 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -247,7 +247,7 @@ private static int start(boolean levelUp) throws CommandSyntaxException { throw NO_GOALS_EXCEPTION.create(); } - if (targetVillager == null || !VillagerCracker.simulator.getCrackedState().isCracked()) { + if (targetVillager == null || !VillagerCracker.simulator.isCracked()) { throw NO_CRACKED_VILLAGER_PRESENT_EXCEPTION.create(); } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 2c2b00e0d..f6db71bdb 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -17,8 +17,11 @@ import net.minecraft.client.Minecraft; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; +import net.minecraft.core.BlockPos; +import net.minecraft.core.Direction; import net.minecraft.core.GlobalPos; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; @@ -26,6 +29,7 @@ import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.sounds.SoundSource; +import net.minecraft.tags.BlockTags; import net.minecraft.tags.FluidTags; import net.minecraft.world.InteractionHand; import net.minecraft.world.entity.Entity; @@ -34,6 +38,12 @@ import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.trading.ItemCost; import net.minecraft.world.item.trading.MerchantOffer; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.block.BedBlock; +import net.minecraft.world.level.block.TrapDoorBlock; +import net.minecraft.world.level.block.state.BlockState; +import net.minecraft.world.level.block.state.properties.BedPart; +import net.minecraft.world.level.block.state.properties.Half; import net.minecraft.world.level.entity.EntityTypeTest; import net.minecraft.world.phys.AABB; import net.minecraft.world.phys.Vec3; @@ -41,10 +51,7 @@ import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.UUID; +import java.util.*; import java.util.function.Predicate; public class VillagerCracker { @@ -124,10 +131,15 @@ public static void setTargetVillager(@Nullable Villager villager) { if (level != null && level.getDayTime() % 24000 < 12000) { // todo, double check this works simulator.onBadRNG("day"); + ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); } - cachedVillager = new WeakReference<>(villager); - villagerUuid = villager == null ? null : villager.getUUID(); + if (villager != null) { + cachedVillager = new WeakReference<>(villager); + villagerUuid = villager.getUUID(); + } else { + reset(); + } } public static void setClockPos(@Nullable GlobalPos pos) { @@ -190,23 +202,58 @@ private static void onTimeSync() { public static void onServerTick() { clockTicksSinceLastTimeSync++; - Villager targetVillager = getVillager(); + final Minecraft mc = Minecraft.getInstance(); + final Villager targetVillager = getVillager(); if (targetVillager == null) { return; } - if (simulator.getCrackedState().isCracked()) { + a: if (simulator.isAtLeastPartiallyCracked()) { if (!isResting(targetVillager.level().dayTime())) { simulator.onBadRNG("day"); + ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); } else if (targetVillager.isInWater() && targetVillager.getFluidHeight(FluidTags.WATER) > targetVillager.getFluidJumpThreshold() || targetVillager.isInLava()) { simulator.onBadRNG("swim"); } else if (!targetVillager.getActiveEffects().isEmpty()) { simulator.onBadRNG("potion"); + } else if (!mc.player.getItemInHand(InteractionHand.MAIN_HAND).isEmpty()) { + simulator.onBadRNG("itemInMainHand"); } else { - Vec3 pos = targetVillager.position(); - int villagersNearVillager = targetVillager.level().getEntities(EntityTypeTest.forExactClass(Villager.class), AABB.ofSize(pos, 10.0, 10.0, 10.0), entity -> entity.position().distanceToSqr(pos) <= 5.0 * 5.0).size(); - if (villagersNearVillager > 1) { - simulator.onBadRNG("gossip"); + Level level = targetVillager.level(); + + { + Vec3 pos = targetVillager.position(); + int villagersNearVillager = level.getEntities(EntityTypeTest.forExactClass(Villager.class), AABB.ofSize(pos, 10.0, 10.0, 10.0), entity -> entity.position().distanceToSqr(pos) <= 5.0 * 5.0).size(); + if (villagersNearVillager > 1) { + simulator.onBadRNG("gossip"); + break a; + } + } + + { + BlockPos pos = targetVillager.blockPosition(); + List validBedHeadPositions = List.of(pos.north(3), pos.east(3), pos.south(3), pos.west(3)); + List bedPartPositions = BlockPos.withinManhattanStream(pos, 15, 7, 15).map(BlockPos::new).filter(p -> level.getBlockState(p).is(BlockTags.BEDS) && level.getBlockState(p).getValue(BedBlock.OCCUPIED) == Boolean.FALSE && level.getBlockState(p).getValue(BedBlock.PART) == BedPart.HEAD).toList(); + Direction bedDirection; + if (bedPartPositions.size() == 1 && validBedHeadPositions.contains(bedPartPositions.getFirst())) { + bedDirection = Direction.Plane.HORIZONTAL.stream().skip(validBedHeadPositions.indexOf(bedPartPositions.getFirst())).findAny().orElse(null); + } else { + simulator.onBadRNG("invalidBedPosition"); + sendInvalidSetupHelp(); + break a; + } + + for (Direction direction : Direction.Plane.HORIZONTAL) { + BlockPos airPos = pos.relative(direction); + BlockPos trapdoorPos = airPos.above(); + BlockState airPosState = level.getBlockState(airPos); + BlockState trapdoorPosState = level.getBlockState(trapdoorPos); + if (!((airPosState.isAir() || direction != bedDirection) && trapdoorPosState.is(BlockTags.TRAPDOORS) && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.OPEN) == Boolean.FALSE)) { + simulator.onBadRNG("invalidCage"); + sendInvalidSetupHelp(); + break a; + } + } } } } @@ -214,7 +261,7 @@ public static void onServerTick() { simulator.simulateTick(); - if (isRunning() && !hasClickedVillager) { + if (simulator.getCrackedState().isCracked() && isRunning() && !hasClickedVillager) { int millisecondsUntilInteract = simulator.getTicksRemaining() * serverMspt - PingCommand.getLocalPing() + magicMillisecondCorrection; if (millisecondsUntilInteract < 200) { LocalPlayer oldPlayer = Minecraft.getInstance().player; @@ -236,6 +283,10 @@ public static void onServerTick() { } } + private static void sendInvalidSetupHelp() { + ClientCommandHelper.sendHelp(Component.translatable("villagerManip.help.setup.prefix").append(Component.translatable("villagerManip.help.setup.here").withStyle(ChatFormatting.UNDERLINE).withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://raw.githubusercontent.com/Earthcomputer/clientcommands/refs/heads/fabric/villager_rng_setup.png")))).append(Component.translatable("villagerManip.help.setup.suffix"))); + } + private static void onDisconnect() { if (Relogger.isRelogging) { UUID prevVillagerUuid = villagerUuid; @@ -339,6 +390,7 @@ public static void reset() { simulator.reset(); clockPos = null; villagerUuid = null; + cachedVillager = new WeakReference<>(null); stopRunning(); } diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index d9fa0f370..f0c0c1af5 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -154,12 +154,14 @@ private void simulateServerAiStep() { } public void updateProgressBar() { - ClientCommandHelper.updateOverlayProgressBar(tickCount, totalTicksWaiting, 50, 60); + if (totalTicksWaiting > 0) { + ClientCommandHelper.updateOverlayProgressBar(tickCount, totalTicksWaiting, 50, 60); + } } @Nullable public VillagerCracker.Offer anyOffersMatch(VillagerTrades.ItemListing[] listings, Entity trader, Predicate predicate) { - if (!getCrackedState().isCracked()) { + if (!isCracked()) { return null; } @@ -183,7 +185,7 @@ public VillagerCracker.Offer anyOffersMatch(VillagerTrades.ItemListing[] listing @Nullable public VillagerCracker.Offer[] generateOffers(VillagerTrades.ItemListing[] listings, Entity trader) { - if (!getCrackedState().isCracked()) { + if (!isCracked()) { return null; } @@ -209,13 +211,23 @@ public void setTicksUntilInteract(int ticks) { } public CrackedState getCrackedState() { - if (random == null || totalAmbientSounds < 2) { + if (totalAmbientSounds == 0) { return CrackedState.UNCRACKED; + } else if (totalAmbientSounds > 0 && random == null) { + return CrackedState.PARTIALLY_CRACKED; } return CrackedState.CRACKED; } + public boolean isCracked() { + return getCrackedState().isCracked(); + } + + public boolean isAtLeastPartiallyCracked() { + return getCrackedState() != CrackedState.UNCRACKED; + } + public void reset() { random = null; prevRandomSeed = 0; @@ -384,7 +396,7 @@ public void onXpOrbSpawned(int value) { @Nullable public VillagerRngSimulator.BruteForceResult bruteForceOffers(VillagerTrades.ItemListing[] listings, int minTicks, int maxTicks, Predicate predicate) { Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager != null && getCrackedState().isCracked()) { + if (targetVillager != null && isCracked()) { VillagerRngSimulator branchedSimulator = this.copy(); int ticksPassed = 0; @@ -413,7 +425,7 @@ public VillagerRngSimulator.BruteForceResult bruteForceOffers(VillagerTrades.Ite public SurroundingOffers generateSurroundingOffers(VillagerTrades.ItemListing[] listings, int centerTicks, int radius) { Villager targetVillager = VillagerCracker.getVillager(); - if (targetVillager == null || !getCrackedState().isCracked()) { + if (targetVillager == null || !isCracked()) { return null; } @@ -506,6 +518,7 @@ public long[] crackSeed() { public enum CrackedState { UNCRACKED, + PARTIALLY_CRACKED, CRACKED; public boolean isCracked() { @@ -514,7 +527,8 @@ public boolean isCracked() { public MutableComponent getMessage(boolean addColor) { return switch (this) { - case UNCRACKED -> Component.translatable("commands.cvillager.partiallyCracked").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); + case UNCRACKED -> Component.translatable("commands.cvillager.uncracked").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); + case PARTIALLY_CRACKED -> Component.translatable("commands.cvillager.partiallyCracked").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); case CRACKED -> Component.translatable("commands.cvillager.inSync").withStyle(addColor ? ChatFormatting.GREEN : ChatFormatting.RESET); }; } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java index c4dfe9226..ec7d97702 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java @@ -59,7 +59,7 @@ private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackIn @Inject(method = "handleDamageEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;handleDamageEvent(Lnet/minecraft/world/damagesource/DamageSource;)V")) private void onHandleDamageEvent(ClientboundDamageEventPacket packet, CallbackInfo ci, @Local Entity entity) { - if (entity == VillagerCracker.getVillager() && VillagerCracker.simulator.getCrackedState().isCracked()) { + if (entity == VillagerCracker.getVillager() && VillagerCracker.simulator.isAtLeastPartiallyCracked()) { VillagerCracker.simulator.onBadRNG("mobHurt"); } } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 9079cfe99..71423dda9 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -266,6 +266,7 @@ "commands.cvillager.noProfession": "The targeted villager has no profession", "commands.cvillager.notAVillager": "Target was not a villager", "commands.cvillager.notLevel1": "The targeted villager has level above 1", + "commands.cvillager.uncracked": "Your villager's RNG is not cracked (~18 quintillion seeds remain)", "commands.cvillager.partiallyCracked": "Your villager's RNG is partially cracked (~83m seeds remain)", "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %s, you only have %s goals", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", @@ -287,6 +288,14 @@ "villagerManip.reset.splash": "Bad Splash Noise", "villagerManip.reset.xpOrb": "Bad XP Orb Size", "villagerManip.reset.yes": "Bad Happy Noise", + "villagerManip.reset.itemInMainHand": "Item in Main Hand", + "villagerManip.reset.invalidBedPosition": "Invalid Bed Position", + "villagerManip.reset.invalidCage": "Invalid Villager Cage", + + "villagerManip.help.day": "Help: Villager RNG manipulation can only be done at night-time", + "villagerManip.help.setup.prefix": "Help: Trap the villager with trapdoors at their head with a bed's head exactly 3 blocks away in any direction, as seen in ", + "villagerManip.help.setup.here": "this", + "villagerManip.help.setup.suffix": " image", "commands.cwe.playerNotFound": "Player not found", diff --git a/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java b/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java index b6dbeecd3..b6a341f4f 100644 --- a/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java +++ b/src/test/java/net/earthcomputer/clientcommands/test/EntityRandomCallHierarchyTest.java @@ -46,8 +46,10 @@ public void testVillager() { .recurseThrough("net/minecraft/world/entity/Entity", "getRandomY", "()D") .recurseThrough("net/minecraft/world/entity/Entity", "getRandomZ", "(D)D") .recurseThrough("net/minecraft/world/entity/LivingEntity", "spawnItemParticles", "(Lnet/minecraft/world/item/ItemStack;I)V") + .recurseThrough("net/minecraft/world/entity/LivingEntity", "makeSound", "(Lnet/minecraft/sounds/SoundEvent;)V") .recurseThrough("net/minecraft/world/entity/LivingEntity", "getSoundVolume", "()F") .recurseThrough("net/minecraft/world/entity/LivingEntity", "getVoicePitch", "()F") + .recurseThrough("net/minecraft/world/entity/LivingEntity", "getVoicePitch", "()F") .recurseThrough("net/minecraft/world/entity/npc/AbstractVillager", "addParticlesAroundSelf", "(Lnet/minecraft/core/particles/ParticleOptions;)V") .walk((reference, callStack) -> { if (filterAiGoal(reference.owner(), "net/minecraft/world/entity/npc/Villager")) { diff --git a/villager_rng_setup.png b/villager_rng_setup.png new file mode 100644 index 0000000000000000000000000000000000000000..cb9e1b27ef6eb0ce186b06ceb5ccee637cbac79d GIT binary patch literal 265777 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 Date: Sun, 1 Dec 2024 15:31:13 -0500 Subject: [PATCH 67/78] moved code to a fn --- .../features/VillagerCracker.java | 109 ++++++++++-------- 1 file changed, 59 insertions(+), 50 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index f6db71bdb..99eea5f90 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -202,63 +202,15 @@ private static void onTimeSync() { public static void onServerTick() { clockTicksSinceLastTimeSync++; - final Minecraft mc = Minecraft.getInstance(); final Villager targetVillager = getVillager(); if (targetVillager == null) { return; } - a: if (simulator.isAtLeastPartiallyCracked()) { - if (!isResting(targetVillager.level().dayTime())) { - simulator.onBadRNG("day"); - ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); - } else if (targetVillager.isInWater() && targetVillager.getFluidHeight(FluidTags.WATER) > targetVillager.getFluidJumpThreshold() || targetVillager.isInLava()) { - simulator.onBadRNG("swim"); - } else if (!targetVillager.getActiveEffects().isEmpty()) { - simulator.onBadRNG("potion"); - } else if (!mc.player.getItemInHand(InteractionHand.MAIN_HAND).isEmpty()) { - simulator.onBadRNG("itemInMainHand"); - } else { - Level level = targetVillager.level(); - - { - Vec3 pos = targetVillager.position(); - int villagersNearVillager = level.getEntities(EntityTypeTest.forExactClass(Villager.class), AABB.ofSize(pos, 10.0, 10.0, 10.0), entity -> entity.position().distanceToSqr(pos) <= 5.0 * 5.0).size(); - if (villagersNearVillager > 1) { - simulator.onBadRNG("gossip"); - break a; - } - } - - { - BlockPos pos = targetVillager.blockPosition(); - List validBedHeadPositions = List.of(pos.north(3), pos.east(3), pos.south(3), pos.west(3)); - List bedPartPositions = BlockPos.withinManhattanStream(pos, 15, 7, 15).map(BlockPos::new).filter(p -> level.getBlockState(p).is(BlockTags.BEDS) && level.getBlockState(p).getValue(BedBlock.OCCUPIED) == Boolean.FALSE && level.getBlockState(p).getValue(BedBlock.PART) == BedPart.HEAD).toList(); - Direction bedDirection; - if (bedPartPositions.size() == 1 && validBedHeadPositions.contains(bedPartPositions.getFirst())) { - bedDirection = Direction.Plane.HORIZONTAL.stream().skip(validBedHeadPositions.indexOf(bedPartPositions.getFirst())).findAny().orElse(null); - } else { - simulator.onBadRNG("invalidBedPosition"); - sendInvalidSetupHelp(); - break a; - } - - for (Direction direction : Direction.Plane.HORIZONTAL) { - BlockPos airPos = pos.relative(direction); - BlockPos trapdoorPos = airPos.above(); - BlockState airPosState = level.getBlockState(airPos); - BlockState trapdoorPosState = level.getBlockState(trapdoorPos); - if (!((airPosState.isAir() || direction != bedDirection) && trapdoorPosState.is(BlockTags.TRAPDOORS) && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.OPEN) == Boolean.FALSE)) { - simulator.onBadRNG("invalidCage"); - sendInvalidSetupHelp(); - break a; - } - } - } - } + if (simulator.isAtLeastPartiallyCracked()) { + checkVillagerSetup(); } - simulator.simulateTick(); if (simulator.getCrackedState().isCracked() && isRunning() && !hasClickedVillager) { @@ -283,6 +235,63 @@ public static void onServerTick() { } } + private static void checkVillagerSetup() { + final Minecraft mc = Minecraft.getInstance(); + final Villager targetVillager = getVillager(); + + if (targetVillager == null) { + return; + } + + if (!isResting(targetVillager.level().dayTime())) { + simulator.onBadRNG("day"); + ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); + } else if (targetVillager.isInWater() && targetVillager.getFluidHeight(FluidTags.WATER) > targetVillager.getFluidJumpThreshold() || targetVillager.isInLava()) { + simulator.onBadRNG("swim"); + } else if (!targetVillager.getActiveEffects().isEmpty()) { + simulator.onBadRNG("potion"); + } else if (!mc.player.getItemInHand(InteractionHand.MAIN_HAND).isEmpty()) { + simulator.onBadRNG("itemInMainHand"); + } else { + Level level = targetVillager.level(); + + { + Vec3 pos = targetVillager.position(); + int villagersNearVillager = level.getEntities(EntityTypeTest.forExactClass(Villager.class), AABB.ofSize(pos, 10.0, 10.0, 10.0), entity -> entity.position().distanceToSqr(pos) <= 5.0 * 5.0).size(); + if (villagersNearVillager > 1) { + simulator.onBadRNG("gossip"); + return; + } + } + + { + BlockPos pos = targetVillager.blockPosition(); + List validBedHeadPositions = List.of(pos.north(3), pos.east(3), pos.south(3), pos.west(3)); + List bedPartPositions = BlockPos.withinManhattanStream(pos, 15, 7, 15).map(BlockPos::new).filter(p -> level.getBlockState(p).is(BlockTags.BEDS) && level.getBlockState(p).getValue(BedBlock.OCCUPIED) == Boolean.FALSE && level.getBlockState(p).getValue(BedBlock.PART) == BedPart.HEAD).toList(); + Direction bedDirection; + if (bedPartPositions.size() == 1 && validBedHeadPositions.contains(bedPartPositions.getFirst())) { + bedDirection = Direction.Plane.HORIZONTAL.stream().skip(validBedHeadPositions.indexOf(bedPartPositions.getFirst())).findAny().orElse(null); + } else { + simulator.onBadRNG("invalidBedPosition"); + sendInvalidSetupHelp(); + return; + } + + for (Direction direction : Direction.Plane.HORIZONTAL) { + BlockPos airPos = pos.relative(direction); + BlockPos trapdoorPos = airPos.above(); + BlockState airPosState = level.getBlockState(airPos); + BlockState trapdoorPosState = level.getBlockState(trapdoorPos); + if (!((airPosState.isAir() || direction != bedDirection) && trapdoorPosState.is(BlockTags.TRAPDOORS) && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.OPEN) == Boolean.FALSE)) { + simulator.onBadRNG("invalidCage"); + sendInvalidSetupHelp(); + return; + } + } + } + } + } + private static void sendInvalidSetupHelp() { ClientCommandHelper.sendHelp(Component.translatable("villagerManip.help.setup.prefix").append(Component.translatable("villagerManip.help.setup.here").withStyle(ChatFormatting.UNDERLINE).withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://raw.githubusercontent.com/Earthcomputer/clientcommands/refs/heads/fabric/villager_rng_setup.png")))).append(Component.translatable("villagerManip.help.setup.suffix"))); } From 7e02d21319676e1cc797b80819199d71a049540f Mon Sep 17 00:00:00 2001 From: RTTV Date: Sun, 1 Dec 2024 15:31:51 -0500 Subject: [PATCH 68/78] oh yeah no that should be there --- .../earthcomputer/clientcommands/features/VillagerCracker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 99eea5f90..039aa22e5 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -221,7 +221,7 @@ public static void onServerTick() { CUtil.sendAtPreciseTime( System.nanoTime() + millisecondsUntilInteract * 1_000_000L, ServerboundInteractPacket.createInteractionPacket(targetVillager, false, InteractionHand.MAIN_HAND), - () -> true, + VillagerCracker::isRunning, () -> { LocalPlayer player = Minecraft.getInstance().player; if (player == oldPlayer) { From d1d8ce396199236ae8e4d8eaf56779a174241018 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sun, 1 Dec 2024 15:33:38 -0500 Subject: [PATCH 69/78] removed useless fn --- .../clientcommands/features/VillagerCracker.java | 2 +- .../clientcommands/features/VillagerRngSimulator.java | 6 +----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 039aa22e5..6d6d166e5 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -213,7 +213,7 @@ public static void onServerTick() { simulator.simulateTick(); - if (simulator.getCrackedState().isCracked() && isRunning() && !hasClickedVillager) { + if (simulator.isCracked() && isRunning() && !hasClickedVillager) { int millisecondsUntilInteract = simulator.getTicksRemaining() * serverMspt - PingCommand.getLocalPing() + magicMillisecondCorrection; if (millisecondsUntilInteract < 200) { LocalPlayer oldPlayer = Minecraft.getInstance().player; diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index f0c0c1af5..3e09e56cb 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -221,7 +221,7 @@ public CrackedState getCrackedState() { } public boolean isCracked() { - return getCrackedState().isCracked(); + return getCrackedState() == CrackedState.CRACKED; } public boolean isAtLeastPartiallyCracked() { @@ -521,10 +521,6 @@ public enum CrackedState { PARTIALLY_CRACKED, CRACKED; - public boolean isCracked() { - return this == CRACKED; - } - public MutableComponent getMessage(boolean addColor) { return switch (this) { case UNCRACKED -> Component.translatable("commands.cvillager.uncracked").withStyle(addColor ? ChatFormatting.RED : ChatFormatting.RESET); From d5bbb5addb4f4ffa9aa7ae0e9ea1adf6c6965685 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sun, 1 Dec 2024 15:36:35 -0500 Subject: [PATCH 70/78] me when wildcard imports --- .../features/VillagerCracker.java | 5 ++++- .../clientcommands/util/DebugRandom.java | 17 +++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 6d6d166e5..aaac20d0f 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -51,7 +51,10 @@ import org.jetbrains.annotations.Nullable; import java.lang.ref.WeakReference; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; import java.util.function.Predicate; public class VillagerCracker { diff --git a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java index de11482bf..6a442d92b 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java @@ -19,8 +19,21 @@ import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; -import javax.swing.*; -import java.awt.*; +import javax.swing.DefaultListModel; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JSplitPane; +import javax.swing.JTabbedPane; +import javax.swing.JTextArea; +import javax.swing.UIManager; +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; From fdb5e7b91cabb9830d8925d39ea8690512e89e10 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sun, 1 Dec 2024 15:45:20 -0500 Subject: [PATCH 71/78] it works, hooray --- .../features/VillagerCracker.java | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index aaac20d0f..6245ed31e 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -132,7 +132,7 @@ public static void setTargetVillager(@Nullable Villager villager) { ClientLevel level = Minecraft.getInstance().level; - if (level != null && level.getDayTime() % 24000 < 12000) { // todo, double check this works + if (level != null && level.getDayTime() % 24000 < 12000) { simulator.onBadRNG("day"); ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.day")); } @@ -257,41 +257,38 @@ private static void checkVillagerSetup() { simulator.onBadRNG("itemInMainHand"); } else { Level level = targetVillager.level(); + Vec3 pos = targetVillager.position(); + BlockPos blockPos = targetVillager.blockPosition(); - { - Vec3 pos = targetVillager.position(); - int villagersNearVillager = level.getEntities(EntityTypeTest.forExactClass(Villager.class), AABB.ofSize(pos, 10.0, 10.0, 10.0), entity -> entity.position().distanceToSqr(pos) <= 5.0 * 5.0).size(); - if (villagersNearVillager > 1) { - simulator.onBadRNG("gossip"); - return; - } + int villagersNearVillager = level.getEntities(EntityTypeTest.forExactClass(Villager.class), AABB.ofSize(pos, 10.0, 10.0, 10.0), entity -> entity.position().distanceToSqr(pos) <= 5.0 * 5.0).size(); + if (villagersNearVillager > 1) { + simulator.onBadRNG("gossip"); + return; } - { - BlockPos pos = targetVillager.blockPosition(); - List validBedHeadPositions = List.of(pos.north(3), pos.east(3), pos.south(3), pos.west(3)); - List bedPartPositions = BlockPos.withinManhattanStream(pos, 15, 7, 15).map(BlockPos::new).filter(p -> level.getBlockState(p).is(BlockTags.BEDS) && level.getBlockState(p).getValue(BedBlock.OCCUPIED) == Boolean.FALSE && level.getBlockState(p).getValue(BedBlock.PART) == BedPart.HEAD).toList(); - Direction bedDirection; - if (bedPartPositions.size() == 1 && validBedHeadPositions.contains(bedPartPositions.getFirst())) { - bedDirection = Direction.Plane.HORIZONTAL.stream().skip(validBedHeadPositions.indexOf(bedPartPositions.getFirst())).findAny().orElse(null); - } else { - simulator.onBadRNG("invalidBedPosition"); + List validBedHeadPositions = List.of(blockPos.north(3), blockPos.east(3), blockPos.south(3), blockPos.west(3)); + List bedHeadPositions = BlockPos.withinManhattanStream(blockPos, 15, 7, 15).map(BlockPos::new).filter(p -> level.getBlockState(p).is(BlockTags.BEDS) && level.getBlockState(p).getValue(BedBlock.OCCUPIED) == Boolean.FALSE && level.getBlockState(p).getValue(BedBlock.PART) == BedPart.HEAD).toList(); + Direction bedDirection; + if (bedHeadPositions.size() == 1 && validBedHeadPositions.contains(bedHeadPositions.getFirst())) { + bedDirection = Direction.Plane.HORIZONTAL.stream().skip(validBedHeadPositions.indexOf(bedHeadPositions.getFirst())).findAny().orElse(null); + } else { + simulator.onBadRNG("invalidBedPosition"); + sendInvalidSetupHelp(); + return; + } + + for (Direction direction : Direction.Plane.HORIZONTAL) { + BlockPos airPos = blockPos.relative(direction); + BlockPos trapdoorPos = airPos.above(); + BlockState airPosState = level.getBlockState(airPos); + BlockState trapdoorPosState = level.getBlockState(trapdoorPos); + if (!((airPosState.isAir() || direction != bedDirection) && trapdoorPosState.is(BlockTags.TRAPDOORS) && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.OPEN) == Boolean.FALSE)) { + simulator.onBadRNG("invalidCage"); sendInvalidSetupHelp(); return; } - - for (Direction direction : Direction.Plane.HORIZONTAL) { - BlockPos airPos = pos.relative(direction); - BlockPos trapdoorPos = airPos.above(); - BlockState airPosState = level.getBlockState(airPos); - BlockState trapdoorPosState = level.getBlockState(trapdoorPos); - if (!((airPosState.isAir() || direction != bedDirection) && trapdoorPosState.is(BlockTags.TRAPDOORS) && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.OPEN) == Boolean.FALSE)) { - simulator.onBadRNG("invalidCage"); - sendInvalidSetupHelp(); - return; - } - } } + } } From 6923b87a653fef926b9466dd6cdc228ff9045df5 Mon Sep 17 00:00:00 2001 From: RTTV Date: Sun, 1 Dec 2024 15:57:00 -0500 Subject: [PATCH 72/78] and that removes the stupid " from" at the end --- .../earthcomputer/clientcommands/command/VillagerCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index 41f8e9950..f3b541a60 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -130,7 +130,7 @@ private static int addGoal( String firstString = first == null ? null : first.string() + " " + CUtil.boundsToString(firstCount); String secondString = second == null ? null : second.string() + " " + CUtil.boundsToString(secondCount); - String resultString = result.string() + " " + CUtil.boundsToString(resultCount); + String resultString = (result.string().endsWith(" from") ? result.string().substring(0, result.string().length() - " from".length()) : result.string()) + " " + CUtil.boundsToString(resultCount); VillagerCracker.goals.add(new VillagerCracker.Goal( resultString, From 29a4a0a0cdab09ea948769c37285f71ec4d4eb1f Mon Sep 17 00:00:00 2001 From: RTTV Date: Sun, 1 Dec 2024 20:38:04 -0500 Subject: [PATCH 73/78] made changes from review --- docs/villager_rng_setup.png | Bin 0 -> 135646 bytes .../features/VillagerCracker.java | 20 +++++------- .../features/VillagerRngSimulator.java | 2 +- .../clientcommands/util/DebugRandom.java | 20 +++++------- .../assets/clientcommands/lang/en_us.json | 29 +++++++++--------- villager_rng_setup.png | Bin 265777 -> 0 bytes 6 files changed, 30 insertions(+), 41 deletions(-) create mode 100644 docs/villager_rng_setup.png delete mode 100644 villager_rng_setup.png diff --git a/docs/villager_rng_setup.png b/docs/villager_rng_setup.png new file mode 100644 index 0000000000000000000000000000000000000000..43b7d09808ba2693730561029b56a64f4cb72892 GIT binary patch literal 135646 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 SYj}5k{nO~` targetVillager.getFluidJumpThreshold() || targetVillager.isInLava()) { simulator.onBadRNG("swim"); } else if (!targetVillager.getActiveEffects().isEmpty()) { @@ -266,23 +266,17 @@ private static void checkVillagerSetup() { return; } - List validBedHeadPositions = List.of(blockPos.north(3), blockPos.east(3), blockPos.south(3), blockPos.west(3)); - List bedHeadPositions = BlockPos.withinManhattanStream(blockPos, 15, 7, 15).map(BlockPos::new).filter(p -> level.getBlockState(p).is(BlockTags.BEDS) && level.getBlockState(p).getValue(BedBlock.OCCUPIED) == Boolean.FALSE && level.getBlockState(p).getValue(BedBlock.PART) == BedPart.HEAD).toList(); - Direction bedDirection; - if (bedHeadPositions.size() == 1 && validBedHeadPositions.contains(bedHeadPositions.getFirst())) { - bedDirection = Direction.Plane.HORIZONTAL.stream().skip(validBedHeadPositions.indexOf(bedHeadPositions.getFirst())).findAny().orElse(null); - } else { + List bedHeadPositions = BlockPos.withinManhattanStream(blockPos, 16, 16, 16).map(BlockPos::new).filter(p -> p.distSqr(blockPos) <= 16.0 * 16.0).filter(p -> level.getBlockState(p).is(BlockTags.BEDS) && level.getBlockState(p).getValue(BedBlock.OCCUPIED) == Boolean.FALSE && level.getBlockState(p).getValue(BedBlock.PART) == BedPart.HEAD).toList(); + if (bedHeadPositions.size() != 1) { simulator.onBadRNG("invalidBedPosition"); sendInvalidSetupHelp(); return; } for (Direction direction : Direction.Plane.HORIZONTAL) { - BlockPos airPos = blockPos.relative(direction); - BlockPos trapdoorPos = airPos.above(); - BlockState airPosState = level.getBlockState(airPos); + BlockPos trapdoorPos = blockPos.relative(direction).above(); BlockState trapdoorPosState = level.getBlockState(trapdoorPos); - if (!((airPosState.isAir() || direction != bedDirection) && trapdoorPosState.is(BlockTags.TRAPDOORS) && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.OPEN) == Boolean.FALSE)) { + if (!(trapdoorPosState.is(BlockTags.TRAPDOORS) && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.OPEN) == Boolean.FALSE)) { simulator.onBadRNG("invalidCage"); sendInvalidSetupHelp(); return; @@ -293,7 +287,7 @@ private static void checkVillagerSetup() { } private static void sendInvalidSetupHelp() { - ClientCommandHelper.sendHelp(Component.translatable("villagerManip.help.setup.prefix").append(Component.translatable("villagerManip.help.setup.here").withStyle(ChatFormatting.UNDERLINE).withStyle(style -> style.withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://raw.githubusercontent.com/Earthcomputer/clientcommands/refs/heads/fabric/villager_rng_setup.png")))).append(Component.translatable("villagerManip.help.setup.suffix"))); + ClientCommandHelper.sendHelp(Component.translatable("villagerManip.help.setup", Component.translatable("villagerManip.help.setup.link").withStyle(style -> style.withUnderlined(true).withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://raw.githubusercontent.com/Earthcomputer/clientcommands/refs/heads/fabric/dpcs/villager_rng_setup.png"))))); } private static void onDisconnect() { diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 3e09e56cb..55981b1bf 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -321,7 +321,7 @@ public void onAmbientSoundPlayed(float pitch) { } public void onBadRNG(@Translatable(prefix = "villagerManip.reset.") String reason) { - ClientCommandHelper.sendFeedback(Component.translatable("villagerManip.reset", Component.translatable("villagerManip.reset." + reason)).withStyle(ChatFormatting.RED)); + ClientCommandHelper.sendError(Component.translatable("villagerManip.reset", Component.translatable("villagerManip.reset." + reason))); reset(); } diff --git a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java index 6a442d92b..602304b7a 100644 --- a/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java +++ b/src/main/java/net/earthcomputer/clientcommands/util/DebugRandom.java @@ -19,18 +19,7 @@ import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; -import javax.swing.DefaultListModel; -import javax.swing.JComponent; -import javax.swing.JFileChooser; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JList; -import javax.swing.JPanel; -import javax.swing.JScrollPane; -import javax.swing.JSplitPane; -import javax.swing.JTabbedPane; -import javax.swing.JTextArea; -import javax.swing.UIManager; +import javax.swing.*; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; @@ -273,6 +262,13 @@ class DebugRandomSourcePanel extends JPanel { add(tabbedPane, BorderLayout.CENTER); JPanel bottomPanel = new JPanel(); + JButton dumpStackTraceButton = new JButton("Dump stack trace"); + dumpStackTraceButton.addActionListener(e -> { + if (selectedStackTrace >= 0 && selectedStackTrace < DebugRandom.stackTraceById.size()) { + DebugRandom.LOGGER.info(DebugRandom.stackTraceById.get(selectedStackTrace)); + } + }); + bottomPanel.add(dumpStackTraceButton); add(bottomPanel, BorderLayout.SOUTH); } diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 71423dda9..089105049 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -266,7 +266,6 @@ "commands.cvillager.noProfession": "The targeted villager has no profession", "commands.cvillager.notAVillager": "Target was not a villager", "commands.cvillager.notLevel1": "The targeted villager has level above 1", - "commands.cvillager.uncracked": "Your villager's RNG is not cracked (~18 quintillion seeds remain)", "commands.cvillager.partiallyCracked": "Your villager's RNG is partially cracked (~83m seeds remain)", "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %s, you only have %s goals", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", @@ -274,28 +273,28 @@ "commands.cvillager.success": "Got the correct trade with correction of %sms", "commands.cvillager.target.cleared": "Target entity cleared", "commands.cvillager.target.set": "Target entity set", + "commands.cvillager.uncracked": "Your villager's RNG is not cracked (~18 quintillion seeds remain)", + "villagerManip.help.day": "Help: Villager RNG manipulation can only be done at night-time", + "villagerManip.help.setup": "Help: Trap the villager with trapdoors at their head with a bed's head between 3 and 16 blocks away, as seen in %s image", + "villagerManip.help.setup.link": "this", "villagerManip.reset": "Restarting villager RNG manipulation. Reason: %s", - "villagerManip.reset.mobHurt": "Mob Hurt", + "villagerManip.reset.ambient": "Bad Ambient Noise", "villagerManip.reset.day": "Daytime", - "villagerManip.reset.swim": "Swum", - "villagerManip.reset.potion": "Potion Effect Active", - "villagerManip.reset.itemEquipped": "Item Equipped", - "villagerManip.reset.gossip": "Gossip", "villagerManip.reset.distance": "Too far from villager", - "villagerManip.reset.ambient": "Bad Ambient Noise", + "villagerManip.reset.gossip": "Gossip", + "villagerManip.reset.invalidBedPosition": "Invalid Bed Position", + "villagerManip.reset.invalidCage": "Invalid Villager Cage", + "villagerManip.reset.itemEquipped": "Item Equipped", + "villagerManip.reset.itemInMainHand": "Item in Main Hand", + "villagerManip.reset.mobHurt": "Mob Hurt", "villagerManip.reset.no": "Bad Unhappy Noise", + "villagerManip.reset.potion": "Potion Effect Active", "villagerManip.reset.splash": "Bad Splash Noise", + "villagerManip.reset.swim": "Swum", + "villagerManip.reset.tooManyBeds": "Too many beds within 16 block radius of villager", "villagerManip.reset.xpOrb": "Bad XP Orb Size", "villagerManip.reset.yes": "Bad Happy Noise", - "villagerManip.reset.itemInMainHand": "Item in Main Hand", - "villagerManip.reset.invalidBedPosition": "Invalid Bed Position", - "villagerManip.reset.invalidCage": "Invalid Villager Cage", - - "villagerManip.help.day": "Help: Villager RNG manipulation can only be done at night-time", - "villagerManip.help.setup.prefix": "Help: Trap the villager with trapdoors at their head with a bed's head exactly 3 blocks away in any direction, as seen in ", - "villagerManip.help.setup.here": "this", - "villagerManip.help.setup.suffix": " image", "commands.cwe.playerNotFound": "Player not found", diff --git a/villager_rng_setup.png b/villager_rng_setup.png deleted file mode 100644 index cb9e1b27ef6eb0ce186b06ceb5ccee637cbac79d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 265777 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 Date: Mon, 2 Dec 2024 19:34:52 -0500 Subject: [PATCH 74/78] push --- .../assets/clientcommands/lang/en_us.json | 44 +++++++++---------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index d0bc315a3..5f3fc790f 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -313,27 +313,6 @@ "commands.cvillager.target.set": "Target entity set", "commands.cvillager.uncracked": "Your villager's RNG is not cracked (~18 quintillion seeds remain)", - "villagerManip.help.day": "Help: Villager RNG manipulation can only be done at night-time", - "villagerManip.help.setup": "Help: Trap the villager with trapdoors at their head with a bed's head between 3 and 16 blocks away, as seen in %s image", - "villagerManip.help.setup.link": "this", - "villagerManip.reset": "Restarting villager RNG manipulation. Reason: %s", - "villagerManip.reset.ambient": "Bad Ambient Noise", - "villagerManip.reset.day": "Daytime", - "villagerManip.reset.distance": "Too far from villager", - "villagerManip.reset.gossip": "Gossip", - "villagerManip.reset.invalidBedPosition": "Invalid Bed Position", - "villagerManip.reset.invalidCage": "Invalid Villager Cage", - "villagerManip.reset.itemEquipped": "Item Equipped", - "villagerManip.reset.itemInMainHand": "Item in Main Hand", - "villagerManip.reset.mobHurt": "Mob Hurt", - "villagerManip.reset.no": "Bad Unhappy Noise", - "villagerManip.reset.potion": "Potion Effect Active", - "villagerManip.reset.splash": "Bad Splash Noise", - "villagerManip.reset.swim": "Swum", - "villagerManip.reset.tooManyBeds": "Too many beds within 16 block radius of villager", - "villagerManip.reset.xpOrb": "Bad XP Orb Size", - "villagerManip.reset.yes": "Bad Happy Noise", - "commands.cwe.playerNotFound": "Player not found", "commands.cweather.reset": "Stopped overriding weather", @@ -436,5 +415,26 @@ "twoPlayerGame.clickToMakeYourMove": "Click here to make your move", "twoPlayerGame.incoming": "%s has made a move in %s", "twoPlayerGame.noGameWithPlayer": "Currently not playing a game with that player", - "twoPlayerGame.playerNotFound": "Player not found" + "twoPlayerGame.playerNotFound": "Player not found", + + "villagerManip.help.day": "Help: Villager RNG manipulation can only be done at night-time", + "villagerManip.help.setup": "Help: Trap the villager with trapdoors at their head with a bed's head between 3 and 16 blocks away, as seen in %s image", + "villagerManip.help.setup.link": "this", + "villagerManip.reset": "Restarting villager RNG manipulation. Reason: %s", + "villagerManip.reset.ambient": "Bad Ambient Noise", + "villagerManip.reset.day": "Daytime", + "villagerManip.reset.distance": "Too far from villager", + "villagerManip.reset.gossip": "Gossip", + "villagerManip.reset.invalidBedPosition": "Invalid Bed Position", + "villagerManip.reset.invalidCage": "Invalid Villager Cage", + "villagerManip.reset.itemEquipped": "Item Equipped", + "villagerManip.reset.itemInMainHand": "Item in Main Hand", + "villagerManip.reset.mobHurt": "Mob Hurt", + "villagerManip.reset.no": "Bad Unhappy Noise", + "villagerManip.reset.potion": "Potion Effect Active", + "villagerManip.reset.splash": "Bad Splash Noise", + "villagerManip.reset.swim": "Swum", + "villagerManip.reset.tooManyBeds": "Too many beds within 16 block radius of villager", + "villagerManip.reset.xpOrb": "Bad XP Orb Size", + "villagerManip.reset.yes": "Bad Happy Noise" } From f75ae003065c6ee91a374fa34417ff85726c34b8 Mon Sep 17 00:00:00 2001 From: RTTV Date: Mon, 2 Dec 2024 19:43:04 -0500 Subject: [PATCH 75/78] mister taxi driver, i don't want your weird math! --- .../earthcomputer/clientcommands/features/VillagerCracker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index cf7578448..f3984f7fa 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -266,7 +266,7 @@ private static void checkVillagerSetup() { return; } - List bedHeadPositions = BlockPos.withinManhattanStream(blockPos, 16, 16, 16).map(BlockPos::new).filter(p -> p.distSqr(blockPos) <= 16.0 * 16.0).filter(p -> level.getBlockState(p).is(BlockTags.BEDS) && level.getBlockState(p).getValue(BedBlock.OCCUPIED) == Boolean.FALSE && level.getBlockState(p).getValue(BedBlock.PART) == BedPart.HEAD).toList(); + List bedHeadPositions = BlockPos.betweenClosedStream(blockPos.offset(-16, -16, -16), blockPos.offset(16, 16, 16)).map(BlockPos::new).filter(p -> p.distSqr(blockPos) <= 16.0 * 16.0).filter(p -> level.getBlockState(p).is(BlockTags.BEDS) && level.getBlockState(p).getValue(BedBlock.OCCUPIED) == Boolean.FALSE && level.getBlockState(p).getValue(BedBlock.PART) == BedPart.HEAD).toList(); if (bedHeadPositions.size() != 1) { simulator.onBadRNG("invalidBedPosition"); sendInvalidSetupHelp(); From d1054fab0c6ee37c2db27b5f88b53c5311c84c0c Mon Sep 17 00:00:00 2001 From: joe Date: Tue, 3 Dec 2024 01:44:41 +0000 Subject: [PATCH 76/78] Include commit hash in clientcommands build and use it in github link in villager rng invalid setup help --- build.gradle | 7 +++ .../buildscript/GenerateBuildInfoTask.kt | 40 ++++++++++++++++ .../features/VillagerCracker.java | 13 ++++- .../clientcommands/util/BuildInfo.java | 48 +++++++++++++++++++ 4 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 buildSrc/src/main/kotlin/net/earthcomputer/clientcommands/buildscript/GenerateBuildInfoTask.kt create mode 100644 src/main/java/net/earthcomputer/clientcommands/util/BuildInfo.java diff --git a/build.gradle b/build.gradle index 0b57d410e..fd163f761 100644 --- a/build.gradle +++ b/build.gradle @@ -1,4 +1,5 @@ import net.earthcomputer.clientcommands.buildscript.CheckLanguageFilesTask +import net.earthcomputer.clientcommands.buildscript.GenerateBuildInfoTask plugins { id 'fabric-loom' version '1.9-SNAPSHOT' @@ -94,6 +95,10 @@ jar { from("LICENSE") } +tasks.register('generateBuildInfo', GenerateBuildInfoTask) { + outputFile = new File(temporaryDir, "build_info.json") +} + processResources { inputs.property "version", project.version inputs.property "mcversion", project.minecraft_version_dependency @@ -108,6 +113,8 @@ processResources { from(sourceSets.main.resources.srcDirs) { exclude "fabric.mod.json" } + + from generateBuildInfo } java { diff --git a/buildSrc/src/main/kotlin/net/earthcomputer/clientcommands/buildscript/GenerateBuildInfoTask.kt b/buildSrc/src/main/kotlin/net/earthcomputer/clientcommands/buildscript/GenerateBuildInfoTask.kt new file mode 100644 index 000000000..27a95be90 --- /dev/null +++ b/buildSrc/src/main/kotlin/net/earthcomputer/clientcommands/buildscript/GenerateBuildInfoTask.kt @@ -0,0 +1,40 @@ +package net.earthcomputer.clientcommands.buildscript + +import com.google.gson.Gson +import com.google.gson.JsonObject +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.tasks.OutputFile +import org.gradle.api.tasks.TaskAction +import org.gradle.process.ExecOperations +import java.io.ByteArrayOutputStream +import javax.inject.Inject + +abstract class GenerateBuildInfoTask : DefaultTask() { + @get:OutputFile + abstract val outputFile: RegularFileProperty + + @get:Inject + protected abstract val execOperations: ExecOperations + + init { + outputs.upToDateWhen { false } + } + + @TaskAction + fun run() { + val gitCommitHashBytes = ByteArrayOutputStream() + execOperations.exec { + commandLine("git", "rev-parse", "HEAD") + standardOutput = gitCommitHashBytes + }.rethrowFailure() + val commitHash = gitCommitHashBytes.toByteArray().decodeToString().trim() + + val json = JsonObject() + json.addProperty("commit_hash", commitHash) + + outputFile.asFile.get().writer().use { + Gson().toJson(json, it) + } + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index f3984f7fa..13ebe3058 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -10,6 +10,7 @@ import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.event.ClientConnectionEvents; import net.earthcomputer.clientcommands.event.MoreClientEvents; +import net.earthcomputer.clientcommands.util.BuildInfo; import net.earthcomputer.clientcommands.util.CUtil; import net.earthcomputer.clientcommands.util.CombinedMedianEM; import net.minecraft.ChatFormatting; @@ -287,7 +288,17 @@ private static void checkVillagerSetup() { } private static void sendInvalidSetupHelp() { - ClientCommandHelper.sendHelp(Component.translatable("villagerManip.help.setup", Component.translatable("villagerManip.help.setup.link").withStyle(style -> style.withUnderlined(true).withClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://raw.githubusercontent.com/Earthcomputer/clientcommands/refs/heads/fabric/dpcs/villager_rng_setup.png"))))); + ClientCommandHelper.sendHelp( + Component.translatable("villagerManip.help.setup", + Component.translatable("villagerManip.help.setup.link").withStyle(style -> style + .withUnderlined(true) + .withClickEvent(new ClickEvent( + ClickEvent.Action.OPEN_URL, + "https://github.com/Earthcomputer/clientcommands/blob/%s/docs/villager_rng_setup.png?raw=true".formatted(BuildInfo.INSTANCE.shortCommitHash(10)) + )) + ) + ) + ); } private static void onDisconnect() { diff --git a/src/main/java/net/earthcomputer/clientcommands/util/BuildInfo.java b/src/main/java/net/earthcomputer/clientcommands/util/BuildInfo.java new file mode 100644 index 000000000..76dca6aac --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/util/BuildInfo.java @@ -0,0 +1,48 @@ +package net.earthcomputer.clientcommands.util; + +import com.google.gson.FieldNamingPolicy; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.mojang.logging.LogUtils; +import net.fabricmc.loader.api.FabricLoader; +import net.minecraft.Util; +import org.slf4j.Logger; + +import java.io.BufferedReader; +import java.nio.file.Files; +import java.nio.file.Path; + +public record BuildInfo(String commitHash) { + private static final Logger LOGGER = LogUtils.getLogger(); + + private static final BuildInfo UNKNOWN = new BuildInfo("refs/heads/fabric"); + + public static final BuildInfo INSTANCE = Util.make(() -> { + Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES).create(); + + Path buildInfoPath = FabricLoader.getInstance().getModContainer("clientcommands") + .orElseThrow() + .findPath("build_info.json") + .orElse(null); + if (buildInfoPath == null) { + LOGGER.warn("Couldn't find build_info.json"); + return UNKNOWN; + } + + try (BufferedReader reader = Files.newBufferedReader(buildInfoPath)) { + BuildInfo result = gson.fromJson(reader, BuildInfo.class); + if (result == null) { + LOGGER.warn("build_info.json was null or empty"); + return UNKNOWN; + } + return result; + } catch (Throwable e) { + LOGGER.warn("Couldn't read build_info.json", e); + return UNKNOWN; + } + }); + + public String shortCommitHash(int length) { + return this == UNKNOWN || length >= commitHash.length() ? commitHash : commitHash.substring(0, length); + } +} From cc85f30179cf9a445d7c23e899e435b8af58b489 Mon Sep 17 00:00:00 2001 From: RTTV Date: Tue, 3 Dec 2024 20:50:17 -0500 Subject: [PATCH 77/78] forgor --- .../net/earthcomputer/clientcommands/Configs.java | 10 +++------- .../clientcommands/command/VillagerCommand.java | 14 +++++++------- .../clientcommands/features/FishingCracker.java | 8 ++++---- .../clientcommands/features/VillagerCracker.java | 2 +- 4 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/main/java/net/earthcomputer/clientcommands/Configs.java b/src/main/java/net/earthcomputer/clientcommands/Configs.java index 6bf464a39..d3ec6597f 100644 --- a/src/main/java/net/earthcomputer/clientcommands/Configs.java +++ b/src/main/java/net/earthcomputer/clientcommands/Configs.java @@ -173,13 +173,9 @@ public static void setMinimumReplyDelaySeconds(float minimumReplyDelaySeconds) { Configs.minimumReplyDelaySeconds = Math.clamp(minimumReplyDelaySeconds, 0.0f, ReplyCommand.MAXIMUM_REPLY_DELAY_SECONDS); } - @Config(setter = @Config.Setter("setVillagerManipulation"), temporary = true) - private static boolean villagerManipulation = false; - public static boolean getVillagerManipulation() { - return villagerManipulation; - } - public static void setVillagerManipulation(boolean villagerManipulation) { - Configs.villagerManipulation = villagerManipulation; + @Config(onChange = "onChangeVillagerManipulation", temporary = true) + public static boolean villagerManipulation = false; + public static void onChangeVillagerManipulation(boolean oldVillagerManipulation, boolean villagerManipulation) { if (villagerManipulation) { ServerBrandManager.rngWarning(); } else { diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index f3b541a60..d1d4098ed 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -124,7 +124,7 @@ private static int addGoal( checkStackSize(second, secondCount); } - if (!Configs.getVillagerManipulation()) { + if (!Configs.villagerManipulation) { throw NEED_VILLAGER_MANIPULATION_EXCEPTION.create(); } @@ -158,7 +158,7 @@ private static void checkStackSize(WithStringArgument.Result { - if (Configs.getFishingManipulation().isEnabled()) { + if (Configs.fishingManipulation.isEnabled()) { onTimeSync(); } }); @@ -594,7 +594,7 @@ private static void onTimeSync() { new ServerboundUseItemPacket(InteractionHand.MAIN_HAND, 0, player.getYRot(), player.getXRot()), () -> { oldFishingHook[0] = player.fishing; - return Configs.getFishingManipulation().isEnabled() && state == State.ASYNC_WAITING_FOR_FISH; + return Configs.fishingManipulation.isEnabled() && state == State.ASYNC_WAITING_FOR_FISH; }, () -> { if (player == Minecraft.getInstance().player) { diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 13ebe3058..3097c9ebf 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -186,7 +186,7 @@ public static void onXpOrbSpawned(ClientboundAddExperienceOrbPacket packet) { private static void onTimeSync() { long now = System.nanoTime(); - if (Configs.getVillagerManipulation() && clockPos != null && !isNewClock && clockTicksSinceLastTimeSync != 20) { + if (Configs.villagerManipulation && clockPos != null && !isNewClock && clockTicksSinceLastTimeSync != 20) { if (now - lastClockRateWarning >= 60_000_000_000L) { if (clockTicksSinceLastTimeSync < 20) { ClientCommandHelper.sendHelp(Component.translatable("commands.cvillager.help.tooSlow")); From bcdc53c55676bad96e907ac82542e0c9f2e7f832 Mon Sep 17 00:00:00 2001 From: Katie Date: Sun, 26 Jan 2025 22:07:18 -0500 Subject: [PATCH 78/78] added checks for villager rng waiting state so it doesn't break added `reset` subcommand levelUp code is still broken --- .../command/VillagerCommand.java | 40 ++++- .../features/VillagerCracker.java | 141 ++++++++++++++---- .../features/VillagerRngSimulator.java | 16 +- .../clientcommands/mixin/VillagerMixin.java | 23 +++ .../villager/ClientPacketListenerMixin.java | 2 +- .../villager/MerchantScreenMixin.java | 1 - .../assets/clientcommands/lang/en_us.json | 8 +- src/main/resources/clientcommands.aw | 3 + src/main/resources/mixins.clientcommands.json | 1 + 9 files changed, 193 insertions(+), 42 deletions(-) create mode 100644 src/main/java/net/earthcomputer/clientcommands/mixin/VillagerMixin.java diff --git a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java index d1d4098ed..5093027ba 100644 --- a/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java +++ b/src/main/java/net/earthcomputer/clientcommands/command/VillagerCommand.java @@ -14,6 +14,7 @@ import net.earthcomputer.clientcommands.task.SimpleTask; import net.earthcomputer.clientcommands.task.TaskManager; import net.earthcomputer.clientcommands.util.CUtil; +import net.earthcomputer.clientcommands.util.CombinedMedianEM; import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource; import net.minecraft.ChatFormatting; import net.minecraft.advancements.critereon.MinMaxBounds; @@ -53,6 +54,7 @@ public class VillagerCommand { private static final SimpleCommandExceptionType NOT_LEVEL_1_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.notLevel1")); private static final SimpleCommandExceptionType NO_GOALS_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.listGoals.noGoals")); private static final SimpleCommandExceptionType ALREADY_RUNNING_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.alreadyRunning")); + private static final SimpleCommandExceptionType CANNOT_MODIFY_GOALS_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.cannotModifyGoals")); private static final Dynamic2CommandExceptionType INVALID_GOAL_INDEX_EXCEPTION = new Dynamic2CommandExceptionType((index, length) -> Component.translatable("commands.cvillager.removeGoal.invalidIndex", index, length)); private static final Dynamic2CommandExceptionType ITEM_OVERSTACKED_EXCEPTION = new Dynamic2CommandExceptionType((item, stackSize) -> Component.translatable("arguments.item.overstacked", item, stackSize)); private static final SimpleCommandExceptionType NEED_VILLAGER_MANIPULATION_EXCEPTION = new SimpleCommandExceptionType(Component.translatable("commands.cvillager.needVillagerManipulation") @@ -104,7 +106,13 @@ public static void register(CommandDispatcher dispatc .then(literal("first-level") .executes(ctx -> start(false))) .then(literal("next-level") - .executes(ctx -> start(true))))); + .executes(ctx -> start(true)))) + .then(literal("reset") + .executes(ctx -> reset())) + .then(literal("reset-correction") + .executes(ctx -> resetCorrection(-25)) + .then(argument("correction", integer()) + .executes(ctx -> resetCorrection(getInteger(ctx, "correction")))))); } private static int addGoal( @@ -128,6 +136,10 @@ private static int addGoal( throw NEED_VILLAGER_MANIPULATION_EXCEPTION.create(); } + if (VillagerCracker.isRunning()) { + throw CANNOT_MODIFY_GOALS_EXCEPTION.create(); + } + String firstString = first == null ? null : first.string() + " " + CUtil.boundsToString(firstCount); String secondString = second == null ? null : second.string() + " " + CUtil.boundsToString(secondCount); String resultString = (result.string().endsWith(" from") ? result.string().substring(0, result.string().length() - " from".length()) : result.string()) + " " + CUtil.boundsToString(resultCount); @@ -179,6 +191,10 @@ private static int removeGoal(FabricClientCommandSource source, int index) throw throw NEED_VILLAGER_MANIPULATION_EXCEPTION.create(); } + if (VillagerCracker.isRunning()) { + throw CANNOT_MODIFY_GOALS_EXCEPTION.create(); + } + index = index - 1; if (index < VillagerCracker.goals.size()) { VillagerCracker.Goal goal = VillagerCracker.goals.remove(index); @@ -268,7 +284,9 @@ private static int start(boolean levelUp) throws CommandSyntaxException { int crackedLevel = levelUp ? currentLevel + 1 : currentLevel; VillagerTrades.ItemListing[] listings = VillagerTrades.TRADES.get(profession).getOrDefault(crackedLevel, new VillagerTrades.ItemListing[0]); - int adjustmentTicks = levelUp ? -40 : 0; + // 39 ticks ahead instead of 40 because the two trade xp calls act as one effective tick. + // this means we have to do our trades for one tick into the future because we'll be re-adjusting for this + int adjustmentTicks = levelUp ? -39 : 0; VillagerRngSimulator.BruteForceResult result = VillagerCracker.simulator.bruteForceOffers(listings, levelUp ? 240 : 10, Configs.maxVillagerManipulationWaitTicks, offer -> VillagerCracker.goals.stream().anyMatch(goal -> goal.matches(offer))); if (result == null) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.bruteForce.failed", Configs.maxVillagerManipulationWaitTicks).withStyle(ChatFormatting.RED), 100); @@ -285,9 +303,12 @@ private static int start(boolean levelUp) throws CommandSyntaxException { price = displayText(offer.first(), false) + " + " + displayText(offer.second(), false); } ClientCommandHelper.sendFeedback(Component.translatable("commands.cvillager.bruteForce.success", displayText(offer.result(), false), price, ticks).withStyle(ChatFormatting.GREEN)); + System.out.println("Expected seed: " + Long.toHexString(result.seed())); VillagerCracker.targetOffer = offer; VillagerCracker.surroundingOffers = surroundingOffers; - VillagerCracker.hasClickedVillager = false; + VillagerCracker.hasQueuedInteractionPackets = false; + VillagerCracker.hasSentInteractionPackets = false; + VillagerCracker.isFirstLevelCrack = !levelUp; VillagerCracker.simulator.setTicksUntilInteract(ticks); TaskManager.addTask("cvillagerWaiting", new SimpleTask() { @Override @@ -312,6 +333,19 @@ public void onCompleted() { return Command.SINGLE_SUCCESS; } + private static int reset() { + VillagerCracker.reset(); + ClientCommandHelper.sendFeedback("commands.cvillager.reset"); + return Command.SINGLE_SUCCESS; + } + + private static int resetCorrection(int correction) { + VillagerCracker.combinedMedianEM = new CombinedMedianEM(); + VillagerCracker.magicMillisecondCorrection = correction; + ClientCommandHelper.sendFeedback("commands.cvillager.resetCorrection", correction); + return Command.SINGLE_SUCCESS; + } + public static String displayText(ItemStack stack, boolean hideCount) { String quantityPrefix = hideCount || stack.getCount() == 1 ? "" : stack.getCount() + " "; List lines = stack.getTooltipLines(Item.TooltipContext.EMPTY, null, TooltipFlag.NORMAL); diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java index 3097c9ebf..a23cd25ab 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerCracker.java @@ -16,6 +16,7 @@ import net.minecraft.ChatFormatting; import net.minecraft.SharedConstants; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.screens.inventory.MerchantScreen; import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.player.LocalPlayer; import net.minecraft.core.BlockPos; @@ -26,6 +27,7 @@ import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundAddExperienceOrbPacket; import net.minecraft.network.protocol.game.ClientboundSoundPacket; +import net.minecraft.network.protocol.game.ServerboundContainerClosePacket; import net.minecraft.network.protocol.game.ServerboundInteractPacket; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; @@ -36,6 +38,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.npc.Villager; import net.minecraft.world.entity.npc.VillagerProfession; +import net.minecraft.world.inventory.ClickType; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.trading.ItemCost; import net.minecraft.world.item.trading.MerchantOffer; @@ -76,14 +79,16 @@ public class VillagerCracker { public static VillagerRngSimulator.SurroundingOffers surroundingOffers = null; private static int clockTicksSinceLastTimeSync = 0; private static long lastClockRateWarning = 0; - public static boolean hasClickedVillager = false; + public static boolean hasSentInteractionPackets = false; + public static boolean hasQueuedInteractionPackets = false; + public static boolean isFirstLevelCrack = true; private static long lastTimeSyncTime; public static int serverMspt = SharedConstants.MILLIS_PER_TICK; public static int magicMillisecondCorrection = 25; public static int maxTicksBefore = 10; public static int maxTicksAfter = 10; - public static final CombinedMedianEM combinedMedianEM = new CombinedMedianEM(); + public static CombinedMedianEM combinedMedianEM = new CombinedMedianEM(); static { ClientConnectionEvents.DISCONNECT.register(VillagerCracker::onDisconnect); @@ -134,7 +139,7 @@ public static void setTargetVillager(@Nullable Villager villager) { ClientLevel level = Minecraft.getInstance().level; if (level != null && level.getDayTime() % 24000 < 12000) { - simulator.onBadRNG("day"); + simulator.onBadSetup("day"); ClientCommandHelper.sendHelp(Component.translatable("villagerManip.help.day")); } @@ -170,7 +175,7 @@ public static void onSoundEventPlayed(ClientboundSoundPacket packet, Vec3 pos) { } else if (soundEvent == SoundEvents.GENERIC_SPLASH) { simulator.onSplashSoundPlayed(packet.getPitch()); } else if (BuiltInRegistries.SOUND_EVENT.getKey(soundEvent).getPath().startsWith("item.armor.equip_")) { - simulator.onBadRNG("itemEquipped"); + simulator.onBadSetup("itemEquipped"); } } @@ -212,50 +217,98 @@ public static void onServerTick() { } if (simulator.isAtLeastPartiallyCracked()) { - checkVillagerSetup(); + checkVillagerStateSetup(); } simulator.simulateTick(); - if (simulator.isCracked() && isRunning() && !hasClickedVillager) { - int millisecondsUntilInteract = simulator.getTicksRemaining() * serverMspt - PingCommand.getLocalPing() + magicMillisecondCorrection; - if (millisecondsUntilInteract < 200) { - LocalPlayer oldPlayer = Minecraft.getInstance().player; - assert oldPlayer != null; + if (isRunning() && checkVillagerWaitingStateSetup() && !hasQueuedInteractionPackets && simulator.isCracked()) { + trySendInteraction(); + } + } + + private static void trySendInteraction() { + final Minecraft mc = Minecraft.getInstance(); + final Villager targetVillager = getVillager(); + final long nanoTime = System.nanoTime(); + int millisecondsUntilInteract = simulator.getTicksRemaining() * serverMspt - PingCommand.getLocalPing() + magicMillisecondCorrection; + if (millisecondsUntilInteract < 200) { + LocalPlayer oldPlayer = mc.player; + assert oldPlayer != null; + + if (isFirstLevelCrack) { + CUtil.sendAtPreciseTime( + nanoTime + millisecondsUntilInteract * 1_000_000L, + ServerboundInteractPacket.createInteractionPacket(targetVillager, false, InteractionHand.MAIN_HAND), + VillagerCracker::isRunning, + () -> { + LocalPlayer player = mc.player; + if (player == oldPlayer) { + player.swing(InteractionHand.MAIN_HAND); + } + hasSentInteractionPackets = true; + } + ); + } else { + // todo: could potentially still break if a "hrmm" happens between this and the interaction + if (!(mc.screen instanceof MerchantScreen screen)) { + simulator.onBadSetup("wrongScreen"); + return; + } + + screen.slotClicked(screen.getMenu().slots.get(2), 2, 0, ClickType.QUICK_MOVE); + + CUtil.sendAtPreciseTime( + nanoTime + millisecondsUntilInteract * 1_000_000L, + new ServerboundContainerClosePacket(oldPlayer.containerMenu.containerId), + VillagerCracker::isRunning, + () -> { + LocalPlayer player = mc.player; + player.clientSideCloseContainer(); + hasSentInteractionPackets = true; + } + ); + + // debug CUtil.sendAtPreciseTime( - System.nanoTime() + millisecondsUntilInteract * 1_000_000L, + nanoTime + (millisecondsUntilInteract + 41L * serverMspt) * 1_000_000L, ServerboundInteractPacket.createInteractionPacket(targetVillager, false, InteractionHand.MAIN_HAND), VillagerCracker::isRunning, () -> { - LocalPlayer player = Minecraft.getInstance().player; + LocalPlayer player = mc.player; if (player == oldPlayer) { player.swing(InteractionHand.MAIN_HAND); } } ); - simulator.resetWaitingState(); - hasClickedVillager = true; } + + simulator.resetWaitingState(); + hasQueuedInteractionPackets = true; } } - private static void checkVillagerSetup() { + private static boolean checkVillagerStateSetup() { final Minecraft mc = Minecraft.getInstance(); final Villager targetVillager = getVillager(); if (targetVillager == null) { - return; + return false; } if (!isResting(targetVillager.level().dayTime())) { - simulator.onBadRNG("day"); + simulator.onBadSetup("day"); ClientCommandHelper.sendHelp(Component.translatable("villagerManip.help.day")); + return false; } else if (targetVillager.isInWater() && targetVillager.getFluidHeight(FluidTags.WATER) > targetVillager.getFluidJumpThreshold() || targetVillager.isInLava()) { - simulator.onBadRNG("swim"); + simulator.onBadSetup("swim"); + return false; } else if (!targetVillager.getActiveEffects().isEmpty()) { - simulator.onBadRNG("potion"); + simulator.onBadSetup("potion"); + return false; } else if (!mc.player.getItemInHand(InteractionHand.MAIN_HAND).isEmpty()) { - simulator.onBadRNG("itemInMainHand"); + simulator.onBadSetup("itemInMainHand"); + return false; } else { Level level = targetVillager.level(); Vec3 pos = targetVillager.position(); @@ -263,28 +316,53 @@ private static void checkVillagerSetup() { int villagersNearVillager = level.getEntities(EntityTypeTest.forExactClass(Villager.class), AABB.ofSize(pos, 10.0, 10.0, 10.0), entity -> entity.position().distanceToSqr(pos) <= 5.0 * 5.0).size(); if (villagersNearVillager > 1) { - simulator.onBadRNG("gossip"); - return; + simulator.onBadSetup("gossip"); + return false; } List bedHeadPositions = BlockPos.betweenClosedStream(blockPos.offset(-16, -16, -16), blockPos.offset(16, 16, 16)).map(BlockPos::new).filter(p -> p.distSqr(blockPos) <= 16.0 * 16.0).filter(p -> level.getBlockState(p).is(BlockTags.BEDS) && level.getBlockState(p).getValue(BedBlock.OCCUPIED) == Boolean.FALSE && level.getBlockState(p).getValue(BedBlock.PART) == BedPart.HEAD).toList(); if (bedHeadPositions.size() != 1) { - simulator.onBadRNG("invalidBedPosition"); + simulator.onBadSetup("invalidBedPosition"); sendInvalidSetupHelp(); - return; + return false; } for (Direction direction : Direction.Plane.HORIZONTAL) { BlockPos trapdoorPos = blockPos.relative(direction).above(); BlockState trapdoorPosState = level.getBlockState(trapdoorPos); if (!(trapdoorPosState.is(BlockTags.TRAPDOORS) && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.HALF) == Half.TOP && trapdoorPosState.getValue(TrapDoorBlock.OPEN) == Boolean.FALSE)) { - simulator.onBadRNG("invalidCage"); + simulator.onBadSetup("invalidCage"); sendInvalidSetupHelp(); - return; + return false; } } + } + return true; + } + + private static boolean checkVillagerWaitingStateSetup() { + if (!Configs.villagerManipulation) { + simulator.onBadSetup("manipInactive"); + stopRunning(); + return false; + } + + Villager targetVillager = VillagerCracker.getVillager(); + if (targetVillager == null || !VillagerCracker.simulator.isCracked()) { + simulator.onBadSetup("uncrackedMisc"); + stopRunning(); + return false; } + + VillagerProfession profession = targetVillager.getVillagerData().getProfession(); + if (profession == VillagerProfession.NONE) { + simulator.onBadSetup("professionLost"); + stopRunning(); + return false; + } + + return true; } private static void sendInvalidSetupHelp() { @@ -351,13 +429,14 @@ public static void onGuiOpened(List actualOffersList) { return; } + // potentially not required? if (player.distanceTo(villager) > 2.0) { - simulator.onBadRNG("distance"); + simulator.onBadSetup("distance"); stopRunning(); return; } - if (isRunning()) { + if ((VillagerCracker.isFirstLevelCrack && isRunning()) || (!VillagerCracker.isFirstLevelCrack && VillagerCracker.hasSentInteractionPackets)) { int[] possibleTicksAhead = possibleTicksAhead(actualOffersList.toArray(Offer[]::new), surroundingOffers); // chop possible ticks ahead into a limited reasonable range final int consideredTickRange = 21; @@ -397,11 +476,17 @@ public static void onGuiOpened(List actualOffersList) { simulator.reset(); stopRunning(); + hasQueuedInteractionPackets = false; + hasSentInteractionPackets = false; + isFirstLevelCrack = true; } } public static void reset() { simulator.reset(); + isFirstLevelCrack = true; + hasSentInteractionPackets = false; + hasQueuedInteractionPackets = false; clockPos = null; villagerUuid = null; cachedVillager = new WeakReference<>(null); diff --git a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java index 55981b1bf..3ded7c7ae 100644 --- a/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java +++ b/src/main/java/net/earthcomputer/clientcommands/features/VillagerRngSimulator.java @@ -254,7 +254,7 @@ public String toString() { public void onAmbientSoundPlayed(float pitch) { boolean justReset = false; if (totalAmbientSounds == 2 && !madeSound) { - onBadRNG("ambient"); + onBadSetup("ambient"); justReset = true; } @@ -320,7 +320,7 @@ public void onAmbientSoundPlayed(float pitch) { } } - public void onBadRNG(@Translatable(prefix = "villagerManip.reset.") String reason) { + public void onBadSetup(@Translatable(prefix = "villagerManip.reset.") String reason) { ClientCommandHelper.sendError(Component.translatable("villagerManip.reset", Component.translatable("villagerManip.reset." + reason))); reset(); } @@ -335,7 +335,7 @@ public void onNoSoundPlayed(float pitch, boolean fromGuiInteract) { } float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; if (pitch != simulatedPitch) { - onBadRNG("no"); + onBadSetup("no"); } else { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); } @@ -350,7 +350,7 @@ public void onYesSoundPlayed(float pitch) { ambientSoundTime = -80; float simulatedPitch = (random.nextFloat() - random.nextFloat()) * 0.2f + 1.0f; if (pitch != simulatedPitch) { - onBadRNG("yes"); + onBadSetup("yes"); } else { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); } @@ -372,7 +372,7 @@ public void onSplashSoundPlayed(float pitch) { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); } else { - onBadRNG("splash"); + onBadSetup("splash"); } } } @@ -386,7 +386,7 @@ public void onXpOrbSpawned(int value) { boolean leveledUp = value > 3 + 3; if (leveledUp) simulatedValue += 5; if (value != simulatedValue) { - onBadRNG("xpOrb"); + onBadSetup("xpOrb"); } else { ClientCommandHelper.addOverlayMessage(Component.translatable("commands.cvillager.inSync", Long.toHexString(random.getSeed())).withStyle(ChatFormatting.GREEN), 100); } @@ -412,7 +412,7 @@ public VillagerRngSimulator.BruteForceResult bruteForceOffers(VillagerTrades.Ite VillagerCracker.Offer offer = offerSimulator.anyOffersMatch(listings, targetVillager, predicate); if (offer != null) { // we do the calls before this ticks processing so that since with 0ms ping, the server reads it next tick - return new BruteForceResult(ticksPassed, offer); + return new BruteForceResult(ticksPassed, offer, offerSimulator.random.getSeed()); } branchedSimulator.simulateTick(); } @@ -530,7 +530,7 @@ public MutableComponent getMessage(boolean addColor) { } } - public record BruteForceResult(int ticksPassed, VillagerCracker.Offer offer) { + public record BruteForceResult(int ticksPassed, VillagerCracker.Offer offer, long seed) { } public record SurroundingOffers(List before, VillagerCracker.Offer[] middle, List after) { diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/VillagerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/VillagerMixin.java new file mode 100644 index 000000000..910ad87df --- /dev/null +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/VillagerMixin.java @@ -0,0 +1,23 @@ +package net.earthcomputer.clientcommands.mixin; + +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.npc.Villager; +import net.minecraft.world.level.Level; +import net.minecraft.world.level.levelgen.LegacyRandomSource; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(Villager.class) +public abstract class VillagerMixin extends Entity { + public VillagerMixin(EntityType entityType, Level level) { + super(entityType, level); + } + + @Inject(method = "updateTrades", at = @At("HEAD")) + private void updateTrades(CallbackInfo ci) { + System.out.println("Actual seed: " + Long.toHexString(((LegacyRandomSource) random).seed.get())); + } +} diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java index ec7d97702..0833adc2c 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/ClientPacketListenerMixin.java @@ -60,7 +60,7 @@ private void onHandleBlockUpdate(ClientboundBlockUpdatePacket packet, CallbackIn @Inject(method = "handleDamageEvent", at = @At(value = "INVOKE", target = "Lnet/minecraft/world/entity/Entity;handleDamageEvent(Lnet/minecraft/world/damagesource/DamageSource;)V")) private void onHandleDamageEvent(ClientboundDamageEventPacket packet, CallbackInfo ci, @Local Entity entity) { if (entity == VillagerCracker.getVillager() && VillagerCracker.simulator.isAtLeastPartiallyCracked()) { - VillagerCracker.simulator.onBadRNG("mobHurt"); + VillagerCracker.simulator.onBadSetup("mobHurt"); } } } diff --git a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/MerchantScreenMixin.java b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/MerchantScreenMixin.java index 0a5288a32..59ccf3b57 100644 --- a/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/MerchantScreenMixin.java +++ b/src/main/java/net/earthcomputer/clientcommands/mixin/commands/villager/MerchantScreenMixin.java @@ -1,6 +1,5 @@ package net.earthcomputer.clientcommands.mixin.commands.villager; -import net.earthcomputer.clientcommands.command.VillagerCommand; import net.earthcomputer.clientcommands.features.VillagerCracker; import net.minecraft.client.gui.screens.inventory.AbstractContainerScreen; import net.minecraft.client.gui.screens.inventory.MerchantScreen; diff --git a/src/main/resources/assets/clientcommands/lang/en_us.json b/src/main/resources/assets/clientcommands/lang/en_us.json index 5f3fc790f..264c42039 100644 --- a/src/main/resources/assets/clientcommands/lang/en_us.json +++ b/src/main/resources/assets/clientcommands/lang/en_us.json @@ -286,6 +286,7 @@ "commands.cvillager.alreadyRunning": "Cannot brute-force villager RNG since villager RNG manipulation is already running", "commands.cvillager.bruteForce.failed": "Could not find a match for any goals within %s ticks", "commands.cvillager.bruteForce.success": "Found a match for %s priced at %s. Will open villager gui in %s ticks", + "commands.cvillager.cannotModifyGoals": "Cannot modify goals while villager is currently being cracked", "commands.cvillager.clock.cleared": "Your clock is cleared", "commands.cvillager.clock.set": "Clock set to %s %s %s (%s)", "commands.cvillager.clock.set.cleared": "Your clock is now cleared", @@ -307,7 +308,8 @@ "commands.cvillager.partiallyCracked": "Your villager's RNG is partially cracked (~83m seeds remain)", "commands.cvillager.removeGoal.invalidIndex": "Unable to remove goal %s, you only have %s goals", "commands.cvillager.removeGoal.success": "Successfully removed goal %s", - "commands.cvillager.resetCracker": "Successfully reset cracked villager RNG", + "commands.cvillager.reset": "Successfully reset villager cracking", + "commands.cvillager.resetCorrection": "Reset timing correction to %sms", "commands.cvillager.success": "Got the correct trade with correction of %sms", "commands.cvillager.target.cleared": "Target entity cleared", "commands.cvillager.target.set": "Target entity set", @@ -429,12 +431,16 @@ "villagerManip.reset.invalidCage": "Invalid Villager Cage", "villagerManip.reset.itemEquipped": "Item Equipped", "villagerManip.reset.itemInMainHand": "Item in Main Hand", + "villagerManip.reset.manipInactive": "Manipulation deactivated", "villagerManip.reset.mobHurt": "Mob Hurt", "villagerManip.reset.no": "Bad Unhappy Noise", "villagerManip.reset.potion": "Potion Effect Active", + "villagerManip.reset.professionLost": "Profession lost", "villagerManip.reset.splash": "Bad Splash Noise", "villagerManip.reset.swim": "Swum", "villagerManip.reset.tooManyBeds": "Too many beds within 16 block radius of villager", + "villagerManip.reset.uncrackedMisc": "Lost cracked state", + "villagerManip.reset.wrongScreen": "No villager GUI open", "villagerManip.reset.xpOrb": "Bad XP Orb Size", "villagerManip.reset.yes": "Bad Happy Noise" } diff --git a/src/main/resources/clientcommands.aw b/src/main/resources/clientcommands.aw index e601a6953..86be7dce3 100644 --- a/src/main/resources/clientcommands.aw +++ b/src/main/resources/clientcommands.aw @@ -42,6 +42,9 @@ accessible field net/minecraft/client/gui/components/EditBox maxLength I accessible class net/minecraft/client/renderer/RenderType$CompositeState accessible class net/minecraft/client/renderer/RenderStateShard$LineStateShard +# Villager Manipulation +accessible method net/minecraft/client/gui/screens/inventory/AbstractContainerScreen slotClicked (Lnet/minecraft/world/inventory/Slot;IILnet/minecraft/world/inventory/ClickType;)V + # RNG Events accessible method net/minecraft/world/entity/Entity isInvulnerableToBase (Lnet/minecraft/world/damagesource/DamageSource;)Z accessible field net/minecraft/world/entity/LivingEntity lastHurt F diff --git a/src/main/resources/mixins.clientcommands.json b/src/main/resources/mixins.clientcommands.json index d81e796ad..cd93592c5 100644 --- a/src/main/resources/mixins.clientcommands.json +++ b/src/main/resources/mixins.clientcommands.json @@ -3,6 +3,7 @@ "package": "net.earthcomputer.clientcommands.mixin", "compatibilityLevel": "JAVA_21", "mixins": [ + "VillagerMixin", "commands.enchant.EnchantmentScreenMixin", "commands.findblock.LevelChunkMixin", "commands.fish.FishingHookMixin",