Added QueryItemSlotForBlock event, fixes #37

This commit is contained in:
Brady 2018-08-20 20:32:18 -05:00
parent 7f578bc3bf
commit 4cf5ba0fcc
No known key found for this signature in database
GPG Key ID: 73A788379A197567
10 changed files with 251 additions and 30 deletions

View File

@ -61,9 +61,11 @@ public enum Baritone {
this.inputOverrideHandler = new InputOverrideHandler(); this.inputOverrideHandler = new InputOverrideHandler();
this.settings = new Settings(); this.settings = new Settings();
this.behaviors = new ArrayList<>(); this.behaviors = new ArrayList<>();
behaviors.add(PathingBehavior.INSTANCE); {
behaviors.add(LookBehavior.INSTANCE); registerBehavior(PathingBehavior.INSTANCE);
behaviors.add(MemoryBehavior.INSTANCE); registerBehavior(LookBehavior.INSTANCE);
registerBehavior(MemoryBehavior.INSTANCE);
}
this.active = true; this.active = true;
this.initialized = true; this.initialized = true;
@ -87,6 +89,7 @@ public enum Baritone {
public void registerBehavior(Behavior behavior) { public void registerBehavior(Behavior behavior) {
this.behaviors.add(behavior); this.behaviors.add(behavior);
this.gameEventHandler.registerEventListener(behavior);
} }
public final boolean isActive() { public final boolean isActive() {

View File

@ -19,6 +19,7 @@ package baritone.bot.behavior;
import baritone.bot.event.listener.AbstractGameEventListener; import baritone.bot.event.listener.AbstractGameEventListener;
import baritone.bot.utils.Helper; import baritone.bot.utils.Helper;
import baritone.bot.utils.interfaces.Toggleable;
/** /**
* A generic bot behavior. * A generic bot behavior.
@ -26,7 +27,7 @@ import baritone.bot.utils.Helper;
* @author Brady * @author Brady
* @since 8/1/2018 6:29 PM * @since 8/1/2018 6:29 PM
*/ */
public class Behavior implements AbstractGameEventListener, Helper { public class Behavior implements AbstractGameEventListener, Toggleable, Helper {
/** /**
* Whether or not this behavior is enabled * Whether or not this behavior is enabled
@ -38,6 +39,7 @@ public class Behavior implements AbstractGameEventListener, Helper {
* *
* @return The new state. * @return The new state.
*/ */
@Override
public final boolean toggle() { public final boolean toggle() {
return this.setEnabled(!this.enabled); return this.setEnabled(!this.enabled);
} }
@ -47,6 +49,7 @@ public class Behavior implements AbstractGameEventListener, Helper {
* *
* @return The new state. * @return The new state.
*/ */
@Override
public final boolean setEnabled(boolean enabled) { public final boolean setEnabled(boolean enabled) {
boolean newState = getNewState(this.enabled, enabled); boolean newState = getNewState(this.enabled, enabled);
if (newState == this.enabled) if (newState == this.enabled)
@ -79,6 +82,7 @@ public class Behavior implements AbstractGameEventListener, Helper {
/** /**
* @return Whether or not this {@link Behavior} is active. * @return Whether or not this {@link Behavior} is active.
*/ */
@Override
public final boolean isEnabled() { public final boolean isEnabled() {
return this.enabled; return this.enabled;
} }

View File

@ -35,7 +35,6 @@
package baritone.bot.event; package baritone.bot.event;
import baritone.bot.Baritone; import baritone.bot.Baritone;
import baritone.bot.behavior.Behavior;
import baritone.bot.chunk.CachedWorld; import baritone.bot.chunk.CachedWorld;
import baritone.bot.chunk.CachedWorldProvider; import baritone.bot.chunk.CachedWorldProvider;
import baritone.bot.chunk.ChunkPacker; import baritone.bot.chunk.ChunkPacker;
@ -44,6 +43,7 @@ import baritone.bot.event.events.type.EventState;
import baritone.bot.event.listener.IGameEventListener; import baritone.bot.event.listener.IGameEventListener;
import baritone.bot.utils.Helper; import baritone.bot.utils.Helper;
import baritone.bot.utils.InputOverrideHandler; import baritone.bot.utils.InputOverrideHandler;
import baritone.bot.utils.interfaces.Toggleable;
import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator; import net.minecraft.client.renderer.Tessellator;
@ -51,6 +51,8 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import org.lwjgl.input.Keyboard; import org.lwjgl.input.Keyboard;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
@ -59,18 +61,20 @@ import java.util.function.Consumer;
*/ */
public final class GameEventHandler implements IGameEventListener, Helper { public final class GameEventHandler implements IGameEventListener, Helper {
private final List<IGameEventListener> listeners = new ArrayList<>();
@Override @Override
public final void onTick(TickEvent event) { public final void onTick(TickEvent event) {
dispatch(behavior -> behavior.onTick(event)); dispatch(listener -> listener.onTick(event));
} }
@Override @Override
public void onPlayerUpdate() { public final void onPlayerUpdate() {
dispatch(Behavior::onPlayerUpdate); dispatch(IGameEventListener::onPlayerUpdate);
} }
@Override @Override
public void onProcessKeyBinds() { public final void onProcessKeyBinds() {
InputOverrideHandler inputHandler = Baritone.INSTANCE.getInputOverrideHandler(); InputOverrideHandler inputHandler = Baritone.INSTANCE.getInputOverrideHandler();
// Simulate the key being held down this tick // Simulate the key being held down this tick
@ -85,16 +89,16 @@ public final class GameEventHandler implements IGameEventListener, Helper {
} }
} }
dispatch(Behavior::onProcessKeyBinds); dispatch(IGameEventListener::onProcessKeyBinds);
} }
@Override @Override
public void onSendChatMessage(ChatEvent event) { public final void onSendChatMessage(ChatEvent event) {
dispatch(behavior -> behavior.onSendChatMessage(event)); dispatch(listener -> listener.onSendChatMessage(event));
} }
@Override @Override
public void onChunkEvent(ChunkEvent event) { public final void onChunkEvent(ChunkEvent event) {
EventState state = event.getState(); EventState state = event.getState();
ChunkEvent.Type type = event.getType(); ChunkEvent.Type type = event.getType();
@ -116,22 +120,22 @@ public final class GameEventHandler implements IGameEventListener, Helper {
} }
} }
dispatch(behavior -> behavior.onChunkEvent(event)); dispatch(listener -> listener.onChunkEvent(event));
} }
@Override @Override
public void onRenderPass(RenderEvent event) { public final void onRenderPass(RenderEvent event) {
/* /*
CachedWorldProvider.INSTANCE.ifWorldLoaded(world -> world.forEachRegion(region -> region.forEachChunk(chunk -> { CachedWorldProvider.INSTANCE.ifWorldLoaded(world -> world.forEachRegion(region -> region.forEachChunk(chunk -> {
drawChunkLine(region.getX() * 512 + chunk.getX() * 16, region.getZ() * 512 + chunk.getZ() * 16, event.getPartialTicks()); drawChunkLine(region.getX() * 512 + chunk.getX() * 16, region.getZ() * 512 + chunk.getZ() * 16, event.getPartialTicks());
}))); })));
*/ */
dispatch(behavior -> behavior.onRenderPass(event)); dispatch(listener -> listener.onRenderPass(event));
} }
@Override @Override
public void onWorldEvent(WorldEvent event) { public final void onWorldEvent(WorldEvent event) {
if (Baritone.settings().chuckCaching.get()) { if (Baritone.settings().chuckCaching.get()) {
CachedWorldProvider cache = CachedWorldProvider.INSTANCE; CachedWorldProvider cache = CachedWorldProvider.INSTANCE;
@ -147,21 +151,34 @@ public final class GameEventHandler implements IGameEventListener, Helper {
} }
} }
dispatch(behavior -> behavior.onWorldEvent(event)); dispatch(listener -> listener.onWorldEvent(event));
} }
@Override @Override
public void onSendPacket(PacketEvent event) { public final void onSendPacket(PacketEvent event) {
dispatch(behavior -> behavior.onSendPacket(event)); dispatch(behavior -> behavior.onSendPacket(event));
} }
@Override @Override
public void onReceivePacket(PacketEvent event) { public final void onReceivePacket(PacketEvent event) {
dispatch(behavior -> behavior.onReceivePacket(event)); dispatch(behavior -> behavior.onReceivePacket(event));
} }
private void dispatch(Consumer<Behavior> dispatchFunction) { @Override
Baritone.INSTANCE.getBehaviors().stream().filter(Behavior::isEnabled).forEach(dispatchFunction); public final void onQueryItemSlotForBlocks(ItemSlotEvent event) {
dispatch(behavior -> behavior.onQueryItemSlotForBlocks(event));
}
public final void registerEventListener(IGameEventListener listener) {
this.listeners.add(listener);
}
private void dispatch(Consumer<IGameEventListener> dispatchFunction) {
this.listeners.stream().filter(this::canDispatch).forEach(dispatchFunction);
}
private boolean canDispatch(IGameEventListener listener) {
return !(listener instanceof Toggleable) || ((Toggleable) listener).isEnabled();
} }
private void drawChunkLine(int posX, int posZ, float partialTicks) { private void drawChunkLine(int posX, int posZ, float partialTicks) {

View File

@ -0,0 +1,56 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot.event.events;
import baritone.bot.event.listener.IGameEventListener;
/**
* Called in some cases where a player's inventory has it's current slot queried.
* <p>
* @see IGameEventListener#onQueryItemSlotForBlocks()
*
* @author Brady
* @since 8/20/2018
*/
public final class ItemSlotEvent {
/**
* The current slot index
*/
private int slot;
public ItemSlotEvent(int slot) {
this.slot = slot;
}
/**
* Sets the new slot index that will be used
*
* @param slot The slot index
*/
public final void setSlot(int slot) {
this.slot = slot;
}
/**
* @return The current slot index
*/
public final int getSlot() {
return this.slot;
}
}

View File

@ -74,4 +74,7 @@ public interface AbstractGameEventListener extends IGameEventListener {
@Override @Override
default void onReceivePacket(PacketEvent event) {} default void onReceivePacket(PacketEvent event) {}
@Override
default void onQueryItemSlotForBlocks(ItemSlotEvent event) {}
} }

View File

@ -36,11 +36,13 @@ package baritone.bot.event.listener;
import baritone.bot.event.events.*; import baritone.bot.event.events.*;
import io.netty.util.concurrent.GenericFutureListener; import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.network.NetworkManager; import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet; import net.minecraft.network.Packet;
@ -114,5 +116,11 @@ public interface IGameEventListener {
*/ */
void onReceivePacket(PacketEvent event); void onReceivePacket(PacketEvent event);
/**
* Run when a query is made for a player's inventory current slot in the context of blocks
*
* @see InventoryPlayer#getDestroySpeed(IBlockState)
* @see InventoryPlayer#canHarvestBlock(IBlockState)
*/
void onQueryItemSlotForBlocks(ItemSlotEvent event);
} }

View File

@ -17,6 +17,9 @@
package baritone.bot.utils; package baritone.bot.utils;
import baritone.bot.Baritone;
import baritone.bot.event.events.ItemSlotEvent;
import baritone.bot.event.listener.AbstractGameEventListener;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -36,10 +39,19 @@ import java.util.Map;
/** /**
* A cached list of the best tools on the hotbar for any block * A cached list of the best tools on the hotbar for any block
* *
* @author avecowa * @author avecowa, Brady
*/ */
public class ToolSet implements Helper { public class ToolSet implements Helper {
/**
* Instance of the internal event listener used to hook into Baritone's event bus
*/
private static final InternalEventListener INTERNAL_EVENT_LISTENER = new InternalEventListener();
static {
Baritone.INSTANCE.getGameEventHandler().registerEventListener(INTERNAL_EVENT_LISTENER);
}
/** /**
* A list of tools on the hotbar that should be considered. * A list of tools on the hotbar that should be considered.
* Note that if there are no tools on the hotbar this list will still have one (null) entry. * Note that if there are no tools on the hotbar this list will still have one (null) entry.
@ -131,18 +143,29 @@ public class ToolSet implements Helper {
// Calculate the slot with the best item // Calculate the slot with the best item
byte slot = this.getBestSlot(state); byte slot = this.getBestSlot(state);
// Save the old current slot INTERNAL_EVENT_LISTENER.setOverrideSlot(slot);
int oldSlot = player().inventory.currentItem;
// Set the best slot
player().inventory.currentItem = slot;
// Calculate the relative hardness of the block to the player // Calculate the relative hardness of the block to the player
float hardness = state.getPlayerRelativeBlockHardness(player(), world(), pos); float hardness = state.getPlayerRelativeBlockHardness(player(), world(), pos);
// Restore the old slot // Restore the old slot
player().inventory.currentItem = oldSlot; INTERNAL_EVENT_LISTENER.setOverrideSlot(-1);
return hardness; return hardness;
} }
private static final class InternalEventListener implements AbstractGameEventListener {
private int overrideSlot;
@Override
public void onQueryItemSlotForBlocks(ItemSlotEvent event) {
if (this.overrideSlot >= 0)
event.setSlot(this.overrideSlot);
}
public final void setOverrideSlot(int overrideSlot) {
this.overrideSlot = overrideSlot;
}
}
} }

View File

@ -0,0 +1,44 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot.utils.interfaces;
/**
* @author Brady
* @since 8/20/2018
*/
public interface Toggleable {
/**
* Toggles the enabled state of this {@link Toggleable}.
*
* @return The new state.
*/
boolean toggle();
/**
* Sets the enabled state of this {@link Toggleable}.
*
* @return The new state.
*/
boolean setEnabled(boolean enabled);
/**
* @return Whether or not this {@link Toggleable} object is enabled
*/
boolean isEnabled();
}

View File

@ -0,0 +1,62 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.bot.Baritone;
import baritone.bot.event.events.ItemSlotEvent;
import net.minecraft.entity.player.InventoryPlayer;
import org.spongepowered.asm.lib.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* @author Brady
* @since 8/20/2018
*/
@Mixin(InventoryPlayer.class)
public class MixinInventoryPlayer {
@Redirect(
method = "getDestroySpeed",
at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I"
)
)
private int getDestroySpeed$getCurrentItem(InventoryPlayer inventory) {
ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem);
Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event);
return event.getSlot();
}
@Redirect(
method = "canHarvestBlock",
at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I"
)
)
private int canHarvestBlock$getCurrentItem(InventoryPlayer inventory) {
ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem);
Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event);
return event.getSlot();
}
}

View File

@ -10,6 +10,7 @@
"MixinGameSettings", "MixinGameSettings",
"MixinGuiContainer", "MixinGuiContainer",
"MixinGuiScreen", "MixinGuiScreen",
"MixinInventoryPlayer",
"MixinKeyBinding", "MixinKeyBinding",
"MixinMain", "MixinMain",
"MixinMinecraft", "MixinMinecraft",