mirror of https://github.com/cabaletta/baritone
Inventory API thing and substitution of legacy code
Also stole `Pair` from elytra branch 😎
This commit is contained in:
parent
4d7eb003e6
commit
827125d827
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public interface IBaritoneInventory {
|
||||
|
||||
/**
|
||||
* Returns a stream containing all the player's regular inventory slots and items. In the order of hotbar, offhand,
|
||||
* then main inventory, for a total of 37 slots. This explicitly does not contain the armor slots or crafting grid.
|
||||
*
|
||||
* @return All the player's inventory slots and items
|
||||
*/
|
||||
Stream<Pair<InventorySlot, ItemStack>> allSlots();
|
||||
|
||||
Stream<Pair<InventorySlot, ItemStack>> hotbarSlots();
|
||||
|
||||
Stream<Pair<InventorySlot, ItemStack>> inventorySlots();
|
||||
|
||||
Pair<InventorySlot, ItemStack> offhand();
|
||||
}
|
|
@ -40,6 +40,8 @@ public interface IPlayerContext {
|
|||
|
||||
IPlayerController playerController();
|
||||
|
||||
IBaritoneInventory inventory();
|
||||
|
||||
World world();
|
||||
|
||||
IWorldData worldData();
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
package baritone.api.utils;
|
||||
|
||||
import java.util.function.ObjIntConsumer;
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public final class Pair<A, B> {
|
||||
|
||||
private final A a;
|
||||
private final B b;
|
||||
|
||||
public Pair(A a, B b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public A first() {
|
||||
return this.a;
|
||||
}
|
||||
|
||||
public B second() {
|
||||
return this.b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || o.getClass() != Pair.class) {
|
||||
return false;
|
||||
}
|
||||
Pair<?, ?> pair = (Pair<?, ?>) o;
|
||||
return Objects.equals(this.a, pair.a) && Objects.equals(this.b, pair.b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * Objects.hashCode(this.a) + Objects.hashCode(this.b);
|
||||
}
|
||||
}
|
|
@ -20,12 +20,12 @@ package baritone.behavior;
|
|||
import baritone.Baritone;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.utils.InventorySlot;
|
||||
import baritone.api.utils.InventorySlot;
|
||||
import baritone.api.utils.Pair;
|
||||
import baritone.utils.ToolSet;
|
||||
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.inventory.ClickType;
|
||||
|
@ -36,12 +36,10 @@ import net.minecraft.world.World;
|
|||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Random;
|
||||
import java.util.*;
|
||||
import java.util.function.IntPredicate;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class InventoryBehavior extends Behavior implements Helper {
|
||||
|
||||
|
@ -69,14 +67,7 @@ public final class InventoryBehavior extends Behavior implements Helper {
|
|||
}
|
||||
|
||||
if (Baritone.settings().allowHotbarManagement.value && baritone.getPathingBehavior().isPathing()) {
|
||||
// TODO: Some way of indicating which slots are currently reserved by this setting
|
||||
if (firstValidThrowaway() >= 9) { // aka there are none on the hotbar, but there are some in main inventory
|
||||
requestSwapWithHotBar(firstValidThrowaway(), 8);
|
||||
}
|
||||
int pick = bestToolAgainst(Blocks.STONE, ItemPickaxe.class);
|
||||
if (pick >= 9) {
|
||||
requestSwapWithHotBar(pick, 0);
|
||||
}
|
||||
this.setupHotbar();
|
||||
}
|
||||
|
||||
if (lastTickRequestedMove != null) {
|
||||
|
@ -85,6 +76,22 @@ public final class InventoryBehavior extends Behavior implements Helper {
|
|||
}
|
||||
}
|
||||
|
||||
private void setupHotbar() {
|
||||
// TODO: Some way of indicating which slots are currently reserved by this setting
|
||||
|
||||
final InventorySlot throwaway = this.findSlotMatching(this::isThrowawayItem);
|
||||
if (throwaway != null && throwaway.getType() == InventorySlot.Type.INVENTORY) {
|
||||
// aka there are none on the hotbar, but there are some in main inventory
|
||||
this.requestSwapWithHotBar(throwaway.getInventoryIndex(), 8);
|
||||
return;
|
||||
}
|
||||
|
||||
final InventorySlot pick = bestToolAgainst(Blocks.STONE, ItemPickaxe.class);
|
||||
if (pick != null && pick.getType() == InventorySlot.Type.INVENTORY) {
|
||||
requestSwapWithHotBar(pick.getInventoryIndex(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean attemptToPutOnHotbar(int inMainInvy, IntPredicate disallowedHotbar) {
|
||||
OptionalInt destination = getTempHotbarSlot(disallowedHotbar);
|
||||
if (destination.isPresent()) {
|
||||
|
@ -132,37 +139,22 @@ public final class InventoryBehavior extends Behavior implements Helper {
|
|||
return true;
|
||||
}
|
||||
|
||||
private int firstValidThrowaway() { // TODO offhand idk
|
||||
NonNullList<ItemStack> invy = ctx.player().inventory.mainInventory;
|
||||
for (int i = 0; i < invy.size(); i++) {
|
||||
if (this.isThrowawayItem(invy.get(i))) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int bestToolAgainst(Block against, Class<? extends ItemTool> cla$$) {
|
||||
NonNullList<ItemStack> invy = ctx.player().inventory.mainInventory;
|
||||
int bestInd = -1;
|
||||
double bestSpeed = -1;
|
||||
for (int i = 0; i < invy.size(); i++) {
|
||||
ItemStack stack = invy.get(i);
|
||||
if (stack.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (Baritone.settings().itemSaver.value && (stack.getItemDamage() + Baritone.settings().itemSaverThreshold.value) >= stack.getMaxDamage() && stack.getMaxDamage() > 1) {
|
||||
continue;
|
||||
}
|
||||
if (cla$$.isInstance(stack.getItem())) {
|
||||
double speed = ToolSet.calculateSpeedVsBlock(stack, against.getDefaultState()); // takes into account enchants
|
||||
if (speed > bestSpeed) {
|
||||
bestSpeed = speed;
|
||||
bestInd = i;
|
||||
private InventorySlot bestToolAgainst(final Block against, final Class<? extends ItemTool> cla$$) {
|
||||
return this.findBestSlotMatching(
|
||||
Comparator.comparingDouble(stack -> ToolSet.calculateSpeedVsBlock(stack, against.getDefaultState())),
|
||||
stack -> {
|
||||
if (stack.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (Baritone.settings().itemSaver.value
|
||||
&& stack.getItemDamage() + Baritone.settings().itemSaverThreshold.value >= stack.getMaxDamage()
|
||||
&& stack.getMaxDamage() > 1
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
return cla$$.isInstance(stack.getItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
return bestInd;
|
||||
);
|
||||
}
|
||||
|
||||
public boolean hasGenericThrowaway() {
|
||||
|
@ -250,47 +242,40 @@ public final class InventoryBehavior extends Behavior implements Helper {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@link InventorySlot} that contains a stack matching the given predicate. The priority of the
|
||||
* returned slot is the hotbar, offhand, and finally the main inventory, if {@link #canAccessInventory()} is
|
||||
* {@code true}. Additionally, for the hotbar and main inventory, slots with a lower index will be returned.
|
||||
*
|
||||
* @param desired The predicate to match
|
||||
* @return A matching slot, or {@code null} if none.
|
||||
*/
|
||||
public InventorySlot findSlotMatching(final Predicate<? super ItemStack> desired) {
|
||||
final InventorySlot hotbar = this.findHotbarMatching(desired);
|
||||
if (hotbar != null) {
|
||||
return hotbar;
|
||||
}
|
||||
|
||||
final EntityPlayerSP p = ctx.player();
|
||||
final NonNullList<ItemStack> inv = p.inventory.mainInventory;
|
||||
|
||||
if (desired.test(p.inventory.offHandInventory.get(0))) {
|
||||
return InventorySlot.offhand();
|
||||
}
|
||||
|
||||
if (this.canAccessInventory()) {
|
||||
for (int i = 9; i < 36; i++) {
|
||||
if (desired.test(inv.get(i))) {
|
||||
return InventorySlot.inventory(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
public InventorySlot findSlotMatching(final Predicate<? super ItemStack> filter) {
|
||||
return this.findBestSlotMatching(null, filter);
|
||||
}
|
||||
|
||||
public InventorySlot findHotbarMatching(final Predicate<? super ItemStack> desired) {
|
||||
final EntityPlayerSP p = ctx.player();
|
||||
final NonNullList<ItemStack> inv = p.inventory.mainInventory;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack item = inv.get(i);
|
||||
if (desired.test(item)) {
|
||||
return InventorySlot.hotbar(i);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
/**
|
||||
* Returns an {@link InventorySlot} that contains a stack matching the given predicate. A comparator may be
|
||||
* specified to prioritize slot selection. The comparator may be {@code null}, in which case, the first slot
|
||||
* matching the predicate is returned. The considered slots are in the order of hotbar, offhand, and finally the
|
||||
* main inventory (if {@link #canAccessInventory()} is {@code true}).
|
||||
*
|
||||
* @param comparator A comparator to find the best element, may be {@code null}
|
||||
* @param filter The predicate to match
|
||||
* @return A matching slot, or {@code null} if none.
|
||||
*/
|
||||
public InventorySlot findBestSlotMatching(final Comparator<? super ItemStack> comparator, final Predicate<? super ItemStack> filter) {
|
||||
return this.findBestMatching0(ctx.inventory().allSlots(), comparator, filter);
|
||||
}
|
||||
|
||||
public InventorySlot findHotbarMatching(final Predicate<? super ItemStack> filter) {
|
||||
return this.findBestHotbarMatching(null, filter);
|
||||
}
|
||||
|
||||
public InventorySlot findBestHotbarMatching(final Comparator<? super ItemStack> comparator, final Predicate<? super ItemStack> filter) {
|
||||
return this.findBestMatching0(ctx.inventory().hotbarSlots(), comparator, filter);
|
||||
}
|
||||
|
||||
private InventorySlot findBestMatching0(final Stream<Pair<InventorySlot, ItemStack>> slots,
|
||||
final Comparator<? super ItemStack> comparator,
|
||||
final Predicate<? super ItemStack> filter) {
|
||||
final Stream<Pair<InventorySlot, ItemStack>> filtered = slots.filter(slot -> filter.test(slot.second()));
|
||||
return (comparator != null
|
||||
? filtered.max((a, b) -> comparator.compare(a.second(), b.second()))
|
||||
: filtered.findFirst()
|
||||
).map(Pair::first).orElse(null);
|
||||
}
|
||||
|
||||
public boolean canAccessInventory() {
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils.player;
|
||||
|
||||
import baritone.api.utils.IBaritoneInventory;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import baritone.api.utils.InventorySlot;
|
||||
import baritone.api.utils.Pair;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/4/2023
|
||||
*/
|
||||
public final class BaritoneInventory implements IBaritoneInventory {
|
||||
|
||||
private final IPlayerContext ctx;
|
||||
|
||||
public BaritoneInventory(IPlayerContext ctx) {
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Pair<InventorySlot, ItemStack>> allSlots() {
|
||||
return Stream.concat(this.hotbarSlots(), Stream.concat(Stream.of(this.offhand()), this.inventorySlots()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Pair<InventorySlot, ItemStack>> hotbarSlots() {
|
||||
return IntStream.range(0, 9).mapToObj(i ->
|
||||
new Pair<>(InventorySlot.hotbar(i), ctx.player().inventory.mainInventory.get(i)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<Pair<InventorySlot, ItemStack>> inventorySlots() {
|
||||
return IntStream.range(9, 36).mapToObj(i ->
|
||||
new Pair<>(InventorySlot.inventory(i), ctx.player().inventory.mainInventory.get(i)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<InventorySlot, ItemStack> offhand() {
|
||||
return new Pair<>(InventorySlot.offhand(), ctx.player().inventory.offHandInventory.get(0));
|
||||
}
|
||||
}
|
|
@ -38,11 +38,13 @@ public final class BaritonePlayerContext implements IPlayerContext {
|
|||
private final Baritone baritone;
|
||||
private final Minecraft mc;
|
||||
private final IPlayerController playerController;
|
||||
private final IBaritoneInventory inventory;
|
||||
|
||||
public BaritonePlayerContext(Baritone baritone, Minecraft mc) {
|
||||
this.baritone = baritone;
|
||||
this.mc = mc;
|
||||
this.playerController = new BaritonePlayerController(mc);
|
||||
this.inventory = new BaritoneInventory(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -60,6 +62,11 @@ public final class BaritonePlayerContext implements IPlayerContext {
|
|||
return this.playerController;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaritoneInventory inventory() {
|
||||
return this.player() == null ? null : this.inventory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public World world() {
|
||||
return this.mc.world;
|
||||
|
|
Loading…
Reference in New Issue