diff --git a/src/main/java/baritone/bot/GameEventHandler.java b/src/main/java/baritone/bot/GameEventHandler.java index 24ebc4332..011fb601e 100755 --- a/src/main/java/baritone/bot/GameEventHandler.java +++ b/src/main/java/baritone/bot/GameEventHandler.java @@ -3,6 +3,7 @@ package baritone.bot; import baritone.bot.behavior.Behavior; import baritone.bot.event.IGameEventListener; import baritone.bot.event.events.ChatEvent; +import baritone.bot.event.events.ChunkEvent; import net.minecraft.client.settings.KeyBinding; import org.lwjgl.input.Keyboard; @@ -18,7 +19,7 @@ public final class GameEventHandler implements IGameEventListener { @Override public final void onTick() { - dispatchEventToBehaviors(behavior -> onTick()); + dispatch(behavior -> onTick()); } @Override @@ -37,15 +38,20 @@ public final class GameEventHandler implements IGameEventListener { } } - dispatchEventToBehaviors(behavior -> onProcessKeyBinds()); + dispatch(behavior -> onProcessKeyBinds()); } @Override public void onSendChatMessage(ChatEvent event) { - dispatchEventToBehaviors(behavior -> onSendChatMessage(event)); + dispatch(behavior -> onSendChatMessage(event)); } - private void dispatchEventToBehaviors(Consumer dispatchFunction) { + @Override + public void onChunkEvent(ChunkEvent event) { + dispatch(behavior -> onChunkEvent(event)); + } + + private void dispatch(Consumer dispatchFunction) { Baritone.INSTANCE.getBehaviors().stream().filter(Behavior::isEnabled).forEach(dispatchFunction); } } \ No newline at end of file diff --git a/src/main/java/baritone/bot/event/AbstractGameEventListener.java b/src/main/java/baritone/bot/event/AbstractGameEventListener.java index 6e7953bde..22199f3f3 100644 --- a/src/main/java/baritone/bot/event/AbstractGameEventListener.java +++ b/src/main/java/baritone/bot/event/AbstractGameEventListener.java @@ -1,6 +1,7 @@ package baritone.bot.event; import baritone.bot.event.events.ChatEvent; +import baritone.bot.event.events.ChunkEvent; /** * An implementation of {@link IGameEventListener} that has all methods @@ -25,4 +26,7 @@ public interface AbstractGameEventListener extends IGameEventListener { @Override default void onSendChatMessage(ChatEvent event) {} + + @Override + default void onChunkEvent(ChunkEvent event) {} } diff --git a/src/main/java/baritone/bot/event/IGameEventListener.java b/src/main/java/baritone/bot/event/IGameEventListener.java index c3e31a563..1e3c03edf 100755 --- a/src/main/java/baritone/bot/event/IGameEventListener.java +++ b/src/main/java/baritone/bot/event/IGameEventListener.java @@ -1,8 +1,10 @@ package baritone.bot.event; import baritone.bot.event.events.ChatEvent; +import baritone.bot.event.events.ChunkEvent; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.multiplayer.WorldClient; /** * @author Brady @@ -11,17 +13,31 @@ import net.minecraft.client.entity.EntityPlayerSP; public interface IGameEventListener { /** - * Run once per game tick from {@link Minecraft#runTick()} + * Run once per game tick before screen input is handled. + * + * @see Minecraft#runTick() */ void onTick(); /** - * Run once per game tick from {@link Minecraft#processKeyBinds()} + * Run once per game tick from before keybinds are processed. + * + * @see Minecraft#processKeyBinds() */ void onProcessKeyBinds(); /** - * Runs whenever the client player sends a message to the server {@link EntityPlayerSP#sendChatMessage(String)} + * Runs whenever the client player sends a message to the server. + * + * @see EntityPlayerSP#sendChatMessage(String) */ void onSendChatMessage(ChatEvent event); + + + /** + * Runs before and after whenever a chunk is either loaded or unloaded. + * + * @see WorldClient#doPreChunk(int, int, boolean) + */ + void onChunkEvent(ChunkEvent event); } diff --git a/src/main/java/baritone/bot/event/events/ChunkEvent.java b/src/main/java/baritone/bot/event/events/ChunkEvent.java new file mode 100644 index 000000000..d3e713a69 --- /dev/null +++ b/src/main/java/baritone/bot/event/events/ChunkEvent.java @@ -0,0 +1,70 @@ +package baritone.bot.event.events; + +import baritone.bot.event.events.type.EventState; + +/** + * @author Brady + * @since 8/2/2018 12:32 AM + */ +public final class ChunkEvent { + + /** + * The state of the event + */ + private final EventState state; + + /** + * The type of chunk event that occurred; + */ + private final Type type; + + /** + * The Chunk X position. + */ + private final int x; + + /** + * The Chunk Y position. + */ + private final int y; + + public ChunkEvent(EventState state, Type type, int x, int y) { + this.state = state; + this.type = type; + this.x = x; + this.y = y; + } + + /** + * @return The state of the event + */ + public final EventState getState() { + return this.state; + } + + /** + * @return The type of chunk event that occurred; + */ + public final Type getType() { + return this.type; + } + + /** + * @return The Chunk X position. + */ + public final int getX() { + return this.x; + } + + /** + * @return The Chunk Y position. + */ + public final int getY() { + return this.y; + } + + public enum Type { + LOAD, + UNLOAD + } +} diff --git a/src/main/java/baritone/bot/event/events/type/EventState.java b/src/main/java/baritone/bot/event/events/type/EventState.java new file mode 100644 index 000000000..f8090edbf --- /dev/null +++ b/src/main/java/baritone/bot/event/events/type/EventState.java @@ -0,0 +1,20 @@ +package baritone.bot.event.events.type; + +/** + * @author Brady + * @since 8/2/2018 12:34 AM + */ +public enum EventState { + + /** + * Indicates that whatever action the event is being + * dispatched as a result of is about to occur. + */ + PRE, + + /** + * Indicates that whatever action the event is being + * dispatched as a result of has already occured. + */ + POST +} diff --git a/src/main/java/baritone/launch/mixins/MixinWorldClient.java b/src/main/java/baritone/launch/mixins/MixinWorldClient.java new file mode 100644 index 000000000..ac6f925e8 --- /dev/null +++ b/src/main/java/baritone/launch/mixins/MixinWorldClient.java @@ -0,0 +1,48 @@ +package baritone.launch.mixins; + +import baritone.bot.Baritone; +import baritone.bot.event.events.ChunkEvent; +import baritone.bot.event.events.type.EventState; +import net.minecraft.client.multiplayer.WorldClient; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** + * @author Brady + * @since 8/2/2018 12:41 AM + */ +@Mixin(WorldClient.class) +public class MixinWorldClient { + + @Inject( + method = "doPreChunk", + at = @At("HEAD") + ) + private void preDoPreChunk(int chunkX, int chunkY, boolean loadChunk, CallbackInfo ci) { + Baritone.INSTANCE.getGameEventHandler().onChunkEvent( + new ChunkEvent( + EventState.PRE, + loadChunk ? ChunkEvent.Type.LOAD : ChunkEvent.Type.UNLOAD, + chunkX, + chunkY + ) + ); + } + + @Inject( + method = "doPreChunk", + at = @At("RETURN") + ) + private void postDoPreChunk(int chunkX, int chunkY, boolean loadChunk, CallbackInfo ci) { + Baritone.INSTANCE.getGameEventHandler().onChunkEvent( + new ChunkEvent( + EventState.POST, + loadChunk ? ChunkEvent.Type.LOAD : ChunkEvent.Type.UNLOAD, + chunkX, + chunkY + ) + ); + } +} diff --git a/src/main/resources/mixins.baritone.json b/src/main/resources/mixins.baritone.json index 798452918..07e6104b5 100755 --- a/src/main/resources/mixins.baritone.json +++ b/src/main/resources/mixins.baritone.json @@ -12,6 +12,7 @@ "MixinGuiScreen", "MixinKeyBinding", "MixinMain", - "MixinMinecraft" + "MixinMinecraft", + "MixinWorldClient" ] } \ No newline at end of file