Skip to content

Commit

Permalink
Make item throws smarter.
Browse files Browse the repository at this point in the history
We now rethrow items when the server rejects an item throw.
Also added a config option for item throw speed.
  • Loading branch information
Earthcomputer committed Mar 3, 2024
1 parent b4b3ee2 commit e7b9ec1
Show file tree
Hide file tree
Showing 9 changed files with 212 additions and 73 deletions.
63 changes: 36 additions & 27 deletions src/main/java/net/cortex/clientAddon/cracker/SeedCracker.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import net.earthcomputer.clientcommands.features.EnchantmentCracker;
import net.earthcomputer.clientcommands.features.PlayerRandCracker;
import net.earthcomputer.clientcommands.mixin.LegacyRandomSourceAccessor;
import net.earthcomputer.clientcommands.task.ItemThrowTask;
import net.earthcomputer.clientcommands.task.LongTask;
import net.earthcomputer.clientcommands.task.TaskManager;
import net.minecraft.ChatFormatting;
Expand All @@ -14,7 +15,6 @@
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.EntityType;

public class SeedCracker {
public interface OnCrack {void callback(long seed); }
Expand All @@ -26,23 +26,40 @@ public interface OnCrack {void callback(long seed); }
public static LongTask currentTask;
private static int attemptCount = 0;
private static final int MAX_ATTEMPTS = 10;
private static String currentTaskName = null;

//returns True on success or false on failer
private static boolean throwItems()
private static String throwItems()
{
LocalPlayer player = Minecraft.getInstance().player;
player.moveTo(player.getX(), player.getY(), player.getZ(), 0, 90);
Minecraft.getInstance().getConnection().send(new ServerboundMovePlayerPacket.Rot(0, 90, true)); // point to correct location
for (int i = 0; i < 20; i++) {
boolean success = PlayerRandCracker.throwItem();
if (!success) {
ItemThrowTask task = new ItemThrowTask(20) {
@Override
protected void onSuccess() {
SeedCracker.attemptCrack();
}

@Override
protected void onFailedToThrowItem() {
Minecraft.getInstance().gui.getChat().addMessage(Component.translatable("itemCrack.notEnoughItems").withStyle(ChatFormatting.RED));
EnchantmentCracker.LOGGER.info("Unable to use rng SeedCracker |not enough items|");
return false;
Configs.playerCrackState = PlayerRandCracker.CrackState.UNCRACKED;
currentTaskName = null;
}

@Override
protected void onItemSpawn(ClientboundAddEntityPacket packet) {
onEntityCreation(packet);
}
};
if (currentTaskName != null) {
TaskManager.forceAddTask(currentTaskName, task);
return currentTaskName;
} else {
return TaskManager.addTask("ccrackrng", task);
}
return true;
}

public static void attemptCrack()
{
long seed= Lattice_cracker.crack(SeedCracker.bits);
Expand All @@ -54,6 +71,7 @@ public static void attemptCrack()
ClientCommandHelper.sendError(Component.translatable("commands.ccrackrng.failed"));
ClientCommandHelper.sendHelp(Component.translatable("commands.ccrackrng.failed.help"));
Configs.playerCrackState = PlayerRandCracker.CrackState.UNCRACKED;
currentTaskName = null;
} else {
SeedCracker.doCrack(SeedCracker.callback);
}
Expand All @@ -77,6 +95,7 @@ public static void attemptCrack()
System.out.print(padLeftZeros(Long.toBinaryString((((long) (rand.nextFloat() * ((float) (1 << 24)))) >> (24 - 4))&0xFL), 4)+" \n");
}*/

currentTaskName = null;
callback.callback(((LegacyRandomSourceAccessor) rand).getSeed().get());//extract seed and call callback
}

Expand All @@ -88,35 +107,25 @@ public static void crack(OnCrack callback) {
private static void doCrack(OnCrack Callback){
callback=Callback;
ClientCommandHelper.addOverlayMessage(Component.translatable("commands.ccrackrng.retries", attemptCount, MAX_ATTEMPTS), 100);
if(throwItems())
{
Configs.playerCrackState = PlayerRandCracker.CrackState.CRACKING;
expectedItems=20;
if (currentTask == null) {
currentTask = new SeedCrackTask();
String taskName = TaskManager.addTask("ccrackrng", currentTask);
Component message = Component.translatable("commands.ccrackrng.starting")
.append(" ")
.append(ClientCommandHelper.getCommandTextComponent("commands.client.cancel", "/ctask stop " + taskName));
Minecraft.getInstance().gui.getChat().addMessage(message);
}
} else {
Configs.playerCrackState = PlayerRandCracker.CrackState.UNCRACKED;
currentTaskName = throwItems();
Configs.playerCrackState = PlayerRandCracker.CrackState.CRACKING;
expectedItems = 20;
if (attemptCount == 1) {
Component message = Component.translatable("commands.ccrackrng.starting")
.append(" ")
.append(ClientCommandHelper.getCommandTextComponent("commands.client.cancel", "/ctask stop " + currentTaskName));
Minecraft.getInstance().gui.getChat().addMessage(message);
}
}

public static void onEntityCreation(ClientboundAddEntityPacket packet) {
if (packet.getType() == EntityType.ITEM && Configs.playerCrackState == PlayerRandCracker.CrackState.CRACKING) {
if (Configs.playerCrackState == PlayerRandCracker.CrackState.CRACKING) {
if (SeedCracker.expectedItems > 0) {
long rand_val = (long) ((Math.atan2(packet.getZa(), packet.getXa()) + Math.PI) / (Math.PI * 2) * ((float) (1 << 24)));
long top_bits = rand_val;
short value = (short) (((top_bits >> (24 - 4)) ^ 0x8L )&0xFL);//INSTEAD OF ^0x8L MAYBE DO +math.pi OR SOMETHING ELSE
SeedCracker.bits[20-SeedCracker.expectedItems]=(long)value;//could be improved
SeedCracker.expectedItems--;
if (SeedCracker.expectedItems == 0) {
//if its the last item
SeedCracker.attemptCrack();
}
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/net/earthcomputer/clientcommands/Configs.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ public static void setMaxChorusItemThrows(int maxChorusItemThrows) {
@Config
public static boolean acceptC2CPackets = false;

@Config
public static float itemThrowsPerTick = 1;

public static boolean conditionLessThan1_20() {
return MultiVersionCompat.INSTANCE.getProtocolVersion() < MultiVersionCompat.V1_20;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@
import com.mojang.logging.LogUtils;
import net.earthcomputer.clientcommands.Configs;
import net.earthcomputer.clientcommands.MultiVersionCompat;
import net.earthcomputer.clientcommands.task.ItemThrowTask;
import net.earthcomputer.clientcommands.task.LongTask;
import net.earthcomputer.clientcommands.task.LongTaskList;
import net.earthcomputer.clientcommands.task.OneTickTask;
import net.earthcomputer.clientcommands.task.SimpleTask;
import net.earthcomputer.clientcommands.task.TaskManager;
import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft;
Expand All @@ -23,7 +23,6 @@
import net.minecraft.util.RandomSource;
import net.minecraft.util.StringRepresentable;
import net.minecraft.world.inventory.EnchantmentMenu;
import net.minecraft.world.inventory.Slot;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
Expand Down Expand Up @@ -373,33 +372,15 @@ public static ManipulateResult manipulateEnchantments(Item item, Predicate<List<
player.connection.send(new ServerboundMovePlayerPacket.Rot(player.getYRot(), 90, player.onGround()));
Configs.playerCrackState = PlayerRandCracker.CrackState.MANIPULATING_ENCHANTMENTS;
}
for (int i = 0; i < timesNeeded; i++) {
// throw the item once it's in the inventory
taskList.addTask(new SimpleTask() {
if (timesNeeded > 0) {
taskList.addTask(new ItemThrowTask(timesNeeded, ItemThrowTask.FLAG_WAIT_FOR_ITEMS) {
@Override
public boolean condition() {
if (Configs.playerCrackState != PlayerRandCracker.CrackState.MANIPULATING_ENCHANTMENTS) {
taskList._break();
return false;
}

Slot slot = PlayerRandCracker.getBestItemThrowSlot(Minecraft.getInstance().player.containerMenu.slots);
//noinspection RedundantIfStatement
if (slot == null) {
return true; // keep waiting
} else {
return false; // ready to throw an item
}
}

@Override
protected void onTick() {
}

@Override
public void onCompleted() {
PlayerRandCracker.throwItem();
scheduleDelay();
return super.condition();
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ public static boolean throwItem() {
return true;
}

public static void unthrowItem() {
seed = (seed * 0xdba6ed0471f1L + 0x25493d2c3b3cL) & MASK;
}

public static Slot getBestItemThrowSlot(List<Slot> slots) {
slots = slots.stream().filter(slot -> {
if (!slot.hasItem()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,10 @@ private SuggestionsHook() {
private static int currentSuggestionId = MAGIC_SUGGESTION_ID;
private static final Int2ObjectMap<CompletableFuture<Suggestions>> pendingSuggestions = new Int2ObjectOpenHashMap<>();

public static CompletableFuture<Void> fence() {
return request("").thenAccept(suggestions -> {});
}

public static CompletableFuture<Suggestions> request(String command) {
ClientPacketListener connection = Minecraft.getInstance().getConnection();
if (connection == null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
package net.earthcomputer.clientcommands.mixin;

import com.mojang.brigadier.StringReader;
import net.cortex.clientAddon.cracker.SeedCracker;
import net.earthcomputer.clientcommands.ClientcommandsDataQueryHandler;
import net.earthcomputer.clientcommands.Configs;
import net.earthcomputer.clientcommands.features.FishingCracker;
import net.earthcomputer.clientcommands.features.PlayerRandCracker;
import net.earthcomputer.clientcommands.features.SuggestionsHook;
import net.earthcomputer.clientcommands.task.ItemThrowTask;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl;
import net.minecraft.client.multiplayer.ClientPacketListener;
Expand Down Expand Up @@ -41,7 +41,9 @@ public void onHandleAddEntity(ClientboundAddEntityPacket packet, CallbackInfo ci
return;
}

SeedCracker.onEntityCreation(packet);
if (packet.getType() == EntityType.ITEM) {
ItemThrowTask.handleItemSpawn(packet);
}

if (FishingCracker.canManipulateFishing()) {
if (packet.getData() == player.getId() && packet.getType() == EntityType.FISHING_BOBBER) {
Expand Down
125 changes: 125 additions & 0 deletions src/main/java/net/earthcomputer/clientcommands/task/ItemThrowTask.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package net.earthcomputer.clientcommands.task;

import com.mojang.logging.LogUtils;
import net.earthcomputer.clientcommands.Configs;
import net.earthcomputer.clientcommands.features.PlayerRandCracker;
import net.earthcomputer.clientcommands.features.SuggestionsHook;
import net.minecraft.client.Minecraft;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.protocol.game.ClientboundAddEntityPacket;
import org.slf4j.Logger;

import java.lang.ref.WeakReference;
import java.util.Set;

public class ItemThrowTask extends SimpleTask {
private static final Logger LOGGER = LogUtils.getLogger();

private static final Set<Object> MUTEX_KEYS = Set.of(ItemThrowTask.class);

public static final int FLAG_URGENT = 1;
public static final int FLAG_WAIT_FOR_ITEMS = 2;

private static WeakReference<ItemThrowTask> currentThrowTask = null;

private final int totalItemsToThrow;
private final int flags;

private int confirmedItemThrows;
private int sentItemThrows;
private float itemThrowsAllowedThisTick;
private boolean waitingFence = false;
private boolean failed = false;

public ItemThrowTask(int itemsToThrow) {
this(itemsToThrow, 0);
}

public ItemThrowTask(int itemsToThrow, int flags) {
this.totalItemsToThrow = itemsToThrow;
this.flags = flags;
}

@Override
public boolean condition() {
return waitingFence || sentItemThrows != totalItemsToThrow || sentItemThrows > confirmedItemThrows;
}

@Override
protected void onTick() {
itemThrowsAllowedThisTick += Configs.itemThrowsPerTick;

while (((flags & FLAG_URGENT) != 0 || itemThrowsAllowedThisTick >= 1) && sentItemThrows < totalItemsToThrow) {
itemThrowsAllowedThisTick--;
if (!PlayerRandCracker.throwItem()) {
if ((flags & FLAG_WAIT_FOR_ITEMS) != 0) {
return;
}
failed = true;
_break();
onFailedToThrowItem();
return;
}
sentItemThrows++;
}

if (!waitingFence && sentItemThrows == totalItemsToThrow && confirmedItemThrows < sentItemThrows) {
waitingFence = true;
SuggestionsHook.fence().thenAccept(v -> {
if (sentItemThrows > confirmedItemThrows) {
LOGGER.info("Server rejected {} item throws. Rethrowing them.", sentItemThrows - confirmedItemThrows);
while (sentItemThrows > confirmedItemThrows) {
PlayerRandCracker.unthrowItem();
sentItemThrows--;
}
}
waitingFence = false;
});
}
}

@Override
public void initialize() {
currentThrowTask = new WeakReference<>(this);
}

@Override
public void onCompleted() {
if (!failed) {
onSuccess();
}
currentThrowTask = null;
}

@Override
public Set<Object> getMutexKeys() {
return MUTEX_KEYS;
}

protected void onFailedToThrowItem() {
}

protected void onSuccess() {
}

protected void onItemSpawn(ClientboundAddEntityPacket packet) {
}

public static void handleItemSpawn(ClientboundAddEntityPacket packet) {
ItemThrowTask task = currentThrowTask == null ? null : currentThrowTask.get();
if (task == null) {
return;
}

LocalPlayer player = Minecraft.getInstance().player;
if (player == null) {
return;
}
if (player.getEyePosition().distanceToSqr(packet.getX(), packet.getY(), packet.getZ()) > 1) {
return;
}

task.confirmedItemThrows++;
task.onItemSpawn(packet);
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package net.earthcomputer.clientcommands.task;

import java.util.Set;

/**
* Acts like a for loop that can delay between iterations to allow the game to continue ticking
*/
public abstract class LongTask {

boolean isInitialized = false;
private boolean delayScheduled;
private boolean broken = false;

Expand Down Expand Up @@ -42,4 +45,7 @@ public boolean stopOnLevelUnload(boolean isDisconnect) {
return true;
}

public Set<Object> getMutexKeys() {
return Set.of();
}
}
Loading

0 comments on commit e7b9ec1

Please sign in to comment.