Compare commits

..

22 Commits

Author SHA1 Message Date
Brady
6a6d0642be Utilize ToolSet for hotbar management's bestToolAgainst 2023-07-06 18:40:34 -07:00
Brady
dbf5058066 Move ItemInteractionHelper into its own file 2023-07-05 21:58:04 -07:00
Brady
bc18f0eabd Allow autoTool to pull tools from the inventory 2023-07-05 21:44:31 -07:00
Brady
827ce7e2a8 Modify ToolSet to accept an IPlayerContext 2023-07-05 19:39:08 -07:00
Brady
2e32c63bc2 Calculate break time based on block state 2023-07-05 18:52:53 -07:00
Brady
53651980ad Mitigate #3945 2023-07-05 11:45:04 -07:00
Brady
ec089cdeaa aha whoopsie 2023-07-05 11:24:34 -07:00
Brady
2408c9b6af Backport primitive computeIfAbsent 2023-07-05 11:14:55 -07:00
Brady
600d5e8a67 More IBaritoneInventory api methods 2023-07-05 10:13:38 -07:00
Brady
57c3e369b0 💚 appease codacy 2023-07-04 21:44:10 -07:00
Brady
827125d827 Inventory API thing and substitution of legacy code
Also stole `Pair` from elytra branch 😎
2023-07-04 21:34:57 -07:00
Brady
4d7eb003e6 Item interaction detection 2023-07-03 18:36:05 -05:00
Brady
1ef622c936 I LOVE ObjIntConsumer 2023-07-02 19:54:11 -05:00
Brady
c44701e689 Changes 2023-07-02 19:46:48 -05:00
Brady
7f27c9d85f Reorganize 2023-07-01 22:19:51 -05:00
Brady
15621ea763 Add allowHotbarManagement setting 2023-07-01 20:08:29 -05:00
Brady
4591fd7eb3 Use Reference2DoubleOpenHashMap in ToolSet 2023-07-01 17:16:51 -05:00
Brady
028405dd30 Only allow @PerformanceCritical on methods 2023-07-01 17:00:04 -05:00
Brady
2953b1cfaf Replace acceptableThrowawayItems references with isThrowawayItem method 2023-07-01 16:41:26 -05:00
Brady
b2cdd27ca2 Remove direct reference to allowInventory in BuilderProcess 2023-07-01 15:38:23 -05:00
Brady
4bf2dd6851 Some initial organization 2023-07-01 15:16:26 -05:00
Leijurv
8211ae4af5 memory leaks are joever 2023-06-29 21:59:31 -07:00
54 changed files with 792 additions and 2686 deletions

View File

