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();
|
IPlayerController playerController();
|
||||||
|
|
||||||
|
IBaritoneInventory inventory();
|
||||||
|
|
||||||
World world();
|
World world();
|
||||||
|
|
||||||
IWorldData worldData();
|
IWorldData worldData();
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package baritone.utils;
|
package baritone.api.utils;
|
||||||
|
|
||||||
import java.util.function.ObjIntConsumer;
|
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.Baritone;
|
||||||
import baritone.api.event.events.TickEvent;
|
import baritone.api.event.events.TickEvent;
|
||||||
import baritone.api.utils.Helper;
|
import baritone.api.utils.Helper;
|
||||||
import baritone.utils.InventorySlot;
|
import baritone.api.utils.InventorySlot;
|
||||||
|
import baritone.api.utils.Pair;
|
||||||
import baritone.utils.ToolSet;
|
import baritone.utils.ToolSet;
|
||||||
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
|
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.client.entity.EntityPlayerSP;
|
|
||||||
import net.minecraft.entity.player.EntityPlayer;
|
import net.minecraft.entity.player.EntityPlayer;
|
||||||
import net.minecraft.init.Blocks;
|
import net.minecraft.init.Blocks;
|
||||||
import net.minecraft.inventory.ClickType;
|
import net.minecraft.inventory.ClickType;
|
||||||
|
@ -36,12 +36,10 @@ import net.minecraft.world.World;
|
||||||
|
|
||||||
import javax.annotation.Nonnull;
|
import javax.annotation.Nonnull;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.OptionalInt;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.function.IntPredicate;
|
import java.util.function.IntPredicate;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public final class InventoryBehavior extends Behavior implements Helper {
|
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()) {
|
if (Baritone.settings().allowHotbarManagement.value && baritone.getPathingBehavior().isPathing()) {
|
||||||
// TODO: Some way of indicating which slots are currently reserved by this setting
|
this.setupHotbar();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastTickRequestedMove != null) {
|
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) {
|
public boolean attemptToPutOnHotbar(int inMainInvy, IntPredicate disallowedHotbar) {
|
||||||
OptionalInt destination = getTempHotbarSlot(disallowedHotbar);
|
OptionalInt destination = getTempHotbarSlot(disallowedHotbar);
|
||||||
if (destination.isPresent()) {
|
if (destination.isPresent()) {
|
||||||
|
@ -132,37 +139,22 @@ public final class InventoryBehavior extends Behavior implements Helper {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private int firstValidThrowaway() { // TODO offhand idk
|
private InventorySlot bestToolAgainst(final Block against, final Class<? extends ItemTool> cla$$) {
|
||||||
NonNullList<ItemStack> invy = ctx.player().inventory.mainInventory;
|
return this.findBestSlotMatching(
|
||||||
for (int i = 0; i < invy.size(); i++) {
|
Comparator.comparingDouble(stack -> ToolSet.calculateSpeedVsBlock(stack, against.getDefaultState())),
|
||||||
if (this.isThrowawayItem(invy.get(i))) {
|
stack -> {
|
||||||
return i;
|
if (stack.isEmpty()) {
|
||||||
}
|
return false;
|
||||||
}
|
}
|
||||||
return -1;
|
if (Baritone.settings().itemSaver.value
|
||||||
}
|
&& stack.getItemDamage() + Baritone.settings().itemSaverThreshold.value >= stack.getMaxDamage()
|
||||||
|
&& stack.getMaxDamage() > 1
|
||||||
private int bestToolAgainst(Block against, Class<? extends ItemTool> cla$$) {
|
) {
|
||||||
NonNullList<ItemStack> invy = ctx.player().inventory.mainInventory;
|
return false;
|
||||||
int bestInd = -1;
|
}
|
||||||
double bestSpeed = -1;
|
return cla$$.isInstance(stack.getItem());
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
);
|
||||||
}
|
|
||||||
return bestInd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasGenericThrowaway() {
|
public boolean hasGenericThrowaway() {
|
||||||
|
@ -250,47 +242,40 @@ public final class InventoryBehavior extends Behavior implements Helper {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public InventorySlot findSlotMatching(final Predicate<? super ItemStack> filter) {
|
||||||
* Returns an {@link InventorySlot} that contains a stack matching the given predicate. The priority of the
|
return this.findBestSlotMatching(null, filter);
|
||||||
* 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 findHotbarMatching(final Predicate<? super ItemStack> desired) {
|
/**
|
||||||
final EntityPlayerSP p = ctx.player();
|
* Returns an {@link InventorySlot} that contains a stack matching the given predicate. A comparator may be
|
||||||
final NonNullList<ItemStack> inv = p.inventory.mainInventory;
|
* specified to prioritize slot selection. The comparator may be {@code null}, in which case, the first slot
|
||||||
for (int i = 0; i < 9; i++) {
|
* matching the predicate is returned. The considered slots are in the order of hotbar, offhand, and finally the
|
||||||
ItemStack item = inv.get(i);
|
* main inventory (if {@link #canAccessInventory()} is {@code true}).
|
||||||
if (desired.test(item)) {
|
*
|
||||||
return InventorySlot.hotbar(i);
|
* @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.
|
||||||
return null;
|
*/
|
||||||
|
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() {
|
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 Baritone baritone;
|
||||||
private final Minecraft mc;
|
private final Minecraft mc;
|
||||||
private final IPlayerController playerController;
|
private final IPlayerController playerController;
|
||||||
|
private final IBaritoneInventory inventory;
|
||||||
|
|
||||||
public BaritonePlayerContext(Baritone baritone, Minecraft mc) {
|
public BaritonePlayerContext(Baritone baritone, Minecraft mc) {
|
||||||
this.baritone = baritone;
|
this.baritone = baritone;
|
||||||
this.mc = mc;
|
this.mc = mc;
|
||||||
this.playerController = new BaritonePlayerController(mc);
|
this.playerController = new BaritonePlayerController(mc);
|
||||||
|
this.inventory = new BaritoneInventory(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -60,6 +62,11 @@ public final class BaritonePlayerContext implements IPlayerContext {
|
||||||
return this.playerController;
|
return this.playerController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public IBaritoneInventory inventory() {
|
||||||
|
return this.player() == null ? null : this.inventory;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public World world() {
|
public World world() {
|
||||||
return this.mc.world;
|
return this.mc.world;
|
||||||
|
|
Loading…
Reference in New Issue