291 lines
7.5 KiB
Java
291 lines
7.5 KiB
Java
package dev.slinky.client.placement;
|
|
|
|
import dev.slinky.client.ClientContext;
|
|
import dev.slinky.client.action.ActionAccess;
|
|
import dev.slinky.client.action.ModuleActionService;
|
|
import dev.slinky.client.inventory.InventoryActions;
|
|
import java.util.function.IntUnaryOperator;
|
|
import net.minecraft.entity.player.InventoryPlayer;
|
|
import net.minecraft.item.ItemStack;
|
|
|
|
public final class PlacementSelection {
|
|
private static int preferred;
|
|
private static boolean startAfterCurrent;
|
|
private static Object selectionOwner;
|
|
private static PlacementSelection.Inventory inventoryOwner;
|
|
private static Object restorationOwner;
|
|
private static int originalSlot;
|
|
private static int inactivity;
|
|
private static int capturedType;
|
|
private static int capturedCount;
|
|
private static int lastSlot;
|
|
private static int repetitions;
|
|
|
|
private PlacementSelection() {
|
|
}
|
|
|
|
public static synchronized void remember(int type, boolean afterCurrent) {
|
|
preferred = type;
|
|
startAfterCurrent = afterCurrent;
|
|
}
|
|
|
|
public static PlacementSelection.Inventory inventory(final InventoryPlayer player) {
|
|
return new PlacementSelection.Inventory() {
|
|
@Override
|
|
public int current() {
|
|
return player.currentItem;
|
|
}
|
|
|
|
@Override
|
|
public void current(int slot) {
|
|
player.currentItem = slot;
|
|
}
|
|
|
|
private ItemStack at(int slot) {
|
|
return player.getStackInSlot(slot);
|
|
}
|
|
|
|
@Override
|
|
public boolean stack(int slot) {
|
|
return this.at(slot) != null;
|
|
}
|
|
|
|
@Override
|
|
public boolean item(int slot) {
|
|
return this.at(slot) != null && this.at(slot).getItem() != null;
|
|
}
|
|
|
|
@Override
|
|
public int type(int slot) {
|
|
return InventoryActions.type(this.at(slot));
|
|
}
|
|
|
|
@Override
|
|
public boolean block(int slot) {
|
|
return ActionAccess.isBlock(this.at(slot));
|
|
}
|
|
|
|
@Override
|
|
public int count(int slot) {
|
|
return this.at(slot).stackSize;
|
|
}
|
|
};
|
|
}
|
|
|
|
public static synchronized void frameReset() {
|
|
if (selectionOwner != null) {
|
|
ModuleActionService.release(selectionOwner);
|
|
}
|
|
|
|
selectionOwner = null;
|
|
inactivity++;
|
|
preferred = 0;
|
|
startAfterCurrent = false;
|
|
}
|
|
|
|
public static synchronized void capture(PlacementSelection.Inventory i) {
|
|
if (capturedType == 0) {
|
|
int slot = i.current();
|
|
if (i.stack(slot) && i.block(slot)) {
|
|
capturedType = i.type(slot);
|
|
capturedCount = i.count(slot);
|
|
if (Integer.compareUnsigned(inactivity, 20) > 0 || lastSlot != slot) {
|
|
repetitions = capturedCount;
|
|
}
|
|
|
|
inactivity = 0;
|
|
lastSlot = slot;
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void capture(ClientContext c) {
|
|
if (c.ready()) {
|
|
capture(inventory(c.player().inventory));
|
|
}
|
|
}
|
|
|
|
public static synchronized void consume(PlacementSelection.Inventory i) {
|
|
if (capturedType != 0) {
|
|
int slot = i.current();
|
|
boolean depleted = !i.stack(slot) || !i.item(slot) || i.type(slot) == 0;
|
|
if (!depleted && i.count(slot) < capturedCount) {
|
|
depleted = --repetitions == 0;
|
|
}
|
|
|
|
if (depleted) {
|
|
preferred = capturedType;
|
|
startAfterCurrent = true;
|
|
}
|
|
|
|
capturedType = 0;
|
|
}
|
|
}
|
|
|
|
public static void consume(ClientContext c) {
|
|
if (c.ready()) {
|
|
consume(inventory(c.player().inventory));
|
|
}
|
|
}
|
|
|
|
public static synchronized int preferred() {
|
|
return preferred;
|
|
}
|
|
|
|
public static synchronized boolean afterCurrent() {
|
|
return startAfterCurrent;
|
|
}
|
|
|
|
public static int bridgeRank(int id) {
|
|
switch (id) {
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 35:
|
|
case 45:
|
|
return 2;
|
|
case 5:
|
|
case 17:
|
|
case 20:
|
|
case 24:
|
|
case 87:
|
|
return 1;
|
|
default:
|
|
int offset = id - 121;
|
|
return Integer.compareUnsigned(offset, 41) <= 0 && (2473901162497L >>> (offset & 63) & 1L) != 0L ? 1 : -1;
|
|
}
|
|
}
|
|
|
|
public static int blockInRank(int id) {
|
|
switch (id) {
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 20:
|
|
case 24:
|
|
case 45:
|
|
case 87:
|
|
case 159:
|
|
return 2;
|
|
case 4:
|
|
case 5:
|
|
case 17:
|
|
case 121:
|
|
case 162:
|
|
return 3;
|
|
case 35:
|
|
return 1;
|
|
case 49:
|
|
return 4;
|
|
default:
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
public static int choose(int[] ids, int current, int preferredId, boolean afterCurrent, IntUnaryOperator rank) {
|
|
int first = current + (afterCurrent ? 1 : 0);
|
|
int chosen = -1;
|
|
int best = -1;
|
|
|
|
for (int n = 0; n < 9; n++) {
|
|
int slot = (first + n) % 9;
|
|
int id = ids[slot];
|
|
if (id != 0) {
|
|
if (preferredId != 0 && id == preferredId) {
|
|
return slot;
|
|
}
|
|
|
|
int score = rank.applyAsInt(id);
|
|
if (score > best) {
|
|
best = score;
|
|
chosen = slot;
|
|
}
|
|
}
|
|
}
|
|
|
|
return chosen;
|
|
}
|
|
|
|
public static synchronized boolean select(ClientContext c, Object token, boolean force, boolean blockIn) {
|
|
return selectionOwner == null && c.ready() && (force || preferred != 0) ? select(inventory(c.player().inventory), token, force, blockIn) : false;
|
|
}
|
|
|
|
public static synchronized boolean select(PlacementSelection.Inventory inventory, Object token, boolean force, boolean blockIn) {
|
|
if (selectionOwner == null && (force || preferred != 0)) {
|
|
int[] ids = new int[9];
|
|
|
|
for (int i = 0; i < 9; i++) {
|
|
ids[i] = inventory.type(i);
|
|
}
|
|
|
|
int chosen = choose(ids, inventory.current(), preferred, startAfterCurrent, blockIn ? PlacementSelection::blockInRank : PlacementSelection::bridgeRank);
|
|
if (chosen != -1 && ModuleActionService.claim(token)) {
|
|
if (restorationOwner != token) {
|
|
originalSlot = inventory.current();
|
|
inventoryOwner = inventory;
|
|
restorationOwner = token;
|
|
}
|
|
|
|
selectionOwner = token;
|
|
inventory.current(chosen);
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static synchronized void release(Object token) {
|
|
if (restorationOwner == token) {
|
|
inventoryOwner.current(originalSlot);
|
|
restorationOwner = null;
|
|
inventoryOwner = null;
|
|
}
|
|
|
|
if (selectionOwner == token) {
|
|
selectionOwner = null;
|
|
}
|
|
|
|
ModuleActionService.release(token);
|
|
}
|
|
|
|
public static synchronized void reset() {
|
|
if (inventoryOwner != null) {
|
|
inventoryOwner.current(originalSlot);
|
|
}
|
|
|
|
if (selectionOwner != null) {
|
|
ModuleActionService.release(selectionOwner);
|
|
}
|
|
|
|
restorationOwner = null;
|
|
selectionOwner = null;
|
|
inventoryOwner = null;
|
|
preferred = 0;
|
|
startAfterCurrent = false;
|
|
repetitions = 0;
|
|
lastSlot = 0;
|
|
capturedCount = 0;
|
|
capturedType = 0;
|
|
inactivity = 0;
|
|
}
|
|
|
|
public interface Inventory {
|
|
int current();
|
|
|
|
void current(int var1);
|
|
|
|
boolean stack(int var1);
|
|
|
|
boolean item(int var1);
|
|
|
|
int type(int var1);
|
|
|
|
boolean block(int var1);
|
|
|
|
int count(int var1);
|
|
}
|
|
}
|