@@ -42,7 +42,6 @@ import java.lang.reflect.Field;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -217,7 +216,6 @@ public class ProguardTask extends BaritoneGradleTask {
Process p = new ProcessBuilder(this.getJavaBinPathForProguard(), "-verbose").start();
String out = IOUtils.toString(p.getInputStream(), "UTF-8").split("\n")[0].split("Opened ")[1].replace("]", "");
template.add(2, "-libraryjars '" + out + "'");
template.add(3, "-libraryjars '" + Paths.get(out).resolveSibling("jce.jar") + "'");
// API config doesn't require any changes from the changes that we made to the template
Files.write(getTemporaryFile(PROGUARD_API_CONFIG), template);

View File

@@ -17,7 +17,6 @@
package baritone.api;
import baritone.api.bot.IUserManager;
import baritone.api.cache.IWorldScanner;
import baritone.api.command.ICommand;
import baritone.api.command.ICommandSystem;
@@ -109,11 +108,6 @@ public interface IBaritoneProvider {
*/
IWorldScanner getWorldScanner();
/**
* @return The {@link IUserManager} instance.
*/
IUserManager getUserManager();
/**
* Returns the {@link ICommandSystem} instance. This is not bound to a specific {@link IBaritone}
* instance because {@link ICommandSystem} itself controls global behavior for {@link ICommand}s.

View File

@@ -73,6 +73,13 @@ public final class Settings {
*/
public final Setting<Boolean> allowInventory = new Setting<>(false);
/**
* Allow Baritone to automatically put useful items (such as tools and throwaway blocks) on the hotbar while
* pathing. This can reduce delays when retrieving items due settings like {@link #ticksBetweenInventoryMoves} and
* {@link #inventoryMoveOnlyIfStationary}. Requires {@link #allowInventory}.
*/
public final Setting<Boolean> allowHotbarManagement = new Setting<>(false);
/**
* Wait this many ticks between InventoryBehavior moving inventory items
*/
@@ -622,6 +629,13 @@ public final class Settings {
*/
public final Setting<Boolean> pruneRegionsFromRAM = new Setting<>(true);
/**
* The chunk packer queue can never grow to larger than this, if it does, the oldest chunks are discarded
* <p>
* The newest chunks are kept, so that if you're moving in a straight line quickly then stop, your immediate render distance is still included
*/
public final Setting<Integer> chunkPackerQueueMaxSize = new Setting<>(2000);
/**
* Fill in blocks behind you
*/
@@ -1289,13 +1303,6 @@ public final class Settings {
*/
public final Setting<Boolean> desktopNotifications = new Setting<>(false);
/**
* Having this setting enabled keeps vanilla collision working. If disabled, bots will ignore
* collision boxes and be able to walk inside each other without issues. This should only be
* disabled when multiple bots are are needed to simultaneously use narrow tunnels.
*/
public final Setting<Boolean> botCollision = new Setting<>(true);
/**
* Desktop notification on path complete
*/

View File

@@ -1,68 +0,0 @@
/*
* 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.bot;
import baritone.api.IBaritone;
import baritone.api.utils.IPlayerContext;
import com.mojang.authlib.GameProfile;
import net.minecraft.network.NetworkManager;
import net.minecraft.util.Session;
/**
* @author Brady
* @since 10/23/2018
*/
public interface IBaritoneUser {
/**
* @return The Baritone instance
*/
IBaritone getBaritone();
/**
* Returns the player context. Equivalent to {@code getBaritone().getPlayerContext()}.
*
* @return The player context
*/
IPlayerContext getPlayerContext();
/**
* @return The network manager that is responsible for the current connection.
*/
NetworkManager getNetworkManager();
/**
* Returns the user login session. Should never be {@code null}, as this should be set when the
* user is constructed.
*
* @return This users's login session
*/
Session getSession();
/**
* Returns the game profile for the account represented by this user.
*
* @return This users's profile.
*/
GameProfile getProfile();
/**
* @return The manager that spawned this {@link IBaritoneUser}.
*/
IUserManager getManager();
}

View File

@@ -1,97 +0,0 @@
/*
* 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.bot;
import baritone.api.bot.connect.ConnectionStatus;
import baritone.api.bot.connect.IConnectionResult;
import baritone.api.event.events.TickEvent;
import com.mojang.authlib.GameProfile;
import net.minecraft.util.Session;
import net.minecraft.util.text.ITextComponent;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
/**
* @author Brady
* @since 1/17/2019
*/
public interface IUserManager {
/**
* Connects a new user with the specified {@link Session} to the current server. Returns
* a {@link IConnectionResult} describing the result of the attempted connection as well
* as a {@link IBaritoneUser} instance if it was {@link ConnectionStatus#SUCCESS}.
*
* @param session The user session
* @return The result of the attempted connection
*/
IConnectionResult connect(Session session);
/**
* Disconnects the specified {@link IBaritoneUser} from its current server. All valid users
* are automatically disconnected when the current game state becomes {@link TickEvent.Type#OUT}.
* A reason may be specified, but is more widely used in server-initiated disconnects.
*
* @param user The user to disconnect
* @param reason The reason for the disconnect, may be {@code null}
*/
void disconnect(IBaritoneUser user, ITextComponent reason);
/**
* Finds the {@link IBaritoneUser} associated with the specified {@link GameProfile}
*
* @param profile The game profile of the user
* @return The user, {@link Optional#empty()} if no match or {@code profile} is {@code null}
*/
default Optional<IBaritoneUser> getUserByProfile(GameProfile profile) {
return profile == null
? Optional.empty()
: this.getUsers().stream().filter(user -> user.getProfile().equals(profile)).findFirst();
}
/**
* Finds the {@link IBaritoneUser} associated with the specified {@link UUID}
*
* @param uuid The uuid of the user
* @return The user, {@link Optional#empty()} if no match or {@code uuid} is {@code null}
*/
default Optional<IBaritoneUser> getUserByUUID(UUID uuid) {
return uuid == null
? Optional.empty()
: this.getUsers().stream().filter(user -> user.getProfile().getId().equals(uuid)).findFirst();
}
/**
* Finds the {@link IBaritoneUser} associated with the specified username
*
* @param username The username of the user
* @return The user, {@link Optional#empty()} if no match or {@code uuid} is {@code null}
*/
default Optional<IBaritoneUser> getUserByName(String username) {
return username == null || username.isEmpty()
? Optional.empty()
: this.getUsers().stream().filter(user -> user.getProfile().getName().equalsIgnoreCase(username)).findFirst();
}
/**
* @return All of the users held by this manager
*/
List<IBaritoneUser> getUsers();
}

View File

@@ -1,50 +0,0 @@
/*
* 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.bot.connect;
/**
* @author Brady
* @since 11/6/2018
*/
public enum ConnectionStatus {
/**
* The local player is not connected to a server, therefore, there is no target server to connect to.
*/
NO_CURRENT_CONNECTION,
/**
* The IP of the targetted address to connect to could not be resolved.
*/
CANT_RESOLVE_HOST,
/**
* The port for the detected LAN server could not be resolved.
*/
CANT_RESOLVE_LAN,
/**
* The connection initialization failed.
*/
CONNECTION_FAILED,
/**
* The connection was a success
*/
SUCCESS
}

View File

@@ -1,44 +0,0 @@
/*
* 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.bot.connect;
import baritone.api.bot.IBaritoneUser;
import java.util.Optional;
/**
* @author Brady
* @since 1/17/2019
*/
public interface IConnectionResult {
/**
* @return The actual status of the connection attempt.
* @see ConnectionStatus
*/
ConnectionStatus getStatus();
/**
* Returns the user that was created in this connection this result reflects, if
* {@link #getStatus()} is {@link ConnectionStatus#SUCCESS}, otherwise it will
* return {@link Optional#empty()}.
*
* @return The user created in the connection
*/
Optional<IBaritoneUser> getUser();
}

View File

@@ -0,0 +1,47 @@
/*
* 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. The elements of the stream are 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, which may otherwise be accessed with {@link #armorSlots()} and/or {@link #itemAt}.
*
* @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();
Stream<Pair<InventorySlot, ItemStack>> armorSlots();
ItemStack itemAt(InventorySlot slot);
}

View File

@@ -17,6 +17,7 @@
package baritone.api.utils;
import baritone.api.IBaritone;
import baritone.api.cache.IWorldData;
import net.minecraft.block.BlockSlab;
import net.minecraft.client.Minecraft;
@@ -34,12 +35,16 @@ import java.util.Optional;
*/
public interface IPlayerContext {
IBaritone baritone();
Minecraft minecraft();
EntityPlayerSP player();
IPlayerController playerController();
IBaritoneInventory inventory();
World world();
IWorldData worldData();

View File

@@ -46,8 +46,6 @@ public interface IPlayerController {
ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player);
void setGameType(GameType type);
GameType getGameType();
EnumActionResult processRightClickBlock(EntityPlayerSP player, World world, BlockPos pos, EnumFacing direction, Vec3d vec, EnumHand hand);

View File

@@ -0,0 +1,129 @@
/*
* 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.function.ObjIntConsumer;
/**
* @author Brady
*/
public final class InventorySlot {
/**
* Maps directly to the slot ids of the player's inventory container.
* <table width="100%">
* <tr>
* <th width="10%">Index</th>
* <th>Description</th>
* </tr>
* <tr><td>0</td><td>crafting output</td></tr>
* <tr><td>1-4</td><td>crafting grid</td></tr>
* <tr><td>5-8</td><td>armor</td></tr>
* <tr><td>9-35</td><td>inventory (index 9-35)</td></tr>
* <tr><td>36-44</td><td>hotbar (index 0-8)</td></tr>
* <tr><td>45</td><td>off-hand</td></tr>
* </table>
*/
private static final InventorySlot[] SLOTS = new InventorySlot[46];
static {
final ObjIntConsumer<Type> populate = new ObjIntConsumer<Type>() {
private int index;
@Override
public void accept(Type type, int count) {
for (int i = 0; i < count; i++) {
SLOTS[this.index] = new InventorySlot(this.index, type);
this.index++;
}
}
};
populate.accept(Type.CRAFTING_OUTPUT, 1);
populate.accept(Type.CRAFTING_GRID, 4);
populate.accept(Type.ARMOR, 4);
populate.accept(Type.INVENTORY, 27);
populate.accept(Type.HOTBAR, 9);
populate.accept(Type.OFFHAND, 1);
}
private final int slotId;
private final Type type;
private InventorySlot(int slotId, Type type) {
this.slotId = slotId;
this.type = type;
}
/**
* @return The ID of this slot, as used by {@code ContainerPlayer}
*/
public int getSlotId() {
return this.slotId;
}
public Type getType() {
return this.type;
}
/**
* Returns the index of this slot in {@code mainInventory}. If this slot does not correspond to an index into
* {@code mainInventory}, then an {@link IllegalArgumentException} is thrown.
*
* @return The index of this slot in the player's {@code mainInventory}
* @throws IllegalArgumentException if type is not {@link Type#HOTBAR} or {@link Type#INVENTORY}
*/
public int getInventoryIndex() {
switch (this.getType()) {
case HOTBAR:
return this.slotId - 36;
case INVENTORY:
return this.slotId;
default:
throw new IllegalStateException("Slot type must be either HOTBAR or INVENTORY");
}
}
public static InventorySlot inventory(final int index) {
if (index >= 0 && index < 9) {
return SLOTS[index + 36]; // HOTBAR
} else if (index >= 9 && index < 36) {
return SLOTS[index]; // INVENTORY
}
throw new IllegalArgumentException();
}
public static InventorySlot armor(final int index) {
if (index < 0 || index >= 4) {
throw new IllegalArgumentException();
}
return SLOTS[index + 5];
}
public static InventorySlot offhand() {
return SLOTS[45];
}
public enum Type {
CRAFTING_OUTPUT,
CRAFTING_GRID,
ARMOR,
INVENTORY,
HOTBAR,
OFFHAND
}
}

View File

@@ -15,29 +15,45 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot.impl;
package baritone.api.utils;
import net.minecraft.client.particle.ParticleManager;
import net.minecraft.entity.Entity;
import net.minecraft.util.EnumParticleTypes;
import javax.annotation.Nonnull;
import java.util.Objects;
/**
* @author Brady
* @since 3/8/2020
*/
public final class BotParticleManager extends ParticleManager {
public final class Pair<A, B> {
public static final BotParticleManager INSTANCE = new BotParticleManager();
private final A a;
private final B b;
private BotParticleManager() {
super(null, null);
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 void emitParticleAtEntity(Entity entityIn, @Nonnull EnumParticleTypes particleTypes) {}
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 void emitParticleAtEntity(Entity p_191271_1_, @Nonnull EnumParticleTypes p_191271_2_, int p_191271_3_) {}
public int hashCode() {
return 31 * Objects.hashCode(this.a) + Objects.hashCode(this.b);
}
}

View File

@@ -21,7 +21,6 @@ import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.event.events.RenderEvent;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -39,13 +38,7 @@ public class MixinEntityRenderer {
)
)
private void renderWorldPass(int pass, float partialTicks, long finishTimeNano, CallbackInfo ci) {
int renderViewDimension = BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().world().provider.getDimensionType().getId();
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
World world = ibaritone.getPlayerContext().world();
if (world == null || world.provider.getDimensionType().getId() != renderViewDimension) {
continue;
}
ibaritone.getGameEventHandler().onRenderPass(new RenderEvent(partialTicks));
}
}

View File

@@ -1,43 +0,0 @@
/*
* 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.launch.mixins;
import baritone.utils.accessor.IGameSettings;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.player.EnumPlayerModelParts;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import java.util.Set;
/**
* @author Brady
* @since 3/6/2020
*/
@Mixin(GameSettings.class)
public abstract class MixinGameSettings implements IGameSettings {
@Accessor
@Override
public abstract void setSetModelParts(Set<EnumPlayerModelParts> setModelParts);
@Accessor
@Override
public abstract void setMc(Minecraft mc);
}

View File

@@ -24,7 +24,6 @@ import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.TickEvent;
import baritone.api.event.events.WorldEvent;
import baritone.api.event.events.type.EventState;
import baritone.utils.accessor.IMinecraft;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
@@ -34,9 +33,7 @@ import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.lib.Opcodes;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -44,7 +41,6 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.io.File;
import java.util.function.BiFunction;
/**
@@ -52,19 +48,13 @@ import java.util.function.BiFunction;
* @since 7/31/2018
*/
@Mixin(Minecraft.class)
public class MixinMinecraft implements IMinecraft {
public class MixinMinecraft {
@Shadow
public EntityPlayerSP player;
@Shadow
public WorldClient world;
@Shadow
@Final
@Mutable
public File gameDir;
@Inject(
method = "init",
at = @At("RETURN")
@@ -186,9 +176,4 @@ public class MixinMinecraft implements IMinecraft {
// rightClickMouse is only for the main player
BaritoneAPI.getProvider().getPrimaryBaritone().getGameEventHandler().onBlockInteract(new BlockInteractEvent(blockpos, BlockInteractEvent.Type.USE));
}
@Override
public void setGameDir(File gameDir) {
this.gameDir = gameDir;
}
}

View File

@@ -23,9 +23,7 @@ import baritone.api.IBaritone;
import baritone.api.event.events.ChunkEvent;
import baritone.api.event.events.type.EventState;
import baritone.cache.CachedChunk;
import baritone.utils.accessor.INetHandlerPlayClient;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.network.play.server.SPacketBlockChange;
import net.minecraft.network.play.server.SPacketChunkData;
@@ -33,7 +31,6 @@ import net.minecraft.network.play.server.SPacketCombatEvent;
import net.minecraft.network.play.server.SPacketMultiBlockChange;
import net.minecraft.util.math.ChunkPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -43,11 +40,7 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
* @since 8/3/2018
*/
@Mixin(NetHandlerPlayClient.class)
public abstract class MixinNetHandlerPlayClient implements INetHandlerPlayClient {
@Accessor
@Override
public abstract void setWorld(WorldClient world);
public class MixinNetHandlerPlayClient {
@Inject(
method = "handleChunkData",

View File

@@ -1,39 +0,0 @@
/*
* 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.launch.mixins;
import baritone.utils.accessor.IThreadLanServerPing;
import net.minecraft.client.multiplayer.ThreadLanServerPing;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
/**
* @author Brady
* @since 3/4/2020
*/
@Mixin(ThreadLanServerPing.class)
public abstract class MixinThreadLanServerPing implements IThreadLanServerPing {
@Accessor
@Override
public abstract String getMotd();
@Accessor
@Override
public abstract String getAddress();
}

View File

@@ -19,9 +19,7 @@
"MixinEntityLivingBase",
"MixinEntityPlayerSP",
"MixinEntityRenderer",
"MixinGameSettings",
"MixinGuiScreen",
"MixinIntegratedServer",
"MixinItemStack",
"MixinItemTool",
"MixinMinecraft",
@@ -33,7 +31,6 @@
"MixinRenderList",
"MixinStateImplementation",
"MixinTabCompleter",
"MixinThreadLanServerPing",
"MixinVboRenderList",
"MixinWorldClient"
]

View File

@@ -26,7 +26,6 @@ import baritone.api.process.IBaritoneProcess;
import baritone.api.utils.IPlayerContext;
import baritone.behavior.*;
import baritone.cache.WorldProvider;
import baritone.command.ExampleBaritoneControl;
import baritone.command.manager.CommandManager;
import baritone.event.GameEventHandler;
import baritone.process.*;
@@ -37,7 +36,6 @@ import baritone.utils.InputOverrideHandler;
import baritone.utils.PathingControlManager;
import baritone.utils.player.BaritonePlayerContext;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiScreen;
import java.io.IOException;
import java.nio.file.Files;
@@ -234,14 +232,10 @@ public class Baritone implements IBaritone {
@Override
public void openClick() {
this.showScreen(new GuiClick());
}
public void showScreen(GuiScreen screen) {
new Thread(() -> {
try {
Thread.sleep(100);
mc.addScheduledTask(() -> mc.displayGuiScreen(screen));
mc.addScheduledTask(() -> mc.displayGuiScreen(new GuiClick()));
} catch (Exception ignored) {}
}).start();
}

View File

@@ -19,11 +19,9 @@ package baritone;
import baritone.api.IBaritone;
import baritone.api.IBaritoneProvider;
import baritone.api.bot.IUserManager;
import baritone.api.cache.IWorldScanner;
import baritone.api.command.ICommandSystem;
import baritone.api.schematic.ISchematicSystem;
import baritone.bot.UserManager;
import baritone.cache.FasterWorldScanner;
import baritone.command.CommandSystem;
import baritone.command.ExampleBaritoneControl;
@@ -81,11 +79,6 @@ public final class BaritoneProvider implements IBaritoneProvider {
return FasterWorldScanner.INSTANCE;
}
@Override
public IUserManager getUserManager() {
return UserManager.INSTANCE;
}
@Override
public ICommandSystem getCommandSystem() {
return CommandSystem.INSTANCE;

View File

@@ -15,22 +15,22 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
package baritone;
import baritone.utils.accessor.IIntegratedServer;
import net.minecraft.client.multiplayer.ThreadLanServerPing;
import net.minecraft.server.integrated.IntegratedServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import baritone.pathing.movement.CalculationContext;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that should be used on methods which are performance critical (i.e. called millions of times per second
* by the pathfinder) and should be modified with care. Particularly useful for methods for which this fact is not
* obvious, such as those which don't have a {@link CalculationContext} parameter.
*
* @author Brady
* @since 3/4/2020
*/
@Mixin(IntegratedServer.class)
public abstract class MixinIntegratedServer implements IIntegratedServer {
@Accessor
@Override
public abstract ThreadLanServerPing getLanServerPing();
}
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
public @interface PerformanceCritical {}

View File

@@ -20,25 +20,29 @@ package baritone.behavior;
import baritone.Baritone;
import baritone.api.event.events.TickEvent;
import baritone.api.utils.Helper;
import baritone.api.utils.InventorySlot;
import baritone.api.utils.Pair;
import baritone.utils.ItemInteractionHelper;
import baritone.utils.ToolSet;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.*;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.OptionalInt;
import java.util.Random;
import java.util.function.IntPredicate;
import java.util.function.Predicate;
import java.util.stream.Stream;
public final class InventoryBehavior extends Behavior implements Helper {
int ticksSinceLastInventoryMove;
int[] lastTickRequestedMove; // not everything asks every tick, so remember the request while coming to a halt
private int ticksSinceLastInventoryMove;
private int[] lastTickRequestedMove; // not everything asks every tick, so remember the request while coming to a halt
public InventoryBehavior(Baritone baritone) {
super(baritone);
@@ -46,31 +50,51 @@ public final class InventoryBehavior extends Behavior implements Helper {
@Override
public void onTick(TickEvent event) {
if (!Baritone.settings().allowInventory.value) {
if (event.getType() == TickEvent.Type.OUT) {
return;
}
if (event.getType() == TickEvent.Type.OUT) {
ticksSinceLastInventoryMove++;
// TODO: Move these checks into "requestSwapWithHotBar" or whatever supersedes it
if (!this.canAccessInventory()) {
return;
}
if (ctx.player().openContainer != ctx.player().inventoryContainer) {
// we have a crafting table or a chest or something open
return;
}
ticksSinceLastInventoryMove++;
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 (Baritone.settings().allowHotbarManagement.value && baritone.getPathingBehavior().isPathing()) {
this.setupHotbar();
}
if (lastTickRequestedMove != null) {
logDebug("Remembering to move " + lastTickRequestedMove[0] + " " + lastTickRequestedMove[1] + " from a previous tick");
requestSwapWithHotBar(lastTickRequestedMove[0], lastTickRequestedMove[1]);
}
}
public boolean attemptToPutOnHotbar(int inMainInvy, Predicate<Integer> disallowedHotbar) {
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 = this.bestToolAgainst(Blocks.STONE, ItemPickaxe.class);
if (pick != null && pick.getType() == InventorySlot.Type.INVENTORY) {
this.requestSwapWithHotBar(pick.getInventoryIndex(), 0);
}
}
private InventorySlot bestToolAgainst(final Block against, final Class<? extends ItemTool> cla$$) {
return new ToolSet(ctx).getBestSlot(against.getDefaultState(), Baritone.settings().preferSilkTouch.value, stack -> cla$$.isInstance(stack.getItem()));
}
public boolean attemptToPutOnHotbar(int inMainInvy, IntPredicate disallowedHotbar) {
OptionalInt destination = getTempHotbarSlot(disallowedHotbar);
if (destination.isPresent()) {
if (!requestSwapWithHotBar(inMainInvy, destination.getAsInt())) {
@@ -80,7 +104,7 @@ public final class InventoryBehavior extends Behavior implements Helper {
return true;
}
public OptionalInt getTempHotbarSlot(Predicate<Integer> disallowedHotbar) {
public OptionalInt getTempHotbarSlot(IntPredicate disallowedHotbar) {
// we're using 0 and 8 for pickaxe and throwaway
ArrayList<Integer> candidates = new ArrayList<>();
for (int i = 1; i < 8; i++) {
@@ -117,114 +141,172 @@ 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 (Baritone.settings().acceptableThrowawayItems.value.contains(invy.get(i).getItem())) {
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;
}
}
}
return bestInd;
}
public boolean hasGenericThrowaway() {
for (Item item : Baritone.settings().acceptableThrowawayItems.value) {
if (throwaway(false, stack -> item.equals(stack.getItem()))) {
return true;
}
}
return false;
return this.canSelectItem(this::isThrowawayItem);
}
public boolean selectThrowawayForLocation(boolean select, int x, int y, int z) {
IBlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z, baritone.bsi.get0(x, y, z));
if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof ItemBlock && maybe.equals(((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(ctx.world(), ctx.playerFeet(), EnumFacing.UP, (float) ctx.player().posX, (float) ctx.player().posY, (float) ctx.player().posZ, stack.getItem().getMetadata(stack.getMetadata()), ctx.player())))) {
return true; // gotem
final Predicate<Predicate<? super ItemStack>> op = select ? this::trySelectItem : this::canSelectItem;
final IBlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z, baritone.bsi.get0(x, y, z));
if (maybe != null) {
return op.test(stack -> {
if (!(stack.getItem() instanceof ItemBlock)) {
return false;
}
Block block = ((ItemBlock) stack.getItem()).getBlock();
return maybe.equals(block.getStateForPlacement(
ctx.world(),
ctx.playerFeet(),
EnumFacing.UP,
0.5f, 1.0f, 0.5f,
stack.getItem().getMetadata(stack.getMetadata()),
ctx.player()
));
}) || op.test(stack -> {
// Since a stack didn't match the desired block state, accept a match of just the block
return stack.getItem() instanceof ItemBlock
&& ((ItemBlock) stack.getItem()).getBlock().equals(maybe.getBlock());
});
}
if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof ItemBlock && ((ItemBlock) stack.getItem()).getBlock().equals(maybe.getBlock()))) {
return op.test(this::isThrowawayItem);
}
public boolean canSelectItem(Predicate<? super ItemStack> desired) {
return this.resolveSelectionStrategy(this.findSlotMatching(desired)) != null;
}
public boolean trySelectItem(Predicate<? super ItemStack> desired) {
final SelectionStrategy strategy = this.resolveSelectionStrategy(this.findSlotMatching(desired));
if (strategy != null) {
strategy.run();
// TODO: Consider cases where returning the SelectionType is needed/useful to the caller
return true;
}
for (Item item : Baritone.settings().acceptableThrowawayItems.value) {
if (throwaway(select, stack -> item.equals(stack.getItem()))) {
return true;
}
}
return false;
}
public boolean throwaway(boolean select, Predicate<? super ItemStack> desired) {
return throwaway(select, desired, Baritone.settings().allowInventory.value);
public SelectionStrategy resolveSelectionStrategy(final InventorySlot slot) {
if (slot != null) {
switch (slot.getType()) {
case HOTBAR:
return SelectionStrategy.of(SelectionType.IMMEDIATE, () ->
ctx.player().inventory.currentItem = slot.getInventoryIndex());
case OFFHAND:
// TODO: It's probably worth adding a parameter to this method so that the caller can indicate what
// the purpose of the item is. For example, attacks are always done using the main hand, so
// just switching to a non-interacting hotbar item isn't sufficient.
final ItemStack heldItem = ctx.player().inventory.getCurrentItem();
if (!ItemInteractionHelper.couldInteract(heldItem)) {
// Don't need to do anything, the item held in the main hand doesn't have any interaction.
return SelectionStrategy.of(SelectionType.IMMEDIATE, () -> {});
}
final InventorySlot hotbar = this.findHotbarMatching(item -> !ItemInteractionHelper.couldInteract(item));
if (hotbar != null) {
return SelectionStrategy.of(SelectionType.IMMEDIATE, () ->
ctx.player().inventory.currentItem = hotbar.getInventoryIndex());
}
// TODO: Swap offhand with an unimportant item
break;
case INVENTORY:
if (this.canAccessInventory()) {
return SelectionStrategy.of(SelectionType.ENQUEUED, () -> {
// TODO: Determine if hotbar swap can be immediate, and return type accordingly
// Also don't only swap into slot 7 that's silly
requestSwapWithHotBar(slot.getInventoryIndex(), 7);
ctx.player().inventory.currentItem = 7;
});
}
break;
default:
break;
}
}
return null;
}
public boolean throwaway(boolean select, Predicate<? super ItemStack> desired, boolean allowInventory) {
EntityPlayerSP p = ctx.player();
NonNullList<ItemStack> inv = p.inventory.mainInventory;
for (int i = 0; i < 9; i++) {
ItemStack item = inv.get(i);
// this usage of settings() is okay because it's only called once during pathing
// (while creating the CalculationContext at the very beginning)
// and then it's called during execution
// since this function is never called during cost calculation, we don't need to migrate
// acceptableThrowawayItems to the CalculationContext
if (desired.test(item)) {
if (select) {
p.inventory.currentItem = i;
}
return true;
}
}
if (desired.test(p.inventory.offHandInventory.get(0))) {
// main hand takes precedence over off hand
// that means that if we have block A selected in main hand and block B in off hand, right clicking places block B
// we've already checked above ^ and the main hand can't possible have an acceptablethrowawayitem
// so we need to select in the main hand something that doesn't right click
// so not a shovel, not a hoe, not a block, etc
for (int i = 0; i < 9; i++) {
ItemStack item = inv.get(i);
if (item.isEmpty() || item.getItem() instanceof ItemPickaxe) {
if (select) {
p.inventory.currentItem = i;
}
return true;
}
}
}
public InventorySlot findBestAccessibleMatching(final Comparator<? super ItemStack> comparator,
final Predicate<? super ItemStack> filter) {
final Stream<Pair<InventorySlot, ItemStack>> accessible = this.canAccessInventory()
? ctx.inventory().allSlots()
: Stream.concat(ctx.inventory().hotbarSlots(), Stream.of(ctx.inventory().offhand()));
return this.findBestMatching0(accessible, comparator, filter);
}
if (allowInventory) {
for (int i = 9; i < 36; i++) {
if (desired.test(inv.get(i))) {
if (select) {
requestSwapWithHotBar(i, 7);
p.inventory.currentItem = 7;
}
return true;
}
}
}
public InventorySlot findSlotMatching(final Predicate<? super ItemStack> filter) {
return this.findBestSlotMatching(null, filter);
}
return false;
/**
* 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() {
return Baritone.settings().allowInventory.value;
}
public boolean isThrowawayItem(ItemStack stack) {
return this.isThrowawayItem(stack.getItem());
}
public boolean isThrowawayItem(Item item) {
return Baritone.settings().acceptableThrowawayItems.value.contains(item);
}
public interface SelectionStrategy extends Runnable {
@Override
void run();
SelectionType getType();
static SelectionStrategy of(final SelectionType type, final Runnable runnable) {
return new SelectionStrategy() {
@Override
public void run() {
runnable.run();
}
@Override
public SelectionType getType() {
return type;
}
};
}
}
public enum SelectionType {
IMMEDIATE, ENQUEUED
}
}

View File

@@ -1,107 +0,0 @@
/*
* 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.bot;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.bot.IBaritoneUser;
import baritone.api.event.events.WorldEvent;
import baritone.api.event.events.type.EventState;
import baritone.api.utils.IPlayerContext;
import baritone.bot.impl.BotMinecraft;
import baritone.bot.impl.BotWorld;
import baritone.bot.impl.BotPlayer;
import baritone.command.ExampleBaritoneControl;
import com.mojang.authlib.GameProfile;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.network.NetworkManager;
import net.minecraft.util.Session;
/**
* Implementation of {@link IBaritoneUser}
*
* @author Brady
* @since 11/6/2018
*/
public final class BaritoneUser implements IBaritoneUser {
private final BotMinecraft mc;
private final UserManager manager;
private final NetworkManager networkManager;
private final Session session;
private final Baritone baritone;
private GameProfile profile;
BaritoneUser(UserManager manager, NetworkManager networkManager, Session session, ServerData serverData) {
this.mc = BotMinecraft.allocate(this);
this.mc.setServerData(serverData);
this.manager = manager;
this.networkManager = networkManager;
this.session = session;
this.profile = session.getProfile();
this.baritone = (Baritone) BaritoneAPI.getProvider().createBaritone(this.mc);
this.baritone.registerBehavior(ExampleBaritoneControl::new);
}
public void onLoginSuccess(GameProfile profile) {
this.profile = profile;
}
public void onWorldLoad(BotWorld world, BotPlayer player, PlayerControllerMP playerController) {
this.baritone.getGameEventHandler().onWorldEvent(new WorldEvent(world, EventState.PRE));
this.mc.player = player;
this.mc.world = world;
this.mc.playerController = playerController;
this.baritone.getGameEventHandler().onWorldEvent(new WorldEvent(world, EventState.POST));
}
@Override
public IBaritone getBaritone() {
return this.baritone;
}
@Override
public IPlayerContext getPlayerContext() {
return this.baritone.getPlayerContext();
}
@Override
public NetworkManager getNetworkManager() {
return this.networkManager;
}
@Override
public Session getSession() {
return this.session;
}
@Override
public GameProfile getProfile() {
return this.profile;
}
@Override
public UserManager getManager() {
return this.manager;
}
}

View File

@@ -1,66 +0,0 @@
/*
* 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.bot;
import baritone.bot.impl.BotWorld;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.world.GameType;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldType;
/**
* @author Brady
* @since 11/7/2018
*/
public final class BotWorldProvider {
/**
* Generic world settings for a typical survival world.
*/
private static final WorldSettings GENERIC_WORLD_SETTINGS = new WorldSettings(0L, GameType.SURVIVAL, true, false, WorldType.DEFAULT);
/**
* All of the dimensions mapped to their respective worlds.
*/
private final Int2ObjectMap<BotWorld> worlds = new Int2ObjectArrayMap<>();
/**
* Gets or creates the {@link BotWorld} for the specified dimension
*
* @param dimension The dimension id
* @return The world
*/
public BotWorld getWorld(int dimension) {
return worlds.computeIfAbsent(dimension, this::createWorldForDim);
}
/**
* Creates a new {@link BotWorld} for the given dimension id.
*
* @param dimension The dimension id
* @return The new world
*/
private BotWorld createWorldForDim(int dimension) {
return new BotWorld(GENERIC_WORLD_SETTINGS, dimension);
}
public void tick() {
this.worlds.forEach((dim, world) -> world.updateEntities());
}
}

View File

@@ -1,203 +0,0 @@
/*
* 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.bot;
import baritone.api.BaritoneAPI;
import baritone.api.bot.IBaritoneUser;
import baritone.api.bot.IUserManager;
import baritone.api.bot.connect.IConnectionResult;
import baritone.api.event.events.TickEvent;
import baritone.api.event.events.type.EventState;
import baritone.api.event.listener.AbstractGameEventListener;
import baritone.api.utils.Helper;
import baritone.api.utils.IPlayerContext;
import baritone.bot.connect.ConnectionResult;
import baritone.bot.handler.BotNetHandlerLoginClient;
import baritone.bot.impl.BotPlayer;
import baritone.bot.impl.BotWorld;
import baritone.utils.accessor.IIntegratedServer;
import baritone.utils.accessor.IThreadLanServerPing;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ServerAddress;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.handshake.client.C00Handshake;
import net.minecraft.network.login.client.CPacketLoginStart;
import net.minecraft.util.Session;
import net.minecraft.util.text.ITextComponent;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import static baritone.api.bot.connect.ConnectionStatus.*;
/**
* @author Brady
* @since 11/6/2018
*/
public enum UserManager implements IUserManager, AbstractGameEventListener {
INSTANCE;
private static final Minecraft mc = Minecraft.getMinecraft();
private final List<IBaritoneUser> users;
private final BotWorldProvider worldProvider;
UserManager() {
BaritoneAPI.getProvider().getPrimaryBaritone().getGameEventHandler().registerEventListener(this);
this.users = new CopyOnWriteArrayList<>();
this.worldProvider = new BotWorldProvider();
}
@Override
public void onTick(TickEvent event) {
if (event.getState() != EventState.PRE) {
return;
}
this.users.forEach(user -> {
switch (event.getType()) {
case IN: {
final IPlayerContext ctx = user.getPlayerContext();
if (ctx.player() != null) {
ctx.playerController().syncHeldItem();
}
if (user.getNetworkManager().isChannelOpen()) {
user.getNetworkManager().processReceivedPackets();
} else {
user.getNetworkManager().handleDisconnection();
}
break;
}
case OUT: {
this.disconnect(user, null);
break;
}
}
});
this.worldProvider.tick();
}
/**
* Connects a new user with the specified {@link Session} to the current server.
*
* @param session The user session
* @return The result of the attempted connection
*/
@Override
public final IConnectionResult connect(Session session) {
if (mc.getIntegratedServer() != null && mc.getIntegratedServer().getPublic()) {
try {
IIntegratedServer integratedServer = (IIntegratedServer) mc.getIntegratedServer();
IThreadLanServerPing lanServerPing = (IThreadLanServerPing) integratedServer.getLanServerPing();
int port = Integer.parseInt(lanServerPing.getAddress());
return connect0(session, new ServerData(lanServerPing.getMotd(), "localhost:" + port, true));
} catch (Exception e) {
e.printStackTrace();
return ConnectionResult.failed(CANT_RESOLVE_LAN);
}
}
ServerData data = mc.getCurrentServerData();
if (data == null) {
return ConnectionResult.failed(NO_CURRENT_CONNECTION);
}
// Connect to the server from the parsed server data
return connect0(session, data);
}
/**
* Connects a new user with the specified {@link Session} to the specified server.
* <p>
* Hi Mickey :)
*
* @param session The user session
* @param data The address of the server to connect to
* @return The result of the attempted connection
*/
private IConnectionResult connect0(Session session, ServerData data) {
ServerAddress address = ServerAddress.fromString(data.serverIP);
InetAddress inetAddress;
try {
inetAddress = InetAddress.getByName(address.getIP());
} catch (UnknownHostException e) {
return ConnectionResult.failed(CANT_RESOLVE_HOST);
}
try {
// Initialize Connection
NetworkManager networkManager = NetworkManager.createNetworkManagerAndConnect(
inetAddress,
address.getPort(),
mc.gameSettings.isUsingNativeTransport()
);
// Create User
BaritoneUser user = new BaritoneUser(this, networkManager, session, data);
this.users.add(user);
// Setup login handler and send connection packets
networkManager.setNetHandler(new BotNetHandlerLoginClient(networkManager, user));
networkManager.sendPacket(new C00Handshake(address.getIP(), address.getPort(), EnumConnectionState.LOGIN));
networkManager.sendPacket(new CPacketLoginStart(session.getProfile()));
return ConnectionResult.success(user);
} catch (Exception e) {
e.printStackTrace();
return ConnectionResult.failed(CONNECTION_FAILED);
}
}
/**
* @return The bot world provider
*/
public final BotWorldProvider getWorldProvider() {
return this.worldProvider;
}
@Override
public final void disconnect(IBaritoneUser user, ITextComponent reason) {
if (this.users.contains(user)) {
if (user.getNetworkManager().isChannelOpen()) {
user.getNetworkManager().closeChannel(reason);
}
BaritoneAPI.getProvider().destroyBaritone(user.getBaritone());
this.users.remove(user);
Helper.HELPER.logDirect(user.getSession().getUsername() + " Disconnected: " +
(reason == null ? "Unknown" : reason.getUnformattedText()));
final IPlayerContext ctx = user.getPlayerContext();
if (ctx.player() != null && ctx.world() != null) {
((BotWorld) ctx.world()).handleWorldRemove((BotPlayer) ctx.player());
}
}
}
@Override
public final List<IBaritoneUser> getUsers() {
return Collections.unmodifiableList(this.users);
}
}

View File

@@ -1,95 +0,0 @@
/*
* 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.bot.connect;
import baritone.api.bot.IBaritoneUser;
import baritone.api.bot.connect.ConnectionStatus;
import baritone.api.bot.connect.IConnectionResult;
import java.util.Objects;
import java.util.Optional;
import static baritone.api.bot.connect.ConnectionStatus.SUCCESS;
/**
* @author Brady
* @since 11/6/2018
*/
public final class ConnectionResult implements IConnectionResult {
/**
* The result status
*/
private final ConnectionStatus status;
/**
* The user created, if the status is {@link ConnectionStatus#SUCCESS}
*/
private final IBaritoneUser user;
private ConnectionResult(ConnectionStatus status, IBaritoneUser user) {
this.status = status;
this.user = user;
}
@Override
public ConnectionStatus getStatus() {
return this.status;
}
@Override
public Optional<IBaritoneUser> getUser() {
return Optional.ofNullable(user);
}
/**
* Creates a new failed {@link ConnectionResult}.
*
* @param status The failed connection status
* @return The connection result
* @throws IllegalArgumentException if {@code status} is {@link ConnectionStatus#SUCCESS}
*/
public static ConnectionResult failed(ConnectionStatus status) {
if (status == SUCCESS) {
throw new IllegalArgumentException("Status must be a failure type");
}
return new ConnectionResult(status, null);
}
/**
* Creates a new success {@link ConnectionResult}.
*
* @param user The user created
* @return The connection result
* @throws IllegalArgumentException if {@code user} is {@code null}
*/
public static ConnectionResult success(IBaritoneUser user) {
Objects.requireNonNull(user);
return new ConnectionResult(SUCCESS, user);
}
@Override
public String toString() {
return "ConnectionResult{" +
"status=" + status +
", user=" + user +
'}';
}
}

View File

@@ -1,72 +0,0 @@
/*
* 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.bot.handler;
import baritone.bot.BaritoneUser;
import baritone.bot.impl.BotMinecraft;
import net.minecraft.client.Minecraft;
import net.minecraft.client.network.NetHandlerLoginClient;
import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.login.server.SPacketLoginSuccess;
import net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
/**
* Handles the login stage when connecting to a server.
*
* @author Brady
* @since 10/29/2018
*/
public final class BotNetHandlerLoginClient extends NetHandlerLoginClient {
/**
* The {@link NetworkManager} that is managing the connection with the server.
*/
private final NetworkManager networkManager;
/**
* The {@link Minecraft} game instance
*/
private final BotMinecraft mc;
/**
* The bot of this connection
*/
private final BaritoneUser user;
public BotNetHandlerLoginClient(NetworkManager networkManager, BaritoneUser user) {
super(networkManager, user.getPlayerContext().minecraft(), null);
this.networkManager = networkManager;
this.mc = (BotMinecraft) user.getPlayerContext().minecraft();
this.user = user;
}
@Override
public void handleLoginSuccess(SPacketLoginSuccess packetIn) {
this.networkManager.setConnectionState(EnumConnectionState.PLAY);
this.networkManager.setNetHandler(new BotNetHandlerPlayClient(this.networkManager, this.user, this.mc, packetIn.getProfile()));
}
@Override
public void onDisconnect(@Nonnull ITextComponent reason) {
// It's important that we don't call the superclass method because that would mess up GUIs and make us upset
this.user.getManager().disconnect(this.user, reason);
}
}

View File

@@ -1,521 +0,0 @@
/*
* 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.bot.handler;
import baritone.api.utils.Helper;
import baritone.bot.BaritoneUser;
import baritone.bot.impl.BotPlayer;
import baritone.bot.impl.BotMinecraft;
import baritone.bot.impl.BotWorld;
import baritone.utils.accessor.INetHandlerPlayClient;
import com.mojang.authlib.GameProfile;
import io.netty.buffer.Unpooled;
import net.minecraft.client.multiplayer.ClientAdvancementManager;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.util.RecipeBookClient;
import net.minecraft.entity.Entity;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.PacketThreadUtil;
import net.minecraft.network.play.client.CPacketClientStatus;
import net.minecraft.network.play.client.CPacketCustomPayload;
import net.minecraft.network.play.client.CPacketResourcePackStatus;
import net.minecraft.network.play.server.*;
import net.minecraft.stats.StatisticsManager;
import net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
// Notes
// - Make some sort of system that prevents repetition of entity info updating
// - For some packets, such as ones that modify position, we can check if the existing server state matches the packet proposed state
// - For other things, we'll actually need the system
/**
* @author Brady
* @since 10/22/2018
*/
public final class BotNetHandlerPlayClient extends NetHandlerPlayClient {
/**
* The {@link NetworkManager} that is managing the connection with the server.
*/
private final NetworkManager networkManager;
/**
* The bot's minecraft game instance
*/
private final BotMinecraft client;
/**
* The bot of this connection
*/
private final BaritoneUser user;
/**
* The bot player
*/
private BotPlayer player;
/**
* The current world.
*/
private BotWorld world;
/**
* The current player controller
*/
private PlayerControllerMP playerController;
BotNetHandlerPlayClient(NetworkManager networkManager, BaritoneUser user, BotMinecraft client, GameProfile profile) {
// noinspection ConstantConditions
super(client, null, networkManager, profile);
this.networkManager = networkManager;
this.client = client;
this.user = user;
// Notify the user that we're ingame
this.user.onLoginSuccess(profile);
}
@Override
public void handleSpawnObject(@Nonnull SPacketSpawnObject packetIn) {
super.handleSpawnObject(packetIn);
}
@Override
public void handleSpawnExperienceOrb(@Nonnull SPacketSpawnExperienceOrb packetIn) {
super.handleSpawnExperienceOrb(packetIn);
}
@Override
public void handleSpawnGlobalEntity(@Nonnull SPacketSpawnGlobalEntity packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (this.world != null) {
if (this.world.weatherEffects.stream().noneMatch(entity -> entity.getEntityId() == packetIn.getEntityId())) {
super.handleSpawnGlobalEntity(packetIn);
}
}
}
@Override
public void handleSpawnMob(@Nonnull SPacketSpawnMob packetIn) {}
@Override
public void handleScoreboardObjective(@Nonnull SPacketScoreboardObjective packetIn) {}
@Override
public void handleSpawnPainting(@Nonnull SPacketSpawnPainting packetIn) {}
@Override
public void handleSpawnPlayer(@Nonnull SPacketSpawnPlayer packetIn) {}
@Override
public void handleAnimation(@Nonnull SPacketAnimation packetIn) {
super.handleAnimation(packetIn);
}
@Override
public void handleStatistics(@Nonnull SPacketStatistics packetIn) {
super.handleStatistics(packetIn);
}
@Override
public void handleRecipeBook(@Nonnull SPacketRecipeBook packetIn) {}
@Override
public void handleBlockBreakAnim(@Nonnull SPacketBlockBreakAnim packetIn) {
super.handleBlockBreakAnim(packetIn);
}
@Override
public void handleSignEditorOpen(@Nonnull SPacketSignEditorOpen packetIn) {}
@Override
public void handleUpdateTileEntity(@Nonnull SPacketUpdateTileEntity packetIn) {}
@Override
public void handleBlockAction(@Nonnull SPacketBlockAction packetIn) {}
@Override
public void handleBlockChange(@Nonnull SPacketBlockChange packetIn) {
super.handleBlockChange(packetIn);
}
@Override
public void handleChat(@Nonnull SPacketChat packetIn) {}
@Override
public void handleTabComplete(@Nonnull SPacketTabComplete packetIn) {}
@Override
public void handleMultiBlockChange(@Nonnull SPacketMultiBlockChange packetIn) {
super.handleMultiBlockChange(packetIn);
}
@Override
public void handleMaps(@Nonnull SPacketMaps packetIn) {}
@Override
public void handleConfirmTransaction(@Nonnull SPacketConfirmTransaction packetIn) {
super.handleConfirmTransaction(packetIn);
}
@Override
public void handleCloseWindow(@Nonnull SPacketCloseWindow packetIn) {
super.handleCloseWindow(packetIn);
}
@Override
public void handleWindowItems(@Nonnull SPacketWindowItems packetIn) {
super.handleWindowItems(packetIn);
}
@Override
public void handleOpenWindow(@Nonnull SPacketOpenWindow packetIn) {}
@Override
public void handleWindowProperty(@Nonnull SPacketWindowProperty packetIn) {
super.handleWindowProperty(packetIn);
}
@Override
public void handleSetSlot(@Nonnull SPacketSetSlot packetIn) {
super.handleSetSlot(packetIn);
}
@Override
public void handleCustomPayload(@Nonnull SPacketCustomPayload packetIn) {}
@Override
public void handleDisconnect(@Nonnull SPacketDisconnect packetIn) {
super.handleDisconnect(packetIn);
}
@Override
public void handleUseBed(@Nonnull SPacketUseBed packetIn) {}
@Override
public void handleEntityStatus(@Nonnull SPacketEntityStatus packetIn) {
super.handleEntityStatus(packetIn);
}
@Override
public void handleEntityAttach(@Nonnull SPacketEntityAttach packetIn) {
super.handleEntityAttach(packetIn);
}
@Override
public void handleSetPassengers(@Nonnull SPacketSetPassengers packetIn) {}
@Override
public void handleExplosion(@Nonnull SPacketExplosion packetIn) {
super.handleExplosion(packetIn);
}
@Override
public void handleChangeGameState(@Nonnull SPacketChangeGameState packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (packetIn.getGameState() == 4) {
this.client.player.connection.sendPacket(new CPacketClientStatus(CPacketClientStatus.State.PERFORM_RESPAWN));
} else if (packetIn.getGameState() != 5) {
super.handleChangeGameState(packetIn);
}
}
@Override
public void handleKeepAlive(@Nonnull SPacketKeepAlive packetIn) {
super.handleKeepAlive(packetIn);
}
@Override
public void handleChunkData(@Nonnull SPacketChunkData packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (packetIn.isFullChunk()) {
if (!this.world.handlePreChunk(this.player, packetIn.getChunkX(), packetIn.getChunkZ(), true)) {
return;
}
}
super.handleChunkData(packetIn);
}
@Override
public void processChunkUnload(@Nonnull SPacketUnloadChunk packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (this.world.handlePreChunk(this.player, packetIn.getX(), packetIn.getZ(), false)) {
super.processChunkUnload(packetIn);
}
}
@Override
public void handleEffect(@Nonnull SPacketEffect packetIn) {}
@Override
public void handleJoinGame(@Nonnull SPacketJoinGame packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.playerController = new PlayerControllerMP(this.user.getPlayerContext().minecraft(), this);
this.world = this.user.getManager().getWorldProvider().getWorld(packetIn.getDimension());
((INetHandlerPlayClient) (Object) this).setWorld(this.world);
this.player = new BotPlayer(this.user, this.client, this.world, this, new StatisticsManager(), new RecipeBookClient());
this.user.onWorldLoad(this.world, this.player, this.playerController);
this.player.preparePlayerToSpawn();
this.player.setEntityId(packetIn.getPlayerId());
this.player.dimension = packetIn.getDimension();
this.world.addEntityToWorld(packetIn.getPlayerId(), this.player);
this.playerController.setGameType(packetIn.getGameType());
packetIn.getGameType().configurePlayerCapabilities(this.player.capabilities);
this.client.gameSettings.sendSettingsToServer();
this.networkManager.sendPacket(new CPacketCustomPayload("MC|Brand", new PacketBuffer(Unpooled.buffer()).writeString("vanilla")));
Helper.HELPER.logDirect("Initialized Player and World");
}
@Override
public void handleEntityMovement(@Nonnull SPacketEntity packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity e = packetIn.getEntity(this.world);
if (e instanceof BotPlayer && !e.equals(this.player)) {
return;
}
super.handleEntityMovement(packetIn);
}
@Override
public void handlePlayerPosLook(@Nonnull SPacketPlayerPosLook packetIn) {
super.handlePlayerPosLook(packetIn);
}
@Override
public void handleParticles(@Nonnull SPacketParticles packetIn) {}
@Override
public void handlePlayerAbilities(@Nonnull SPacketPlayerAbilities packetIn) {
super.handlePlayerAbilities(packetIn);
}
@Override
public void handlePlayerListItem(@Nonnull SPacketPlayerListItem packetIn) {
super.handlePlayerListItem(packetIn);
}
@Override
public void handleDestroyEntities(@Nonnull SPacketDestroyEntities packetIn) {
super.handleDestroyEntities(packetIn);
}
@Override
public void handleRemoveEntityEffect(@Nonnull SPacketRemoveEntityEffect packetIn) {
super.handleRemoveEntityEffect(packetIn);
}
@Override
public void handleRespawn(@Nonnull SPacketRespawn packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (packetIn.getDimensionID() != this.player.dimension) {
this.world.handleWorldRemove(this.player);
this.world = this.user.getManager().getWorldProvider().getWorld(packetIn.getDimensionID());
((INetHandlerPlayClient) (Object) this).setWorld(this.world);
}
BotPlayer prev = this.player;
this.player = new BotPlayer(this.user, this.client, this.world, this, prev.getStatFileWriter(), prev.getRecipeBook());
this.user.onWorldLoad(this.world, this.player, this.playerController);
// noinspection ConstantConditions
this.player.getDataManager().setEntryValues(prev.getDataManager().getAll());
this.player.preparePlayerToSpawn();
this.player.setEntityId(prev.getEntityId());
this.player.dimension = packetIn.getDimensionID();
this.player.setServerBrand(prev.getServerBrand());
this.world.addEntityToWorld(prev.getEntityId(), this.player);
this.playerController.setGameType(packetIn.getGameType());
}
@Override
public void handleEntityHeadLook(@Nonnull SPacketEntityHeadLook packetIn) {}
@Override
public void handleHeldItemChange(@Nonnull SPacketHeldItemChange packetIn) {
super.handleHeldItemChange(packetIn);
}
@Override
public void handleDisplayObjective(@Nonnull SPacketDisplayObjective packetIn) {}
@Override
public void handleEntityMetadata(@Nonnull SPacketEntityMetadata packetIn) {
super.handleEntityMetadata(packetIn);
}
@Override
public void handleEntityVelocity(@Nonnull SPacketEntityVelocity packetIn) {
super.handleEntityVelocity(packetIn);
}
@Override
public void handleEntityEquipment(@Nonnull SPacketEntityEquipment packetIn) {
super.handleEntityEquipment(packetIn);
}
@Override
public void handleSetExperience(@Nonnull SPacketSetExperience packetIn) {
super.handleSetExperience(packetIn);
}
@Override
public void handleUpdateHealth(@Nonnull SPacketUpdateHealth packetIn) {
super.handleUpdateHealth(packetIn);
}
@Override
public void handleTeams(@Nonnull SPacketTeams packetIn) {}
@Override
public void handleUpdateScore(@Nonnull SPacketUpdateScore packetIn) {}
@Override
public void handleSpawnPosition(@Nonnull SPacketSpawnPosition packetIn) { /* We probably don't need to know this, the server handles everything related to spawn psoition? */ }
@Override
public void handleTimeUpdate(@Nonnull SPacketTimeUpdate packetIn) {
super.handleTimeUpdate(packetIn);
}
@Override
public void handleSoundEffect(@Nonnull SPacketSoundEffect packetIn) {}
@Override
public void handleCustomSound(@Nonnull SPacketCustomSound packetIn) {}
@Override
public void handleCollectItem(@Nonnull SPacketCollectItem packetIn) {
super.handleCollectItem(packetIn);
}
@Override
public void handleEntityTeleport(@Nonnull SPacketEntityTeleport packetIn) {
super.handleEntityTeleport(packetIn);
}
@Override
public void handleEntityProperties(@Nonnull SPacketEntityProperties packetIn) {
super.handleEntityProperties(packetIn);
}
@Override
public void handleEntityEffect(@Nonnull SPacketEntityEffect packetIn) {
super.handleEntityEffect(packetIn);
}
@Override
public void handleCombatEvent(@Nonnull SPacketCombatEvent packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
// We only care if we died
if (packetIn.eventType == SPacketCombatEvent.Event.ENTITY_DIED) {
if (packetIn.playerId == this.player.getEntityId()) {
// Perform an instantaneous respawn
this.networkManager.sendPacket(new CPacketClientStatus(CPacketClientStatus.State.PERFORM_RESPAWN));
user.getBaritone().getGameEventHandler().onPlayerDeath();
}
}
}
@Override
public void handleServerDifficulty(@Nonnull SPacketServerDifficulty packetIn) {}
@Override
public void handleCamera(SPacketCamera packetIn) {}
@Override
public void handleWorldBorder(@Nonnull SPacketWorldBorder packetIn) {
super.handleWorldBorder(packetIn);
}
@Override
public void handleTitle(@Nonnull SPacketTitle packetIn) {}
@Override
public void handlePlayerListHeaderFooter(@Nonnull SPacketPlayerListHeaderFooter packetIn) {}
@Override
public void handleResourcePack(@Nonnull SPacketResourcePackSend packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
// Lie to the server and tell them we accepted it in response
this.networkManager.sendPacket(new CPacketResourcePackStatus(CPacketResourcePackStatus.Action.ACCEPTED));
this.networkManager.sendPacket(new CPacketResourcePackStatus(CPacketResourcePackStatus.Action.SUCCESSFULLY_LOADED));
}
@Override
public void handleUpdateBossInfo(@Nonnull SPacketUpdateBossInfo packetIn) {}
@Override
public void handleCooldown(@Nonnull SPacketCooldown packetIn) {
super.handleCooldown(packetIn);
}
@Override
public void handleMoveVehicle(@Nonnull SPacketMoveVehicle packetIn) {
super.handleMoveVehicle(packetIn);
}
@Override
public void handleAdvancementInfo(@Nonnull SPacketAdvancementInfo packetIn) {
super.handleAdvancementInfo(packetIn);
}
@Override
public void handleSelectAdvancementsTab(@Nonnull SPacketSelectAdvancementsTab packetIn) {
super.handleSelectAdvancementsTab(packetIn);
}
@Override
public void func_194307_a(@Nonnull SPacketPlaceGhostRecipe p_194307_1_) {}
@Override
public void onDisconnect(@Nonnull ITextComponent reason) {
// TODO Maybe more world unloading
this.world.removeEntity(this.player);
this.user.getManager().disconnect(this.user, reason);
}
@Nonnull
@Override
public ClientAdvancementManager getAdvancementManager() {
throw new UnsupportedOperationException("This method shouldn't have been called; That is unepic!");
}
public BotPlayer player() {
return player;
}
public BotWorld world() {
return world;
}
}

View File

@@ -1,53 +0,0 @@
/*
* 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.bot.impl;
import baritone.api.bot.IBaritoneUser;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.inventory.GuiInventory;
import javax.annotation.Nonnull;
/**
* @author Brady
*/
public final class BotGuiInventory extends GuiInventory {
private final IBaritoneUser user;
public BotGuiInventory(IBaritoneUser user) {
super(user.getPlayerContext().player());
this.user = user;
}
@Override
public void setWorldAndResolution(@Nonnull Minecraft primary, int width, int height) {
final Minecraft mc = this.user.getPlayerContext().minecraft();
mc.displayWidth = primary.displayWidth;
mc.displayHeight = primary.displayHeight;
super.setWorldAndResolution(mc, width, height);
}
@Override
protected void drawGuiContainerBackgroundLayer(float partialTicks, int mouseX, int mouseY) {
final BotPlayer player = (BotPlayer) this.user.getPlayerContext().player();
player.isUser = false;
super.drawGuiContainerBackgroundLayer(partialTicks, mouseX, mouseY);
player.isUser = true;
}
}

View File

@@ -1,187 +0,0 @@
/*
* 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.bot.impl;
import baritone.api.bot.IBaritoneUser;
import baritone.utils.ObjectAllocator;
import baritone.utils.accessor.IGameSettings;
import baritone.utils.accessor.IMinecraft;
import com.google.common.util.concurrent.ListenableFuture;
import com.mojang.authlib.minecraft.MinecraftSessionService;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.SoundHandler;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.gui.toasts.GuiToast;
import net.minecraft.client.main.GameConfiguration;
import net.minecraft.client.renderer.RenderItem;
import net.minecraft.client.renderer.entity.RenderManager;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.client.tutorial.Tutorial;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.EnumHandSide;
import net.minecraft.util.Session;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashSet;
import java.util.concurrent.Callable;
/**
* "Implementation" of {@link Minecraft} which gets allocated without receiving a constructor call.
* This allows us to avoid the game's setup process (moreso in versions after 1.12 than 1.12 itself).
*
* @author Brady
* @since 3/3/2020
*/
public final class BotMinecraft extends Minecraft {
private static final Minecraft mc = Minecraft.getMinecraft();
private IBaritoneUser user;
private Tutorial tutorial;
private GuiToast toastGui;
private BotMinecraft(GameConfiguration gameConfig) {
super(gameConfig);
}
@Nullable
@Override
public Entity getRenderViewEntity() {
return mc.getRenderViewEntity();
}
@Nonnull
@Override
public Session getSession() {
return this.user.getSession();
}
@Override
public @Nonnull MinecraftSessionService getSessionService() {
return mc.getSessionService();
}
@Override
public <V> @Nonnull ListenableFuture<V> addScheduledTask(@Nonnull Callable<V> callableToSchedule) {
return mc.addScheduledTask(callableToSchedule);
}
@Override
public boolean isCallingFromMinecraftThread() {
return mc.isCallingFromMinecraftThread();
}
@Nonnull
@Override
public Tutorial getTutorial() {
return this.tutorial;
}
@Nonnull
@Override
public SoundHandler getSoundHandler() {
return BotSoundHandler.INSTANCE;
}
@Nonnull
@Override
public GuiToast getToastGui() {
return this.toastGui;
}
@Override
public void displayGuiScreen(@Nullable GuiScreen guiScreenIn) {
// do nothing
if (guiScreenIn == null) {
if (mc.currentScreen instanceof BotGuiInventory) {
mc.displayGuiScreen(null);
}
}
}
@Nonnull
@Override
public TextureManager getTextureManager() {
return mc.getTextureManager();
}
@Nonnull
@Override
public RenderItem getRenderItem() {
return mc.getRenderItem();
}
@Nonnull
@Override
public TextureMap getTextureMapBlocks() {
return mc.getTextureMapBlocks();
}
@Override
public void dispatchKeypresses() {
// Do nothing
}
public static BotMinecraft allocate(IBaritoneUser user) {
BotMinecraft bm = ObjectAllocator.allocate(BotMinecraft.class);
((IMinecraft) (Object) bm).setGameDir(mc.gameDir);
// Gui Compatibility
bm.fontRenderer = mc.fontRenderer;
bm.user = user;
bm.tutorial = new Tutorial(bm);
bm.gameSettings = createGameSettings(bm);
bm.effectRenderer = BotParticleManager.INSTANCE;
bm.toastGui = new GuiToast(bm);
return bm;
}
private static GameSettings createGameSettings(BotMinecraft bm) {
GameSettings settings = ObjectAllocator.allocate(GameSettings.class);
// Settings that get accessed on entity tick
settings.keyBindSprint = ObjectAllocator.allocate(KeyBinding.class);
settings.autoJump = false;
// Settings that are sent to the server
settings.language = "en_us";
settings.renderDistanceChunks = 8;
settings.chatVisibility = EntityPlayer.EnumChatVisibility.FULL;
settings.chatColours = true;
settings.mainHand = EnumHandSide.RIGHT;
// Gui Compatibility
settings.keyBindPickBlock = mc.gameSettings.keyBindPickBlock;
settings.keyBindsHotbar = mc.gameSettings.keyBindsHotbar;
settings.keyBindInventory = mc.gameSettings.keyBindInventory;
settings.keyBindDrop = mc.gameSettings.keyBindDrop;
// Private fields that must be initialized
IGameSettings accessor = (IGameSettings) settings;
accessor.setMc(bm);
accessor.setSetModelParts(new HashSet<>());
return settings;
}
}

View File

@@ -1,187 +0,0 @@
/*
* 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.bot.impl;
import baritone.Baritone;
import baritone.api.bot.IBaritoneUser;
import baritone.utils.PlayerMovementInput;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.network.NetworkPlayerInfo;
import net.minecraft.entity.Entity;
import net.minecraft.entity.IMerchant;
import net.minecraft.entity.passive.AbstractHorse;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.stats.RecipeBook;
import net.minecraft.stats.StatisticsManager;
import net.minecraft.tileentity.CommandBlockBaseLogic;
import net.minecraft.tileentity.TileEntityCommandBlock;
import net.minecraft.tileentity.TileEntitySign;
import net.minecraft.tileentity.TileEntityStructure;
import net.minecraft.util.EnumHand;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.GameType;
import net.minecraft.world.IInteractionObject;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
// Some Notes:
// - Inventory handling!
// - If chest deposit gets added it will be most useful for bot-system
/**
* @author Brady
* @since 10/23/2018
*/
@SuppressWarnings("EntityConstructor")
public final class BotPlayer extends EntityPlayerSP {
private final IBaritoneUser user;
private NetworkPlayerInfo playerInfo;
public boolean isUser;
public BotPlayer(IBaritoneUser user, Minecraft mc, World world, NetHandlerPlayClient netHandlerPlayClient, StatisticsManager statisticsManager, RecipeBook recipeBook) {
super(mc, world, netHandlerPlayClient, statisticsManager, recipeBook);
this.user = user;
this.movementInput = new PlayerMovementInput(this.user.getBaritone().getInputOverrideHandler());
this.isUser = true;
}
@Override
public void onUpdate() {
this.entityCollisionReduction = Baritone.settings().botCollision.value ? 0.0F : 1.0F;
super.onUpdate();
}
@Override
public boolean isUser() {
// Used by BotGuiInventory to fix player model rendering in the gui
return this.isUser;
}
@Override
public double getDistanceSq(@Nonnull Entity entityIn) {
if (entityIn == Minecraft.getMinecraft().getRenderViewEntity()) {
// Always render nametag in BotGuiInventory
return 0.0;
} else {
return super.getDistanceSq(entityIn);
}
}
@Override
public void sendStatusMessage(@Nonnull ITextComponent chatComponent, boolean actionBar) {
// TODO: Custom message handling
}
@Override
public void sendMessage(@Nonnull ITextComponent component) {
// TODO: Custom message handling
}
@Override
public void openEditSign(@Nonnull TileEntitySign signTile) {
// TODO: Custom GUI handling
}
@Override
public void displayGuiEditCommandCart(@Nonnull CommandBlockBaseLogic commandBlock) {
// TODO: Custom GUI handling
}
@Override
public void displayGuiCommandBlock(@Nonnull TileEntityCommandBlock commandBlock) {
// TODO: Custom GUI handling
}
@Override
public void openEditStructure(@Nonnull TileEntityStructure structure) {
// TODO: Custom GUI handling
}
@Override
public void openBook(ItemStack stack, EnumHand hand) {
// TODO: Custom GUI handling
}
@Override
public void displayGUIChest(@Nonnull IInventory chestInventory) {
// TODO: Custom GUI handling
}
@Override
public void openGuiHorseInventory(@Nonnull AbstractHorse horse, IInventory inventoryIn) {
// TODO: Custom GUI handling
}
@Override
public void displayGui(IInteractionObject guiOwner) {
// TODO: Custom GUI handling
}
@Override
public void displayVillagerTradeGui(IMerchant villager) {
// TODO: Custom GUI handling
}
@Override
public void onCriticalHit(@Nonnull Entity entityHit) {
// Don't render
}
@Override
public void onEnchantmentCritical(@Nonnull Entity entityHit) {
// Don't render
}
@Override
protected boolean isCurrentViewEntity() {
return true;
}
@Override
public boolean isSpectator() {
NetworkPlayerInfo networkplayerinfo = this.connection.getPlayerInfo(this.getGameProfile().getId());
// noinspection ConstantConditions
return networkplayerinfo != null && networkplayerinfo.getGameType() == GameType.SPECTATOR;
}
@Override
public boolean isCreative() {
NetworkPlayerInfo networkplayerinfo = this.connection.getPlayerInfo(this.getGameProfile().getId());
// noinspection ConstantConditions
return networkplayerinfo != null && networkplayerinfo.getGameType() == GameType.CREATIVE;
}
@Nullable
@Override
protected NetworkPlayerInfo getPlayerInfo() {
return this.playerInfo == null ? (this.playerInfo = this.connection.getPlayerInfo(this.getUniqueID())) : null;
}
@Override
public boolean isAutoJumpEnabled() {
return false;
}
}

View File

@@ -1,39 +0,0 @@
/*
* 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.bot.impl;
import net.minecraft.client.audio.ISound;
import net.minecraft.client.audio.SoundHandler;
import javax.annotation.Nonnull;
/**
* @author Brady
* @since 3/7/2020
*/
public final class BotSoundHandler extends SoundHandler {
public static final BotSoundHandler INSTANCE = new BotSoundHandler();
private BotSoundHandler() {
super(null, null);
}
@Override
public void playSound(@Nonnull ISound sound) {}
}

View File

@@ -1,106 +0,0 @@
/*
* 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.bot.impl;
import it.unimi.dsi.fastutil.ints.*;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.entity.Entity;
import net.minecraft.profiler.Profiler;
import net.minecraft.util.SoundCategory;
import net.minecraft.util.SoundEvent;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.EnumDifficulty;
import net.minecraft.world.WorldSettings;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
/**
* @author Brady
* @since 11/7/2018
*/
public final class BotWorld extends WorldClient {
private static Profiler BOT_WORLD_PROFILER = new Profiler();
private final Map<ChunkPos, IntSet> loadedChunksMap;
public BotWorld(WorldSettings settings, int dimension) {
super(null, settings, dimension, EnumDifficulty.EASY, BOT_WORLD_PROFILER);
this.loadedChunksMap = new HashMap<>();
}
@Override
public void playSound(double x, double y, double z, SoundEvent soundIn, SoundCategory category, float volume, float pitch, boolean distanceDelay) {
// Do nothing
}
@Override
public void addEntityToWorld(int entityID, Entity entity) {
this.removeEntityFromWorld(entityID);
this.spawnEntity(entity);
this.entitiesById.addKey(entityID, entity);
}
@Override
public Entity removeEntityFromWorld(int entityID) {
Entity entity = this.entitiesById.lookup(entityID);
if (entity != null && !(entity instanceof BotPlayer)) {
this.removeEntity(entity);
this.entitiesById.removeObject(entityID);
}
return entity;
}
@Nullable
@Override
public Entity getEntityByID(int id) {
return this.entitiesById.lookup(id);
}
/**
* @param bot The bot requesting the chunk
* @param chunkX The chunk X position
* @param chunkZ The chunk Z position
* @param load {@code true} if the chunk is being loaded, {@code false} if the chunk is being unloaded.
* @return Whether or not the chunk needs to be loaded or unloaded accordingly.
*/
public boolean handlePreChunk(BotPlayer bot, int chunkX, int chunkZ, boolean load) {
IntSet bots = this.loadedChunksMap.computeIfAbsent(new ChunkPos(chunkX, chunkZ), $ -> new IntArraySet());
if (load) {
boolean wasEmpty = bots.isEmpty();
bots.add(bot.getEntityId());
return wasEmpty;
} else {
bots.remove(bot.getEntityId());
return bots.isEmpty();
}
}
public void handleWorldRemove(BotPlayer bot) {
// Remove Bot from world
this.removeEntity(bot);
this.entitiesById.removeObject(bot.getEntityId());
// Unload all chunks that are no longer loaded by the removed Bot
this.loadedChunksMap.entrySet().stream()
.peek(entry -> entry.getValue().remove(bot.getEntityId()))
.filter(entry -> entry.getValue().isEmpty())
.forEach(entry -> this.doPreChunk(entry.getKey().x, entry.getKey().z, false));
}
}

View File

@@ -307,6 +307,9 @@ public final class CachedWorld implements ICachedWorld, Helper {
try {
ChunkPos pos = toPackQueue.take();
Chunk chunk = toPackMap.remove(pos);
if (toPackQueue.size() > Baritone.settings().chunkPackerQueueMaxSize.value) {
continue;
}
CachedChunk cached = ChunkPacker.pack(chunk);
CachedWorld.this.updateCachedChunk(cached);
//System.out.println("Processed chunk at " + chunk.x + "," + chunk.z);

View File

@@ -18,7 +18,6 @@
package baritone.cache;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.cache.IWorldProvider;
import baritone.api.utils.IPlayerContext;
import baritone.utils.accessor.IAnvilChunkLoader;
@@ -161,10 +160,6 @@ public class WorldProvider implements IWorldProvider {
readmeDir = baritone.getDirectory();
}
if (this.baritone != BaritoneAPI.getProvider().getPrimaryBaritone()) {
worldDir = worldDir.resolve("bot");
}
return Optional.of(new Tuple<>(worldDir, readmeDir));
}

View File

@@ -1,168 +0,0 @@
/*
* 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.command.defaults;
import baritone.Baritone;
import baritone.api.IBaritone;
import baritone.api.bot.IBaritoneUser;
import baritone.api.bot.connect.IConnectionResult;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandInvalidTypeException;
import baritone.api.event.events.ChatEvent;
import baritone.bot.UserManager;
import baritone.bot.impl.BotGuiInventory;
import net.minecraft.util.Session;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX;
/**
* @author Brady
* @since 3/2/2020
*/
public class BotCommand extends Command {
public BotCommand(IBaritone baritone) {
super(baritone, "bot");
}
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
final Action action = Action.getByName(args.getString());
if (action == null) {
throw new CommandInvalidTypeException(args.consumed(), "an action");
}
if (action == Action.ADD) {
final String username = args.hasAny() ? args.getString() : "Bot" + System.currentTimeMillis() % 1000;
final Session session = new Session(username, UUID.randomUUID().toString(), "", "");
final IConnectionResult result = UserManager.INSTANCE.connect(session);
logDirect(result.toString());
} else if (action.requiresBotSelector()) {
final String selector = args.getString();
final List<IBaritoneUser> bots;
if (selector.equals("*")) {
bots = UserManager.INSTANCE.getUsers();
} else if (selector.contains(",")) {
bots = Arrays.stream(selector.split(","))
.map(UserManager.INSTANCE::getUserByName)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
} else {
bots = UserManager.INSTANCE.getUserByName(selector)
.map(Collections::singletonList)
.orElseGet(Collections::emptyList);
}
if (bots.isEmpty()) {
throw new CommandInvalidTypeException(args.consumed(), "selector didn't match any bots");
}
if (action == Action.INVENTORY) {
// Only display one inventory lol
final IBaritoneUser bot = bots.get(0);
((Baritone) baritone).showScreen(new BotGuiInventory(bot));
return;
}
switch (action) {
case DISCONNECT: {
bots.forEach(bot -> UserManager.INSTANCE.disconnect(bot, null));
break;
}
case SAY: {
final String message = args.rawRest();
bots.forEach(bot -> bot.getPlayerContext().player().sendChatMessage(message));
break;
}
case EXECUTE: {
final String command = FORCE_COMMAND_PREFIX + args.rawRest();
bots.forEach(bot -> bot.getBaritone().getGameEventHandler().onSendChatMessage(new ChatEvent(command)));
break;
}
}
}
}
@Override
public Stream<String> tabComplete(String label, IArgConsumer args) {
return Stream.empty();
}
@Override
public String getShortDesc() {
return "Manage bots";
}
@Override
public List<String> getLongDesc() {
return Arrays.asList(
"Spawns a bot",
"",
"Usage:",
"> bot add/a <name>",
"> bot inventory/i [bot]",
"> bot disconnect/d [bot]",
"> bot say/s [bot] [args...]",
"> bot execute/e [bot] [args...]"
);
}
private enum Action {
ADD("add", "a"),
INVENTORY("inventory", "i"),
DISCONNECT("disconnect", "d"),
SAY("say", "s"),
EXECUTE("execute", "e");
private final String[] names;
Action(String... names) {
this.names = names;
}
public boolean requiresBotSelector() {
return this == INVENTORY || this == DISCONNECT || this == SAY || this == EXECUTE;
}
public static Action getByName(String name) {
for (Action action : Action.values()) {
for (String alias : action.names) {
if (alias.equalsIgnoreCase(name)) {
return action;
}
}
}
return null;
}
public static String[] getAllNames() {
Set<String> names = new HashSet<>();
for (Action action : Action.values()) {
names.addAll(Arrays.asList(action.names));
}
return names.toArray(new String[0]);
}
}
}

View File

@@ -46,7 +46,6 @@ public final class DefaultCommands {
new LitematicaCommand(baritone),
new ComeCommand(baritone),
new AxisCommand(baritone),
new BotCommand(baritone),
new ForceCancelCommand(baritone),
new GcCommand(baritone),
new InvertCommand(baritone),

View File

@@ -93,7 +93,7 @@ public class CalculationContext {
this.world = baritone.getPlayerContext().world();
this.worldData = (WorldData) baritone.getPlayerContext().worldData();
this.bsi = new BlockStateInterface(baritone.getPlayerContext(), forUseOnAnotherThread);
this.toolSet = new ToolSet(player);
this.toolSet = new ToolSet(baritone.getPlayerContext());
this.hasThrowaway = Baritone.settings().allowPlace.value && ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway();
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.value && InventoryPlayer.isHotbar(player.inventory.getSlotFor(STACK_BUCKET_WATER)) && !world.provider.isNether();
this.canSprint = Baritone.settings().allowSprint.value && player.getFoodStats().getFoodLevel() > 6;

View File

@@ -18,12 +18,12 @@
package baritone.pathing.movement;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.pathing.movement.ActionCosts;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.*;
import baritone.api.utils.input.Input;
import baritone.behavior.InventoryBehavior;
import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.pathing.precompute.Ternary;
import baritone.utils.BlockStateInterface;
@@ -577,23 +577,17 @@ public interface MovementHelper extends ActionCosts, Helper {
/**
* AutoTool for a specific block
*
* @param ctx The player context
* @param b the blockstate to mine
* @param ctx The player context
* @param state The blockstate to mine
*/
static void switchToBestToolFor(IPlayerContext ctx, IBlockState b) {
switchToBestToolFor(ctx, b, new ToolSet(ctx.player()), BaritoneAPI.getSettings().preferSilkTouch.value);
}
/**
* AutoTool for a specific block with precomputed ToolSet data
*
* @param ctx The player context
* @param b the blockstate to mine
* @param ts previously calculated ToolSet
*/
static void switchToBestToolFor(IPlayerContext ctx, IBlockState b, ToolSet ts, boolean preferSilkTouch) {
if (Baritone.settings().autoTool.value && !Baritone.settings().assumeExternalAutoTool.value) {
ctx.player().inventory.currentItem = ts.getBestSlot(b.getBlock(), preferSilkTouch);
static void switchToBestToolFor(IPlayerContext ctx, IBlockState state) {
if (ToolSet.isAutoTool()) {
// TODO: Submit through InventoryBehavior, instead of executing the strategy here
final InventorySlot slot = new ToolSet(ctx).getBestSlot(state, Baritone.settings().preferSilkTouch.value, null);
final InventoryBehavior.SelectionStrategy strategy = ((Baritone) ctx.baritone()).getInventoryBehavior().resolveSelectionStrategy(slot);
if (strategy != null) {
strategy.run();
}
}
}

View File

@@ -542,7 +542,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
}
if (Baritone.settings().allowInventory.value) {
if (baritone.getInventoryBehavior().canAccessInventory()) {
ArrayList<Integer> usefulSlots = new ArrayList<>();
List<IBlockState> noValidHotbarOption = new ArrayList<>();
outer:

View File

@@ -269,7 +269,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
for (BlockPos pos : both) {
boolean soulsand = openSoulsand.contains(pos);
Optional<Rotation> rot = RotationUtils.reachableOffset(ctx, pos, new Vec3d(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5), ctx.playerController().getBlockReachDistance(), false);
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, soulsand ? this::isNetherWart : this::isPlantable)) {
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().trySelectItem(soulsand ? this::isNetherWart : this::isPlantable)) {
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), ctx.playerController().getBlockReachDistance());
if (result.typeOfHit == RayTraceResult.Type.BLOCK && result.sideHit == EnumFacing.UP) {
baritone.getLookBehavior().updateTarget(rot.get(), true);
@@ -287,7 +287,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
}
Vec3d faceCenter = new Vec3d(pos).add(0.5, 0.5, 0.5).add(new Vec3d(dir.getDirectionVec()).scale(0.5));
Optional<Rotation> rot = RotationUtils.reachableOffset(ctx, pos, faceCenter, ctx.playerController().getBlockReachDistance(), false);
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, this::isCocoa)) {
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().trySelectItem(this::isCocoa)) {
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), ctx.playerController().getBlockReachDistance());
if (result.typeOfHit == RayTraceResult.Type.BLOCK && result.sideHit == dir) {
baritone.getLookBehavior().updateTarget(rot.get(), true);
@@ -301,7 +301,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
}
for (BlockPos pos : bonemealable) {
Optional<Rotation> rot = RotationUtils.reachable(ctx, pos);
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, this::isBoneMeal)) {
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().trySelectItem(this::isBoneMeal)) {
baritone.getLookBehavior().updateTarget(rot.get(), true);
if (ctx.isLookingAt(pos)) {
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_RIGHT, true);
@@ -323,17 +323,17 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
for (BlockPos pos : toBreak) {
goalz.add(new BuilderProcess.GoalBreak(pos));
}
if (baritone.getInventoryBehavior().throwaway(false, this::isPlantable)) {
if (baritone.getInventoryBehavior().canSelectItem(this::isPlantable)) {
for (BlockPos pos : openFarmland) {
goalz.add(new GoalBlock(pos.up()));
}
}
if (baritone.getInventoryBehavior().throwaway(false, this::isNetherWart)) {
if (baritone.getInventoryBehavior().canSelectItem(this::isNetherWart)) {
for (BlockPos pos : openSoulsand) {
goalz.add(new GoalBlock(pos.up()));
}
}
if (baritone.getInventoryBehavior().throwaway(false, this::isCocoa)) {
if (baritone.getInventoryBehavior().canSelectItem(this::isCocoa)) {
for (BlockPos pos : openLog) {
for (EnumFacing direction : EnumFacing.Plane.HORIZONTAL) {
if (ctx.world().getBlockState(pos.offset(direction)).getBlock() instanceof BlockAir) {
@@ -342,7 +342,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
}
}
}
if (baritone.getInventoryBehavior().throwaway(false, this::isBoneMeal)) {
if (baritone.getInventoryBehavior().canSelectItem(this::isBoneMeal)) {
for (BlockPos pos : bonemealable) {
goalz.add(new GoalBlock(pos));
}

View File

@@ -0,0 +1,100 @@
/*
* 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;
import it.unimi.dsi.fastutil.objects.Reference2BooleanMap;
import it.unimi.dsi.fastutil.objects.Reference2BooleanOpenHashMap;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResult;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import javax.annotation.Nonnull;
import java.lang.reflect.Method;
/**
* @author Brady
*/
public final class ItemInteractionHelper {
private ItemInteractionHelper() {}
private static final Reference2BooleanMap<Class<? extends Item>> CACHE = new Reference2BooleanOpenHashMap<>();
public static boolean couldInteract(final ItemStack stack) {
if (stack.isEmpty()) {
return false;
}
return CACHE.computeIfAbsent(stack.getItem().getClass(), itemClass -> {
try {
final Method onItemUse = itemClass.getMethod(Helper1.name, Helper1.parameters);
final Method onItemRightClick = itemClass.getMethod(Helper2.name, Helper2.parameters);
// If the declaring class isn't Item, then the method is overridden
return onItemUse.getDeclaringClass() != Item.class
|| onItemRightClick.getDeclaringClass() != Item.class;
} catch (NoSuchMethodException ignored) {
// this shouldn't happen
return true;
}
});
}
private static final class Helper1 extends Item {
public static final String name;
public static final Class<?>[] parameters;
static {
final Method method = Helper1.class.getDeclaredMethods()[0];
name = method.getName();
parameters = method.getParameterTypes();
}
@Nonnull
@Override
public EnumActionResult onItemUse(@Nonnull EntityPlayer player, @Nonnull World worldIn,
@Nonnull BlockPos pos, @Nonnull EnumHand hand,
@Nonnull EnumFacing facing, float hitX, float hitY, float hitZ) {
return super.onItemUse(player, worldIn, pos, hand, facing, hitX, hitY, hitZ);
}
}
private static final class Helper2 extends Item {
public static final String name;
public static final Class<?>[] parameters;
static {
final Method method = Helper2.class.getDeclaredMethods()[0];
name = method.getName();
parameters = method.getParameterTypes();
}
@Nonnull
@Override
public ActionResult<ItemStack> onItemRightClick(@Nonnull World worldIn, @Nonnull EntityPlayer playerIn,
@Nonnull EnumHand handIn) {
return super.onItemRightClick(worldIn, playerIn, handIn);
}
}
}

View File

@@ -1,55 +0,0 @@
/*
* 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;
import sun.misc.Unsafe;
import java.lang.reflect.Field;
/**
* Hacky util to allocate objects without needing to invoke their constructor.
*
* @author Brady
* @since 3/3/2020
*/
public final class ObjectAllocator {
private static final Unsafe theUnsafe;
static {
try {
Class<?> clazz = Class.forName("sun.misc.Unsafe");
Field field = clazz.getDeclaredField("theUnsafe");
field.setAccessible(true);
theUnsafe = (Unsafe) field.get(null);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private ObjectAllocator() {}
public static <T> T allocate(Class<T> clazz) {
try {
// noinspection unchecked
return (T) theUnsafe.allocateInstance(clazz);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

View File

@@ -56,7 +56,7 @@ public final class PathRenderer implements IRenderer {
if (ctx.world() == null) {
return;
}
if (ctx.minecraft().currentScreen instanceof GuiClick && behavior.baritone == BaritoneAPI.getProvider().getPrimaryBaritone()) {
if (ctx.minecraft().currentScreen instanceof GuiClick) {
((GuiClick) ctx.minecraft().currentScreen).onRender();
}

View File

@@ -17,15 +17,14 @@
package baritone.utils;
import baritone.api.utils.IInputOverrideHandler;
import baritone.api.utils.input.Input;
import net.minecraft.util.MovementInput;
public class PlayerMovementInput extends MovementInput {
private final IInputOverrideHandler handler;
private final InputOverrideHandler handler;
public PlayerMovementInput(IInputOverrideHandler handler) {
PlayerMovementInput(InputOverrideHandler handler) {
this.handler = handler;
}

View File

@@ -18,62 +18,78 @@
package baritone.utils;
import baritone.Baritone;
import baritone.PerformanceCritical;
import baritone.api.utils.IPlayerContext;
import baritone.api.utils.InventorySlot;
import baritone.utils.accessor.IItemTool;
import it.unimi.dsi.fastutil.HashCommon;
import it.unimi.dsi.fastutil.objects.Reference2DoubleOpenHashMap;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.init.Enchantments;
import net.minecraft.init.MobEffects;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.item.ItemTool;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
import java.util.Comparator;
import java.util.function.Predicate;
import java.util.function.ToDoubleFunction;
/**
* A cached list of the best tools on the hotbar for any block
*
* @author Avery, Brady, leijurv
*/
public class ToolSet {
public final class ToolSet {
/**
* A cache mapping a {@link Block} to how long it will take to break
* with this toolset, given the optimum tool is used.
*/
private final Map<Block, Double> breakStrengthCache;
private final Cache breakStrengthCache;
/**
* My buddy leijurv owned me so we have this to not create a new lambda instance.
*/
private final Function<Block, Double> backendCalculation;
private final ToDoubleFunction<IBlockState> backendCalculation;
private final EntityPlayerSP player;
private final IPlayerContext ctx;
public ToolSet(EntityPlayerSP player) {
breakStrengthCache = new HashMap<>();
this.player = player;
public ToolSet(IPlayerContext ctx) {
this.ctx = ctx;
this.breakStrengthCache = new Cache();
if (Baritone.settings().considerPotionEffects.value) {
double amplifier = potionAmplifier();
Function<Double, Double> amplify = x -> amplifier * x;
backendCalculation = amplify.compose(this::getBestDestructionTime);
double amplifier = this.potionAmplifier();
this.backendCalculation = block -> amplifier * this.getBestDestructionSpeed(block);
} else {
backendCalculation = this::getBestDestructionTime;
this.backendCalculation = this::getBestDestructionSpeed;
}
}
/**
* Using the best tool on the hotbar, how fast we can mine this block
*
* @param state the blockstate to be mined
* @param state the state to be mined
* @return the speed of how fast we'll mine it. 1/(time in ticks)
*/
@PerformanceCritical
public double getStrVsBlock(IBlockState state) {
return breakStrengthCache.computeIfAbsent(state.getBlock(), backendCalculation);
return this.breakStrengthCache.computeIfAbsent(state, this.backendCalculation);
}
/**
* Calculate how effectively a block can be destroyed
*
* @param state the block state to be mined
* @return A double containing the destruction speed with the best tool
*/
private double getBestDestructionSpeed(IBlockState state) {
final ItemStack stack = isAutoTool()
? ctx.inventory().itemAt(this.getBestSlot(state, false, null))
: ctx.player().getHeldItemMainhand();
return calculateSpeedVsBlock(stack, state) * avoidanceMultiplier(state.getBlock());
}
/**
@@ -81,92 +97,55 @@ public class ToolSet {
* harvest level order; there is a chance for multiple at the same with modded tools
* but in that case we don't really care.
*
* @param itemStack a possibly empty ItemStack
* @return values from 0 up
* @param stack a possibly empty ItemStack
* @return The tool's harvest level, or {@code -1} if the stack isn't a tool
*/
private int getMaterialCost(ItemStack itemStack) {
if (itemStack.getItem() instanceof ItemTool) {
ItemTool tool = (ItemTool) itemStack.getItem();
return ((IItemTool) tool).getHarvestLevel();
private static int getMaterialCost(ItemStack stack) {
if (stack.getItem() instanceof IItemTool) {
return ((IItemTool) stack.getItem()).getHarvestLevel();
} else {
return -1;
}
}
public boolean hasSilkTouch(ItemStack stack) {
return EnchantmentHelper.getEnchantmentLevel(Enchantments.SILK_TOUCH, stack) > 0;
}
/**
* Calculate which tool on the hotbar is best for mining, depending on an override setting,
* related to auto tool movement cost, it will either return current selected slot, or the best slot.
*
* @param b the blockstate to be mined
* @param state the blockstate to be mined
* @param preferSilkTouch whether to prefer silk touch tools
* @param extra An additional filter to apply on top of the default, setting-based ones, may be {@code null}
* @return An int containing the index in the tools array that worked best
*/
public InventorySlot getBestSlot(final IBlockState state, final boolean preferSilkTouch,
final Predicate<? super ItemStack> extra) {
final Comparator<ItemStack> compare = Comparator
// Prioritize mining speed over everything
.<ItemStack>comparingDouble(stack -> calculateSpeedVsBlock(stack, state))
// Prioritize silk touch tools, if preferSilkTouch is true, over reduced material cost
.thenComparing(ToolSet::hasSilkTouch, (a, b) -> preferSilkTouch ? Boolean.compare(a, b) : 0)
// Minimize material cost
.thenComparing(Comparator.comparingInt(ToolSet::getMaterialCost).reversed());
public int getBestSlot(Block b, boolean preferSilkTouch) {
return getBestSlot(b, preferSilkTouch, false);
}
public int getBestSlot(Block b, boolean preferSilkTouch, boolean pathingCalculation) {
/*
If we actually want know what efficiency our held item has instead of the best one
possible, this lets us make pathing depend on the actual tool to be used (if auto tool is disabled)
*/
if (!Baritone.settings().autoTool.value && pathingCalculation) {
return player.inventory.currentItem;
}
int best = 0;
double highestSpeed = Double.NEGATIVE_INFINITY;
int lowestCost = Integer.MIN_VALUE;
boolean bestSilkTouch = false;
IBlockState blockState = b.getDefaultState();
for (int i = 0; i < 9; i++) {
ItemStack itemStack = player.inventory.getStackInSlot(i);
if (!Baritone.settings().useSwordToMine.value && itemStack.getItem() instanceof ItemSword) {
continue;
}
if (Baritone.settings().itemSaver.value && (itemStack.getItemDamage() + Baritone.settings().itemSaverThreshold.value) >= itemStack.getMaxDamage() && itemStack.getMaxDamage() > 1) {
continue;
}
double speed = calculateSpeedVsBlock(itemStack, blockState);
boolean silkTouch = hasSilkTouch(itemStack);
if (speed > highestSpeed) {
highestSpeed = speed;
best = i;
lowestCost = getMaterialCost(itemStack);
bestSilkTouch = silkTouch;
} else if (speed == highestSpeed) {
int cost = getMaterialCost(itemStack);
if ((cost < lowestCost && (silkTouch || !bestSilkTouch)) ||
(preferSilkTouch && !bestSilkTouch && silkTouch)) {
highestSpeed = speed;
best = i;
lowestCost = cost;
bestSilkTouch = silkTouch;
return ((Baritone) ctx.baritone()).getInventoryBehavior().findBestAccessibleMatching(
compare,
stack -> {
if (!Baritone.settings().useSwordToMine.value && stack.getItem() instanceof ItemSword) {
return false;
}
if (Baritone.settings().itemSaver.value
&& stack.getItemDamage() + Baritone.settings().itemSaverThreshold.value >= stack.getMaxDamage()
&& stack.getMaxDamage() > 1
) {
return false;
}
return extra == null || extra.test(stack);
}
}
}
return best;
);
}
/**
* Calculate how effectively a block can be destroyed
*
* @param b the blockstate to be mined
* @return A double containing the destruction ticks with the best tool
*/
private double getBestDestructionTime(Block b) {
ItemStack stack = player.inventory.getStackInSlot(getBestSlot(b, false, true));
return calculateSpeedVsBlock(stack, b.getDefaultState()) * avoidanceMultiplier(b);
}
private double avoidanceMultiplier(Block b) {
return Baritone.settings().blocksToAvoidBreaking.value.contains(b) ? Baritone.settings().avoidBreakingMultiplier.value : 1;
public static boolean isAutoTool() {
return Baritone.settings().autoTool.value && !Baritone.settings().assumeExternalAutoTool.value;
}
/**
@@ -175,10 +154,19 @@ public class ToolSet {
*
* @param item the item to mine it with
* @param state the blockstate to be mined
* @return how long it would take in ticks
* @return the speed of how fast we'll mine it. 1/(time in ticks)
*/
public static double calculateSpeedVsBlock(ItemStack item, IBlockState state) {
float hardness = state.getBlockHardness(null, null);
float hardness;
try {
// noinspection DataFlowIssue
hardness = state.getBlockHardness(null, null);
} catch (NullPointerException ignored) {
// Just catch the exception and act as if the block is unbreakable. Even in situations where we could
// reasonably determine the hardness by passing the correct world/position (not via 'getStrVsBlock' during
// performance critical cost calculation), it's not worth it for the sake of consistency.
return -1;
}
if (hardness < 0) {
return -1;
}
@@ -199,6 +187,15 @@ public class ToolSet {
}
}
private static double avoidanceMultiplier(Block block) {
return Baritone.settings().blocksToAvoidBreaking.value.contains(block)
? Baritone.settings().avoidBreakingMultiplier.value : 1;
}
private static boolean hasSilkTouch(ItemStack stack) {
return EnchantmentHelper.getEnchantmentLevel(Enchantments.SILK_TOUCH, stack) > 0;
}
/**
* Calculates any modifier to breaking time based on status effects.
*
@@ -206,11 +203,11 @@ public class ToolSet {
*/
private double potionAmplifier() {
double speed = 1;
if (player.isPotionActive(MobEffects.HASTE)) {
speed *= 1 + (player.getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
if (ctx.player().isPotionActive(MobEffects.HASTE)) {
speed *= 1 + (ctx.player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
}
if (player.isPotionActive(MobEffects.MINING_FATIGUE)) {
switch (player.getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) {
if (ctx.player().isPotionActive(MobEffects.MINING_FATIGUE)) {
switch (ctx.player().getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) {
case 0:
speed *= 0.3;
break;
@@ -227,4 +224,60 @@ public class ToolSet {
}
return speed;
}
/*
* Copyright (C) 2002-2022 Sebastiano Vigna
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
private static final class Cache extends Reference2DoubleOpenHashMap<IBlockState> {
public double computeIfAbsent(final IBlockState key, final ToDoubleFunction<IBlockState> mappingFunction) {
int pos = this.find(key);
if (pos >= 0) {
return this.value[pos];
} else {
double newValue = mappingFunction.applyAsDouble(key);
this.insert(-pos - 1, key, newValue);
return newValue;
}
}
private int find(final IBlockState k) {
if (((k) == (null))) return containsNullKey ? n : -(n + 1);
Object curr;
final Object[] key = this.key;
int pos;
// The starting point.
if (((curr = key[pos = (HashCommon.mix(System.identityHashCode(k))) & mask]) == (null))) return -(pos + 1);
if (((k) == (curr))) return pos;
// There's always an unused entry.
while (true) {
if (((curr = key[pos = (pos + 1) & mask]) == (null))) return -(pos + 1);
if (((k) == (curr))) return pos;
}
}
private void insert(int pos, IBlockState k, double v) {
if (pos == this.n) {
this.containsNullKey = true;
}
final Object[] key = this.key;
key[pos] = k;
this.value[pos] = v;
if (this.size++ >= this.maxFill) {
this.rehash(HashCommon.arraySize(this.size + 1, this.f));
}
}
}
}

View File

@@ -1,34 +0,0 @@
/*
* 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.accessor;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.player.EnumPlayerModelParts;
import java.util.Set;
/**
* @author Brady
* @since 3/6/2020
*/
public interface IGameSettings {
void setSetModelParts(Set<EnumPlayerModelParts> setModelParts);
void setMc(Minecraft mc);
}

View File

@@ -1,29 +0,0 @@
/*
* 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.accessor;
import net.minecraft.client.multiplayer.ThreadLanServerPing;
/**
* @author Brady
* @since 3/4/2020
*/
public interface IIntegratedServer {
ThreadLanServerPing getLanServerPing();
}

View File

@@ -1,28 +0,0 @@
/*
* 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.accessor;
import java.io.File;
/**
* @author Brady
*/
public interface IMinecraft {
void setGameDir(File gameDir);
}

View File

@@ -1,29 +0,0 @@
/*
* 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.accessor;
import net.minecraft.client.multiplayer.WorldClient;
/**
* @author Brady
* @since 3/8/2020
*/
public interface INetHandlerPlayClient {
void setWorld(WorldClient world);
}

View File

@@ -1,29 +0,0 @@
/*
* 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.accessor;
/**
* @author Brady
* @since 3/4/2020
*/
public interface IThreadLanServerPing {
String getMotd();
String getAddress();
}

View File

@@ -0,0 +1,73 @@
/*
* 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
*/
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(InventorySlot::inventory).map(this::itemSlotPairAt);
}
@Override
public Stream<Pair<InventorySlot, ItemStack>> inventorySlots() {
return IntStream.range(9, 36).mapToObj(InventorySlot::inventory).map(this::itemSlotPairAt);
}
@Override
public Pair<InventorySlot, ItemStack> offhand() {
return new Pair<>(InventorySlot.offhand(), ctx.player().inventory.offHandInventory.get(0));
}
@Override
public Stream<Pair<InventorySlot, ItemStack>> armorSlots() {
return IntStream.range(0, 4).mapToObj(InventorySlot::armor).map(this::itemSlotPairAt);
}
@Override
public ItemStack itemAt(InventorySlot slot) {
return ctx.player().inventoryContainer.getSlot(slot.getSlotId()).getStack();
}
private Pair<InventorySlot, ItemStack> itemSlotPairAt(InventorySlot slot) {
return new Pair<>(slot, this.itemAt(slot));
}
}

View File

@@ -18,6 +18,7 @@
package baritone.utils.player;
import baritone.Baritone;
import baritone.api.IBaritone;
import baritone.api.cache.IWorldData;
import baritone.api.utils.*;
import net.minecraft.client.Minecraft;
@@ -38,11 +39,18 @@ 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
public IBaritone baritone() {
return this.baritone;
}
@Override
@@ -60,6 +68,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;

View File

@@ -72,11 +72,6 @@ public final class BaritonePlayerController implements IPlayerController {
return mc.playerController.windowClick(windowId, slotId, mouseButton, type, player);
}
@Override
public void setGameType(GameType type) {
mc.playerController.setGameType(type);
}
@Override
public GameType getGameType() {
return mc.playerController.getCurrentGameType();