Compare commits

..

99 Commits

Author SHA1 Message Date
Brady 9a33c5cd9f Merge branch 'master' into bot-system 2020-01-01 19:23:01 -06:00
Brady 9f5f275a17 Merge branch 'master' into bot-system 2019-10-07 09:42:35 -05:00
Brady ac4895823e Remove comms 2019-10-04 15:52:08 -05:00
Brady 62cea04080 Fix compiler errors 2019-10-04 15:51:44 -05:00
Brady d772a97a0b Fix 2019-10-04 10:22:06 -05:00
Brady 7af0ed6ea1 Merge conflicts 2019-10-04 10:19:35 -05:00
Brady fe3f3a66ce Format bot code 2019-01-22 13:30:11 -06:00
Brady 9c5f82c814 Merge branch 'master' into bot-system 2019-01-18 13:52:22 -06:00
Brady 7c66762f48 Bot system API exposure 2019-01-17 14:43:44 -06:00
Leijurv 830c8190de Merge branch 'comms' into bot-system 2019-01-17 12:18:27 -08:00
Leijurv 47b258d7a4 Merge branch 'master' into comms 2019-01-17 12:16:45 -08:00
Brady df80858c49 Remove duplicate MovementInput implementation, Fixes #312 2019-01-16 13:55:24 -06:00
Brady 5dec544802 Minor fix LOL 2019-01-15 14:59:56 -06:00
Brady 494c056613 Resolve merge conflicts 2019-01-15 14:53:05 -06:00
Brady c0e947f016 Clean up canBreak 2018-12-24 12:23:57 -06:00
Brady c6ce5ea160 Nobody cares about creative mode 2018-12-24 12:19:09 -06:00
Brady 7b2930d5e5 Bot Breaking that is moderately cursed
DMCA gang
2018-12-24 12:11:28 -06:00
Brady 44ca284717 Merge branch 'master' into bot-system 2018-12-18 19:36:10 -06:00
Leijurv 380a645a6c only report items that are actually in the echest 2018-12-17 19:51:24 -08:00
Leijurv 0249bd5dd7 a few more packets, and consistent indexing 2018-12-17 15:15:20 -08:00
Leijurv 8cd8a95763 little fix 2018-12-16 20:14:07 -08:00
Brady 029a2b7f3e Fix NullPointerException 2018-12-15 12:27:19 -06:00
Leijurv 767d0c8ec1 better reporting 2018-12-14 21:57:20 -08:00
Brady 8febed2e42 Remove dependency for PlayerControllerMP implementation 2018-12-14 17:24:07 -06:00
Leijurv 37b1604e5d Merge branch 'master' into comms 2018-12-14 09:38:40 -08:00
Leijurv 82d15570f3 fix rare exception 2018-12-02 16:05:21 -08:00
Leijurv 2c2c420b3a Merge branch 'comms' into bot-system 2018-12-02 13:35:40 -08:00
Leijurv 1422b0a149 Merge branch 'master' into bot-system 2018-12-02 13:35:23 -08:00
Leijurv 6b6dd916b4 Merge branch 'calc-request' into comms 2018-11-23 19:09:01 -08:00
Leijurv 11e44acf65 helper to handle pending msgs 2018-11-23 16:35:03 -08:00
Leijurv 16fec4a1a0 buffered connection creation helper 2018-11-23 16:09:59 -08:00
Leijurv bbded21afb Merge branch 'master' into bot-system 2018-11-23 14:12:02 -08:00
Leijurv 5ae4f23886 Merge branch 'comms' into calc-request 2018-11-23 13:34:48 -08:00
Leijurv f222980a1a move comms to cabaletta.comms 2018-11-23 13:32:18 -08:00
Leijurv c57f65f832 complete new segmented calculation system 2018-11-23 13:17:03 -08:00
Leijurv 85a6ec022e Merge branch 'comms' into calc-request 2018-11-23 13:13:35 -08:00
Leijurv c1032da828 Merge branch 'master' into comms 2018-11-23 13:12:38 -08:00
Leijurv e0d894d296 computation request and response 2018-11-23 12:09:35 -08:00
Leijurv 27c818f873 Merge branch 'comms' into calc-request 2018-11-23 11:49:49 -08:00
Leijurv fdd758bc90 too much log spam 2018-11-23 11:48:01 -08:00
Leijurv 3a2620192b too much log spam 2018-11-23 11:46:47 -08:00
Leijurv c423d5f575 report path start position 2018-11-23 11:35:13 -08:00
Leijurv 81a9b71429 Merge branch 'segment-calculation' into comms 2018-11-23 10:36:56 -08:00
Leijurv 81ecc209d3 synchronize partial reads and writes to a socket 2018-11-23 10:09:13 -08:00
Leijurv 0dc67593bb lots more status 2018-11-18 21:56:46 -08:00
Leijurv 2e180e81ed Merge branch 'comms' of github.com:cabaletta/baritone into comms 2018-11-18 21:42:04 -08:00
Leijurv 0b11057449 Merge branch 'master' into comms 2018-11-18 21:41:50 -08:00
Brady 186652a8d8 Protocol lol 2018-11-18 19:52:11 -06:00
Leijurv 168c151901 Merge branch 'comms' into bot-system 2018-11-18 17:39:35 -08:00
Leijurv 18d8cfb6de Merge branch 'master' into comms 2018-11-18 17:39:26 -08:00
Leijurv f99befd307 oh thats important 2018-11-18 12:04:37 -08:00
Leijurv 9ad35dbf28 remove the useless stuff 2018-11-18 11:35:54 -08:00
Leijurv dfb49179c5 not a handler lol 2018-11-18 11:27:53 -08:00
Brady 3c913a7b85 Fix jar export 2018-11-18 13:27:25 -06:00
Leijurv f01cf669e8 wtf 2018-11-18 11:06:40 -08:00
Leijurv 2d87033f49 f 2018-11-18 11:06:11 -08:00
Leijurv f014e42aa4 initial comms 2018-11-18 11:01:46 -08:00
Brady 46de72e28c Comms Sourceset 2018-11-17 18:07:16 -06:00
Brady 3d5cf9772e Less cancer 2018-11-14 20:55:37 -06:00
Leijurv 7cb38352ac bots 2018-11-14 17:17:52 -08:00
Leijurv 42c78337c7 Merge branch 'master' into bot-system 2018-11-14 16:41:52 -08:00
Brady 0f81212f17 Compile fix 2018-11-13 21:41:52 -06:00
Brady ad0041c2c5 Merge branch 'master' into bot-system 2018-11-13 17:14:29 -06:00
Brady 19e7585cd2 Merge branch 'master' into bot-system 2018-11-11 16:23:47 -06:00
Brady 3aeb29ab22 Merge branch 'master' into bot-system 2018-11-11 13:36:22 -06:00
Brady 8dfe5dfd32 Fix jce.jar not being included as library jar in proguard config 2018-11-09 22:43:00 -06:00
Brady 90236962c4 nice 2018-11-09 22:17:00 -06:00
Brady 2e9e8c1ea1 Actually entirely epic, we're okay 2018-11-09 22:00:11 -06:00
Brady 4bf659e14e Fix ConcurrentModificationException 2018-11-09 21:10:49 -06:00
Brady ceca258867 MORE handlers
also removed scoreboard handlers because lol
2018-11-09 20:50:43 -06:00
Leijurv abda4b3a31 begone 2018-11-09 13:28:49 -08:00
Brady 98664540e2 Merge branch 'master' into bot-system 2018-11-09 14:42:23 -06:00
Brady 484dac66b7 JUMP 2018-11-09 13:58:55 -06:00
Brady 40282cd140 Automatic Disconnect 2018-11-07 16:53:32 -06:00
Brady 41c74cb08c More handlers 2018-11-07 12:23:28 -06:00
Brady 7c92817801 Offline bot testing 2018-11-07 12:01:26 -06:00
Brady 1d56585c67 Fix success connection result 2018-11-06 16:22:24 -06:00
Brady a4ac9c6f8d Bot Connecting 2018-11-06 15:25:25 -06:00
Brady 42d15a7b93 Merge branch 'master' into bot-system 2018-11-06 14:10:11 -06:00
Brady 335c97bae6 Merge branch 'master' into bot-system 2018-11-05 16:06:53 -06:00
Brady 8a8afddce3 Fix bad stack overflow error 2018-10-30 13:57:50 -05:00
Brady c3f6ee87b3 Feed codacy 2018-10-29 23:27:54 -05:00
Brady f45fb3cd8c Add reminder lol 2018-10-29 23:20:11 -05:00
Brady 71c7ed54e5 Reverse increment/decrement 2018-10-29 23:10:46 -05:00
Brady 4f978be2a2 Begin MovementInput implementation 2018-10-29 23:04:26 -05:00
Brady 133d956b3a Create login handler 2018-10-29 22:43:36 -05:00
Brady 095e452632 Merge branch 'master' into bot-system 2018-10-29 22:08:29 -05:00
Brady 047d7f06b8 More handlers 2018-10-26 11:38:52 -05:00
Brady 09a119c4ca More handlers 2018-10-24 20:51:01 -05:00
Brady 746e1f6652 handleTimeUpdate 2018-10-24 19:04:49 -05:00
Brady 1d22cf63f0 Lol 2018-10-23 23:08:43 -05:00
Brady d4b3e71694 handleCombatEvent 2018-10-23 23:07:58 -05:00
Brady a08b406af9 handleCooldown 2018-10-23 23:04:13 -05:00
Brady 1afd367e53 handleResourcePack 2018-10-23 23:00:58 -05:00
Brady 59e920b7b1 Meme 3 2018-10-23 09:58:36 -05:00
Brady 79d230d924 another thought 2018-10-23 00:49:38 -05:00
Brady 29cf79fe17 We don't need the connection handler from the user 2018-10-23 00:46:31 -05:00
Brady 8e75817e29 Meme 2 2018-10-23 00:29:30 -05:00
Brady c6bd3f4f00 Meme 2018-10-23 00:05:48 -05:00
33 changed files with 2294 additions and 34 deletions
+2 -9
View File
@@ -14,19 +14,12 @@ Baritone version:
Forge mods (if used): Forge mods (if used):
## Exception, error or logs ## Exception, error or logs
Please find your `latest.log` or `debug.log` in this folder and attach it to the issue You can find your logs in `%appdata%/.minecraft/logs/` (Windows) or `/Library/Application\ Support/minecraft/logs` (Mac).
Linux: `~/.minecraft/logs/`
Windows: `%appdata%/.minecraft/logs/`
Mac: `/Library/Application\ Support/minecraft/logs/`
## How to reproduce ## How to reproduce
Add your steps to reproduce the issue/bug experienced here. Add your steps to reproduce the issue/bug experienced here.
## Final checklist ## Final checklist
- [x] I know how to properly use check boxes
- [ ] I have included the version of Minecraft I'm running, baritone's version and forge mods (if used). - [ ] I have included the version of Minecraft I'm running, baritone's version and forge mods (if used).
- [ ] I have included logs, exceptions and / or steps to reproduce the issue. - [ ] I have included logs, exceptions and / or steps to reproduce the issue.
- [ ] I have not used any OwO's or UwU's in this issue. - [ ] I have not used any OwO's or UwU's in this issue.
+1 -2
View File
@@ -10,5 +10,4 @@ assignees: ''
With as much detail as possible, describe your question and what you may need help with. With as much detail as possible, describe your question and what you may need help with.
## Final checklist ## Final checklist
- [x] I know how to properly use check boxes - [ ] I have not used any OwO's or UwU's in this issue.
- [ ] I have not used any OwO's or UwU's in this issue.
+1 -2
View File
@@ -16,5 +16,4 @@ If applicable, what settings/customizability should be offered to tweak the func
Describe how your suggestion would improve Baritone, or the reason behind it being added. Describe how your suggestion would improve Baritone, or the reason behind it being added.
## Final checklist ## Final checklist
- [x] I know how to properly use check boxes - [ ] I have not used any OwO's or UwU's in this issue.
- [ ] I have not used any OwO's or UwU's in this issue.
+36
View File
@@ -0,0 +1,36 @@
# Baritone Comms Protocol
## Data Types
| Name | Descriptor | Java |
|------------|-----------------------------------------------------------|-----------------------------|
| coordinate | Big endian 8-byte floating point number | [readDouble], [writeDouble] |
| string | unsigned short (length) followed by UTF-8 character bytes | [readUTF], [writeUTF] |
## Inbound
Allows the server to execute a chat command on behalf of the client's player
### Chat
| Name | Type |
|---------|--------|
| Message | string |
## Outbound
Update the player position with the server
### Status
| Name | Type |
|------|------------|
| X | coordinate |
| Y | coordinate |
| Z | coordinate |
<!-- External links -->
[readUTF]: https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#readUTF()
[writeUTF]: https://docs.oracle.com/javase/7/docs/api/java/io/DataOutputStream.html#writeUTF(java.lang.String)
[readDouble]: https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#readDouble()
[writeDouble]: https://docs.oracle.com/javase/7/docs/api/java/io/DataOutputStream.html#writeDouble(double)
+86 -1
View File
@@ -1 +1,86 @@
[Release](https://github.com/hykilpikonna/baritone/releases/tag/sx-1) # Baritone
[![Build Status](https://travis-ci.com/cabaletta/baritone.svg?branch=master)](https://travis-ci.com/cabaletta/baritone/)
[![Release](https://img.shields.io/github/release/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/releases/)
[![License](https://img.shields.io/badge/license-LGPL--3.0%20with%20anime%20exception-green.svg)](LICENSE)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/a73d037823b64a5faf597a18d71e3400)](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=cabaletta/baritone&amp;utm_campaign=Badge_Grade)
[![HitCount](http://hits.dwyl.com/cabaletta/baritone.svg)](http://hits.dwyl.com/cabaletta/baritone/)
[![GitHub All Releases](https://img.shields.io/github/downloads/cabaletta/baritone/total.svg)](https://github.com/cabaletta/baritone/releases/)
[![Minecraft](https://img.shields.io/badge/MC-1.12.2-brightgreen.svg)](https://github.com/cabaletta/baritone/tree/master/)
[![Minecraft](https://img.shields.io/badge/MC-1.13.2-brightgreen.svg)](https://github.com/cabaletta/baritone/tree/1.13.2/)
[![Minecraft](https://img.shields.io/badge/MC-1.14.4-brightgreen.svg)](https://github.com/cabaletta/baritone/tree/1.14.4/)
[![Code of Conduct](https://img.shields.io/badge/%E2%9D%A4-code%20of%20conduct-blue.svg?style=flat)](https://github.com/cabaletta/baritone/blob/master/CODE_OF_CONDUCT.md)
[![Known Vulnerabilities](https://snyk.io/test/github/cabaletta/baritone/badge.svg?targetFile=build.gradle)](https://snyk.io/test/github/cabaletta/baritone?targetFile=build.gradle)
[![Contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/cabaletta/baritone/issues/)
[![Issues](https://img.shields.io/github/issues/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/issues/)
[![GitHub issues-closed](https://img.shields.io/github/issues-closed/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/issues?q=is%3Aissue+is%3Aclosed)
[![Pull Requests](https://img.shields.io/github/issues-pr/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/pulls/)
![Code size](https://img.shields.io/github/languages/code-size/cabaletta/baritone.svg)
![GitHub repo size](https://img.shields.io/github/repo-size/cabaletta/baritone.svg)
![Lines of Code](https://tokei.rs/b1/github/cabaletta/baritone?category=code)
[![GitHub contributors](https://img.shields.io/github/contributors/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/graphs/contributors/)
[![GitHub commits](https://img.shields.io/github/commits-since/cabaletta/baritone/v1.0.0.svg)](https://github.com/cabaletta/baritone/commit/)
[![Impact integration](https://img.shields.io/badge/Impact%20integration-v1.2.10%20/%20v1.3.5%20/%20v1.4.3-brightgreen.svg)](https://impactclient.net/)
[![ForgeHax integration](https://img.shields.io/badge/ForgeHax%20%22integration%22-scuffed-yellow.svg)](https://github.com/fr1kin/ForgeHax/)
[![Aristois add-on integration](https://img.shields.io/badge/Aristois%20add--on%20integration-v1.3.4%20/%20v1.4.1-green.svg)](https://gitlab.com/emc-mods-indrit/baritone_api)
[![WWE integration](https://img.shields.io/badge/WWE%20%22integration%22-master%3F-green.svg)](https://wweclient.com/)
[![Future integration](https://img.shields.io/badge/Future%20integration-Soon™%3F%3F%3F-red.svg)](https://futureclient.net/)
[![forthebadge](https://forthebadge.com/images/badges/built-with-swag.svg)](http://forthebadge.com/)
[![forthebadge](https://forthebadge.com/images/badges/mom-made-pizza-rolls.svg)](http://forthebadge.com/)
A Minecraft pathfinder bot.
Baritone is the pathfinding system used in [Impact](https://impactclient.net/) since 4.4. There's a [showcase video](https://www.youtube.com/watch?v=yI8hgW_m6dQ) made by @Adovin#3153 on Baritone's integration into Impact. [Here's](https://www.youtube.com/watch?v=StquF69-_wI) a video I made showing off what it can do.
The easiest way to install Baritone is to install [Impact](https://impactclient.net/), which comes with Baritone. The second easiest way (for 1.12.2 only) is to install the v1.2.* forge api jar from [releases](https://github.com/cabaletta/baritone/releases). Otherwise, see [Installation & setup](SETUP.md). Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it.
For 1.14.4, [click here](https://www.dropbox.com/s/rkml3hjokd3qv0m/1.14.4-Baritone.zip?dl=1). Or [with optifine](https://github.com/cabaletta/baritone/issues/797).
This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
the original version of the bot for Minecraft 1.8.9, rebuilt for 1.12.2 and 1.13.2. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
Have committed at least once a day from Aug 1 2018 to Aug 1 2019.
1Leijurv3DWTrGAfmmiTphjhXLvQiHg7K2
# Getting Started
Here are some links to help to get started:
- [Features](FEATURES.md)
- [Installation & setup](SETUP.md)
- [API Javadocs](https://baritone.leijurv.com/)
- [Settings](https://baritone.leijurv.com/baritone/api/Settings.html#field.detail)
- [Usage (chat control)](USAGE.md)
# API
The API is heavily documented, you can find the Javadocs for the latest release [here](https://baritone.leijurv.com/).
Please note that usage of anything located outside of the ``baritone.api`` package is not supported by the API release
jar.
Below is an example of basic usage for changing some settings, and then pathing to a X/Z goal.
```
BaritoneAPI.getSettings().allowSprint.value = true;
BaritoneAPI.getSettings().primaryTimeoutMS.value = 2000L;
BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAndPath(new GoalXZ(10000, 20000));
```
# FAQ
## Can I use Baritone as a library in my custom utility client?
That's what it's for, sure! (As long as usage is in compliance with the LGPL 3.0 License)
## How is it so fast?
Magic. (Hours of [leijurv](https://github.com/leijurv/) enduring excruciating pain)
## Why is it called Baritone?
It's named for FitMC's deep sultry voice.
+1 -1
View File
@@ -16,7 +16,7 @@
*/ */
group 'baritone' group 'baritone'
version '1.2.11' version '1.2.10'
buildscript { buildscript {
repositories { repositories {
@@ -34,6 +34,7 @@ import java.lang.reflect.Field;
import java.net.URL; import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*; import java.util.*;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@@ -113,6 +114,7 @@ public class ProguardTask extends BaritoneGradleTask {
Process p = new ProcessBuilder("java", "-verbose").start(); Process p = new ProcessBuilder("java", "-verbose").start();
String out = IOUtils.toString(p.getInputStream(), "UTF-8").split("\n")[0].split("Opened ")[1].replace("]", ""); String out = IOUtils.toString(p.getInputStream(), "UTF-8").split("\n")[0].split("Opened ")[1].replace("]", "");
template.add(2, "-libraryjars '" + out + "'"); 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 // API config doesn't require any changes from the changes that we made to the template
Files.write(getTemporaryFile(PROGUARD_API_CONFIG), template); Files.write(getTemporaryFile(PROGUARD_API_CONFIG), template);
@@ -17,6 +17,7 @@
package baritone.api; package baritone.api;
import baritone.api.bot.IUserManager;
import baritone.api.cache.IWorldScanner; import baritone.api.cache.IWorldScanner;
import baritone.api.command.ICommand; import baritone.api.command.ICommand;
import baritone.api.command.ICommandSystem; import baritone.api.command.ICommandSystem;
@@ -69,13 +70,18 @@ public interface IBaritoneProvider {
} }
/** /**
* Returns the {@link IWorldScanner} instance. This is not a type returned by * Returns the {@link IWorldScanner} instance. This is not a type returned by a
* {@link IBaritone} implementation, because it is not linked with {@link IBaritone}. * {@link IBaritone} implementation because it is not linked with {@link IBaritone}.
* *
* @return The {@link IWorldScanner} instance. * @return The {@link IWorldScanner} instance.
*/ */
IWorldScanner getWorldScanner(); IWorldScanner getWorldScanner();
/**
* @return The {@link IUserManager} instance.
*/
IUserManager getUserManager();
/** /**
* Returns the {@link ICommandSystem} instance. This is not bound to a specific {@link IBaritone} * 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. * instance because {@link ICommandSystem} itself controls global behavior for {@link ICommand}s.
@@ -0,0 +1,80 @@
/*
* 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.IPlayerController;
import com.mojang.authlib.GameProfile;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.network.INetHandler;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.INetHandlerPlayClient;
import net.minecraft.util.Session;
/**
* @author Brady
* @since 10/23/2018
*/
public interface IBaritoneUser {
/**
* @return The network manager that is responsible for the current connection.
*/
NetworkManager getNetworkManager();
/**
* Returns the current play network handler. Can also be acquired via
* {@link NetworkManager#getNetHandler()} from {@link #getNetworkManager()},
* and checking if the {@link INetHandler} is an instance of {@link INetHandlerPlayClient}.
*
* @return The current play network handler
*/
INetHandlerPlayClient getConnection();
/**
* @return The locally managed entity for this user.
*/
EntityPlayerSP getEntity();
/**
* @return The bot player controller
*/
IPlayerController getPlayerController();
/**
* 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();
IBaritone getBaritone();
}
@@ -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.api.bot;
import baritone.api.bot.connect.IConnectionResult;
import com.mojang.authlib.GameProfile;
import net.minecraft.util.Session;
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.
*
* @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.
*
* @param user The user to disconnect
*/
void disconnect(IBaritoneUser user);
/**
* 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() : users().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() : users().stream().filter(user -> user.getProfile().getId().equals(uuid)).findFirst();
}
/**
* @return All of the users held by this manager
*/
List<IBaritoneUser> users();
}
@@ -0,0 +1,45 @@
/*
* 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 connection initialization failed.
*/
CONNECTION_FAILED,
/**
* The connection was a success
*/
SUCCESS
}
@@ -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 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();
}
@@ -37,7 +37,7 @@ public enum RelativeGoalXZ implements IDatatypePost<GoalXZ, BetterBlockPos> {
final IArgConsumer consumer = ctx.getConsumer(); final IArgConsumer consumer = ctx.getConsumer();
return new GoalXZ( return new GoalXZ(
MathHelper.floor(consumer.getDatatypePost(RelativeCoordinate.INSTANCE, (double) origin.x)), MathHelper.floor(consumer.getDatatypePost(RelativeCoordinate.INSTANCE, (double) origin.x)),
MathHelper.floor(consumer.getDatatypePost(RelativeCoordinate.INSTANCE, (double) origin.z)) MathHelper.floor(consumer.getDatatypePost(RelativeCoordinate.INSTANCE, (double) origin.y))
); );
} }
@@ -105,7 +105,7 @@ public interface IPath {
* Returns the estimated number of ticks to complete the path from the given node index. * Returns the estimated number of ticks to complete the path from the given node index.
* *
* @param pathPosition The index of the node we're calculating from * @param pathPosition The index of the node we're calculating from
* @return The estimated number of ticks remaining frm the given position * @return The estimated number of ticks remaining from the given position
*/ */
default double ticksRemainingFrom(int pathPosition) { default double ticksRemainingFrom(int pathPosition) {
double sum = 0; double sum = 0;
@@ -117,6 +117,15 @@ public interface IPath {
return sum; return sum;
} }
/**
* Returns the estimated amount of time needed to complete this path from start to finish
*
* @return The estimated amount of time, in ticks
*/
default double totalTicks() {
return ticksRemainingFrom(0);
}
/** /**
* Cuts off this path at the loaded chunk border, and returns the resulting path. Default * Cuts off this path at the loaded chunk border, and returns the resulting path. Default
* implementation just returns this path, without the intended functionality. * implementation just returns this path, without the intended functionality.
@@ -46,6 +46,8 @@ public interface IPlayerController {
ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player); ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player);
void setGameType(GameType type);
GameType getGameType(); GameType getGameType();
EnumActionResult processRightClickBlock(EntityPlayerSP player, World world, BlockPos pos, EnumFacing direction, Vec3d vec, EnumHand hand); EnumActionResult processRightClickBlock(EntityPlayerSP player, World world, BlockPos pos, EnumFacing direction, Vec3d vec, EnumHand hand);
+4 -5
View File
@@ -25,12 +25,11 @@ import baritone.api.utils.Helper;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
import baritone.behavior.*; import baritone.behavior.*;
import baritone.cache.WorldProvider; import baritone.cache.WorldProvider;
import baritone.command.manager.CommandManager;
import baritone.event.GameEventHandler; import baritone.event.GameEventHandler;
import baritone.process.*; import baritone.process.*;
import baritone.selection.SelectionManager; import baritone.selection.SelectionManager;
import baritone.utils.*; import baritone.utils.*;
import baritone.command.manager.CommandManager;
import baritone.utils.player.PrimaryPlayerContext;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import java.io.File; import java.io.File;
@@ -87,11 +86,11 @@ public class Baritone implements IBaritone {
public BlockStateInterface bsi; public BlockStateInterface bsi;
Baritone() { public Baritone(IPlayerContext playerContext) {
this.gameEventHandler = new GameEventHandler(this); this.gameEventHandler = new GameEventHandler(this);
// Define this before behaviors try and get it, or else it will be null and the builds will fail! // Define this before behaviors try and get it, or else it will be null and the builds will fail!
this.playerContext = PrimaryPlayerContext.INSTANCE; this.playerContext = playerContext;
{ {
// the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist // the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist
@@ -234,4 +233,4 @@ public class Baritone implements IBaritone {
public static Executor getExecutor() { public static Executor getExecutor() {
return threadPool; return threadPool;
} }
} }
+17 -5
View File
@@ -19,15 +19,19 @@ package baritone;
import baritone.api.IBaritone; import baritone.api.IBaritone;
import baritone.api.IBaritoneProvider; import baritone.api.IBaritoneProvider;
import baritone.api.bot.IBaritoneUser;
import baritone.api.bot.IUserManager;
import baritone.api.cache.IWorldScanner; import baritone.api.cache.IWorldScanner;
import baritone.api.command.ICommandSystem; import baritone.api.command.ICommandSystem;
import baritone.bot.UserManager;
import baritone.api.schematic.ISchematicSystem; import baritone.api.schematic.ISchematicSystem;
import baritone.command.BaritoneChatControl; import baritone.command.BaritoneChatControl;
import baritone.cache.WorldScanner; import baritone.cache.WorldScanner;
import baritone.command.CommandSystem; import baritone.command.CommandSystem;
import baritone.utils.player.PrimaryPlayerContext;
import baritone.utils.schematic.SchematicSystem; import baritone.utils.schematic.SchematicSystem;
import java.util.Collections; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@@ -37,11 +41,9 @@ import java.util.List;
public final class BaritoneProvider implements IBaritoneProvider { public final class BaritoneProvider implements IBaritoneProvider {
private final Baritone primary; private final Baritone primary;
private final List<IBaritone> all;
{ {
this.primary = new Baritone(); this.primary = new Baritone(PrimaryPlayerContext.INSTANCE);
this.all = Collections.singletonList(this.primary);
// Setup chat control, just for the primary instance // Setup chat control, just for the primary instance
new BaritoneChatControl(this.primary); new BaritoneChatControl(this.primary);
@@ -54,7 +56,12 @@ public final class BaritoneProvider implements IBaritoneProvider {
@Override @Override
public List<IBaritone> getAllBaritones() { public List<IBaritone> getAllBaritones() {
return all; List<IBaritone> baritones = new ArrayList<>();
baritones.add(getPrimaryBaritone());
for (IBaritoneUser ibu : UserManager.INSTANCE.users()) {
baritones.add(ibu.getBaritone());
}
return baritones;
} }
@Override @Override
@@ -62,6 +69,11 @@ public final class BaritoneProvider implements IBaritoneProvider {
return WorldScanner.INSTANCE; return WorldScanner.INSTANCE;
} }
@Override
public IUserManager getUserManager() {
return UserManager.INSTANCE;
}
@Override @Override
public ICommandSystem getCommandSystem() { public ICommandSystem getCommandSystem() {
return CommandSystem.INSTANCE; return CommandSystem.INSTANCE;
@@ -32,6 +32,7 @@ import net.minecraft.block.BlockBed;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet; import net.minecraft.network.Packet;
import net.minecraft.network.play.client.CPacketClickWindow;
import net.minecraft.network.play.client.CPacketCloseWindow; import net.minecraft.network.play.client.CPacketCloseWindow;
import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock; import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock;
import net.minecraft.network.play.server.SPacketCloseWindow; import net.minecraft.network.play.server.SPacketCloseWindow;
@@ -117,6 +118,11 @@ public final class MemoryBehavior extends Behavior {
if (p instanceof CPacketCloseWindow) { if (p instanceof CPacketCloseWindow) {
getCurrent().save(); getCurrent().save();
} }
if (p instanceof CPacketClickWindow) {
CPacketClickWindow c = event.cast();
System.out.println("CLICK " + c.getWindowId() + " " + c.getSlotId() + " " + c.getUsedButton() + " " + c.getClickType());
}
} }
} }
@@ -154,9 +160,21 @@ public final class MemoryBehavior extends Behavior {
if (p instanceof SPacketCloseWindow) { if (p instanceof SPacketCloseWindow) {
getCurrent().save(); getCurrent().save();
} }
// apparently doesn't happen
/*if (p instanceof SPacketWindowItems) {
SPacketWindowItems meme = (SPacketWindowItems) p;
if (meme.getWindowId() == ctx.player().openContainer.windowId && enderChestWindowId != null && meme.getWindowId() == enderChestWindowId) {
System.out.println("RECEIVED GUARANTEED ECHEST CONTENTS" + meme.getItemStacks());
}
}*/
} }
} }
public boolean eChestOpen() {
return enderChestWindowId != null && ctx.player().openContainer.windowId == enderChestWindowId;
}
@Override @Override
public void onBlockInteract(BlockInteractEvent event) { public void onBlockInteract(BlockInteractEvent event) {
if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(ctx, event.getPos()) instanceof BlockBed) { if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(ctx, event.getPos()) instanceof BlockBed) {
@@ -0,0 +1,110 @@
/*
* 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.IBaritone;
import baritone.api.bot.IBaritoneUser;
import baritone.api.bot.IUserManager;
import baritone.api.utils.IPlayerController;
import baritone.bot.spec.BotWorld;
import baritone.bot.spec.EntityBot;
import com.mojang.authlib.GameProfile;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.INetHandlerPlayClient;
import net.minecraft.util.Session;
/**
* Implementation of {@link IBaritoneUser}
*
* @author Brady
* @since 11/6/2018
*/
public class BaritoneUser implements IBaritoneUser {
private final UserManager manager;
private final NetworkManager networkManager;
private final Session session;
private GameProfile profile;
private INetHandlerPlayClient netHandlerPlayClient;
private BotWorld world;
private EntityBot player;
private IPlayerController playerController;
private final Baritone baritone;
BaritoneUser(UserManager manager, NetworkManager networkManager, Session session) {
this.manager = manager;
this.networkManager = networkManager;
this.session = session;
this.baritone = new Baritone(new BotPlayerContext(this));
}
public void onLoginSuccess(GameProfile profile, INetHandlerPlayClient netHandlerPlayClient) {
this.profile = profile;
this.netHandlerPlayClient = netHandlerPlayClient;
}
public void onWorldLoad(BotWorld world, EntityBot player, IPlayerController playerController) {
this.world = world;
this.player = player;
this.playerController = playerController;
}
@Override
public NetworkManager getNetworkManager() {
return this.networkManager;
}
@Override
public INetHandlerPlayClient getConnection() {
return this.netHandlerPlayClient;
}
@Override
public EntityBot getEntity() {
return this.player;
}
@Override
public IPlayerController getPlayerController() {
return this.playerController;
}
@Override
public Session getSession() {
return this.session;
}
@Override
public GameProfile getProfile() {
return this.profile;
}
@Override
public UserManager getManager() {
return this.manager;
}
@Override
public IBaritone getBaritone() {
return baritone;
}
}
@@ -0,0 +1,80 @@
/*
* 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.bot.IBaritoneUser;
import baritone.api.cache.IWorldData;
import baritone.api.utils.IPlayerContext;
import baritone.api.utils.IPlayerController;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
public class BotPlayerContext implements IPlayerContext {
/**
* The backing {@link IBaritoneUser}
*/
private final IBaritoneUser bot;
public BotPlayerContext(IBaritoneUser bot) {
this.bot = bot;
}
@Override
public EntityPlayerSP player() {
if (bot.getEntity() == null) {
return null;
}
return bot.getEntity();
}
@Override
public IPlayerController playerController() {
if (bot.getEntity() == null) {
return null;
}
return bot.getPlayerController();
}
@Override
public World world() {
if (bot.getEntity() == null) {
return null;
}
return bot.getEntity().world;
}
@Override
public IWorldData worldData() {
return bot.getBaritone().getWorldProvider().getCurrentWorld();
}
@Override
public RayTraceResult objectMouseOver() {
Entity entity = this.bot.getEntity();
if (entity != null) {
double blockReachDistance = this.bot.getPlayerController().getBlockReachDistance();
return entity.rayTrace(blockReachDistance, 1.0F);
}
return null;
}
}
@@ -0,0 +1,66 @@
/*
* 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.spec.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 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());
}
}
+164
View File
@@ -0,0 +1,164 @@
/*
* 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.bot.connect.ConnectionResult;
import baritone.bot.handler.BotNetHandlerLoginClient;
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 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 final class UserManager implements IUserManager, Helper {
public static final UserManager INSTANCE = new UserManager();
private final List<IBaritoneUser> users = new CopyOnWriteArrayList<>();
private final BotWorldProvider worldProvider;
private UserManager() {
// Setup an event listener that automatically disconnects bots when we're not in-game
BaritoneAPI.getProvider().getPrimaryBaritone().getGameEventHandler().registerEventListener(new AbstractGameEventListener() {
@Override
public final void onTick(TickEvent event) {
if (event.getState() == EventState.PRE) {
if (event.getType() == TickEvent.Type.OUT)
UserManager.this.users.forEach(UserManager.this::disconnect);
UserManager.this.worldProvider.tick();
}
}
});
this.worldProvider = new BotWorldProvider();
}
/**
* 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) {
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, ServerAddress.fromString(data.serverIP));
}
/**
* Connects a new user with the specified {@link Session} to the specified server.
* <p>
* Hi Mickey :)
*
* @param session The user session
* @param address The address of the server to connect to
* @return The result of the attempted connection
*/
private IConnectionResult connect0(Session session, ServerAddress address) {
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);
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) {
return ConnectionResult.failed(CONNECTION_FAILED);
}
}
/**
* Notifies the manager of an {@link IBaritoneUser} disconnect, and
* removes the {@link IBaritoneUser} from the list of users.
*
* @param user The user that disconnected
* @param state The connection state at the time of disconnect
*/
public final void notifyDisconnect(IBaritoneUser user, EnumConnectionState state) {
this.users.remove(user);
}
/**
* @return The bot world provider
*/
public final BotWorldProvider getWorldProvider() {
return this.worldProvider;
}
@Override
public final void disconnect(IBaritoneUser user) {
// It's probably fine to pass null to this, because the handlers aren't doing anything with it
// noinspection ConstantConditions
user.getNetworkManager().closeChannel(null);
this.users.remove(user);
}
@Override
public final List<IBaritoneUser> users() {
return Collections.unmodifiableList(this.users);
}
}
@@ -0,0 +1,87 @@
/*
* 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);
}
}
@@ -0,0 +1,118 @@
/*
* 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 com.mojang.authlib.GameProfile;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.exceptions.AuthenticationUnavailableException;
import com.mojang.authlib.exceptions.InvalidCredentialsException;
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.client.CPacketEncryptionResponse;
import net.minecraft.network.login.server.SPacketEncryptionRequest;
import net.minecraft.network.login.server.SPacketLoginSuccess;
import net.minecraft.util.CryptManager;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import javax.annotation.Nonnull;
import javax.crypto.SecretKey;
import java.math.BigInteger;
import java.security.PublicKey;
/**
* Handles the login stage when connecting to a server.
*
* @author Brady
* @since 10/29/2018
*/
public 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 Minecraft mc;
/**
* The bot of this connection
*/
private final BaritoneUser user;
public BotNetHandlerLoginClient(NetworkManager networkManager, BaritoneUser user) {
super(networkManager, Minecraft.getMinecraft(), null);
this.networkManager = networkManager;
this.mc = Minecraft.getMinecraft();
this.user = user;
}
@Override
public void handleEncryptionRequest(SPacketEncryptionRequest packetIn) {
SecretKey secretkey = CryptManager.createNewSharedKey();
PublicKey publicKey = packetIn.getPublicKey();
// Setup joinServer payload info
GameProfile profile = this.user.getSession().getProfile();
String authenticationToken = this.user.getSession().getToken();
String serverId = new BigInteger(CryptManager.getServerIdHash(packetIn.getServerId(), publicKey, secretkey)).toString(16);
if (this.mc.getCurrentServerData() != null && this.mc.getCurrentServerData().isOnLAN()) {
try {
this.mc.getSessionService().joinServer(profile, authenticationToken, serverId);
} catch (AuthenticationException e) {
// Couldn't connect to auth servers but will continue to join LAN
}
} else {
try {
this.mc.getSessionService().joinServer(profile, authenticationToken, serverId);
} catch (AuthenticationUnavailableException e) {
this.networkManager.closeChannel(new TextComponentTranslation("disconnect.loginFailedInfo", new TextComponentTranslation("disconnect.loginFailedInfo.serversUnavailable")));
return;
} catch (InvalidCredentialsException e) {
this.networkManager.closeChannel(new TextComponentTranslation("disconnect.loginFailedInfo", new TextComponentTranslation("disconnect.loginFailedInfo.invalidSession")));
return;
} catch (AuthenticationException e) {
this.networkManager.closeChannel(new TextComponentTranslation("disconnect.loginFailedInfo", e.getMessage()));
return;
}
}
// noinspection unchecked
this.networkManager.sendPacket(new CPacketEncryptionResponse(secretkey, publicKey, packetIn.getVerifyToken()),
future -> BotNetHandlerLoginClient.this.networkManager.enableEncryption(secretkey));
}
@Override
public void handleLoginSuccess(SPacketLoginSuccess packetIn) {
this.networkManager.setConnectionState(EnumConnectionState.PLAY);
this.networkManager.setNetHandler(new BotNetHandlerPlayClient(this.networkManager, this.user, Minecraft.getMinecraft(), 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().notifyDisconnect(this.user, EnumConnectionState.LOGIN);
}
}
@@ -0,0 +1,706 @@
/*
* 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.spec.BotPlayerController;
import baritone.bot.spec.BotWorld;
import baritone.bot.spec.EntityBot;
import com.mojang.authlib.GameProfile;
import io.netty.buffer.Unpooled;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.ClientAdvancementManager;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.util.RecipeBookClient;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.entity.player.PlayerCapabilities;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.PacketThreadUtil;
import net.minecraft.network.play.INetHandlerPlayClient;
import net.minecraft.network.play.client.*;
import net.minecraft.network.play.server.*;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.stats.StatisticsManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumHandSide;
import net.minecraft.util.IThreadListener;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.Explosion;
import net.minecraft.world.chunk.Chunk;
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
/**
* This class would effectively operate the same if we directly implemented {@link INetHandlerPlayClient},
* however, the {@link EntityPlayerSP} constructor requires an actual implementation of
* {@link NetHandlerPlayClient} in order to access the {@link GameProfile}.
*
* @author Brady
* @since 10/22/2018
*/
public class BotNetHandlerPlayClient extends NetHandlerPlayClient {
/**
* The {@link NetworkManager} that is managing the connection with the server.
*/
private final NetworkManager networkManager;
/**
* This is the {@link Minecraft} game instance, however, to prevent unwanted references
* to the game instance fields, we refer to it as a {@link IThreadListener}.
*/
private final IThreadListener client;
/**
* The bot of this connection
*/
private final BaritoneUser user;
/**
* The bot entity
*/
private EntityBot player;
/**
* The current world.
*/
private BotWorld world;
/**
* The current player controller
*/
private BotPlayerController playerController;
public BotNetHandlerPlayClient(NetworkManager networkManager, BaritoneUser user, Minecraft 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, this);
}
@Override
public void handleSpawnObject(@Nonnull SPacketSpawnObject packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleSpawnExperienceOrb(@Nonnull SPacketSpawnExperienceOrb packetIn) { /* We will want to know this if we want Tenor to collect XP */ }
@Override
public void handleSpawnGlobalEntity(@Nonnull SPacketSpawnGlobalEntity packetIn) { /* Only lightning bolts, this may change in the future */ }
@Override
public void handleSpawnMob(@Nonnull SPacketSpawnMob packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleScoreboardObjective(@Nonnull SPacketScoreboardObjective packetIn) {}
@Override
public void handleSpawnPainting(@Nonnull SPacketSpawnPainting packetIn) {}
@Override
public void handleSpawnPlayer(@Nonnull SPacketSpawnPlayer packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleAnimation(@Nonnull SPacketAnimation packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = this.world.getEntityByID(packetIn.getEntityID());
if (entity != null) {
switch (packetIn.getAnimationType()) {
case 0: {
((EntityLivingBase) entity).swingArm(EnumHand.MAIN_HAND);
break;
}
case 1: {
entity.performHurtAnimation();
break;
}
case 2: {
((EntityPlayer) entity).wakeUpPlayer(false, false, false);
break;
}
case 3: {
((EntityLivingBase) entity).swingArm(EnumHand.OFF_HAND);
break;
}
}
}
}
@Override
public void handleStatistics(@Nonnull SPacketStatistics packetIn) { /* Lol global bot stats when?? */ }
@Override
public void handleRecipeBook(@Nonnull SPacketRecipeBook packetIn) {}
@Override
public void handleBlockBreakAnim(@Nonnull SPacketBlockBreakAnim packetIn) {}
@Override
public void handleSignEditorOpen(@Nonnull SPacketSignEditorOpen packetIn) {}
@Override
public void handleUpdateTileEntity(@Nonnull SPacketUpdateTileEntity packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleBlockAction(@Nonnull SPacketBlockAction packetIn) {}
@Override
public void handleBlockChange(@Nonnull SPacketBlockChange packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.world.setBlockState(packetIn.getBlockPosition(), packetIn.getBlockState());
}
@Override
public void handleChat(@Nonnull SPacketChat packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleTabComplete(@Nonnull SPacketTabComplete packetIn) {}
@Override
public void handleMultiBlockChange(@Nonnull SPacketMultiBlockChange packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
for (SPacketMultiBlockChange.BlockUpdateData data : packetIn.getChangedBlocks()) {
this.world.setBlockState(data.getPos(), data.getBlockState());
}
}
@Override
public void handleMaps(@Nonnull SPacketMaps packetIn) {}
@Override
public void handleConfirmTransaction(@Nonnull SPacketConfirmTransaction packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleCloseWindow(@Nonnull SPacketCloseWindow packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.player.closeScreenAndDropStack();
}
@Override
public void handleWindowItems(@Nonnull SPacketWindowItems packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
(packetIn.getWindowId() == 0 ? this.player.inventoryContainer : this.player.openContainer).setAll(packetIn.getItemStacks());
}
@Override
public void handleOpenWindow(@Nonnull SPacketOpenWindow packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleWindowProperty(@Nonnull SPacketWindowProperty packetIn) {}
@Override
public void handleSetSlot(@Nonnull SPacketSetSlot packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
ItemStack stack = packetIn.getStack();
int slot = packetIn.getSlot();
switch (packetIn.getWindowId()) {
case -1: {
this.player.inventory.setItemStack(stack);
break;
}
case -2: {
this.player.inventory.setInventorySlotContents(slot, stack);
break;
}
default: {
if (packetIn.getWindowId() == 0 && packetIn.getSlot() >= 36 && slot < 45) {
this.player.inventoryContainer.putStackInSlot(slot, stack);
} else if (packetIn.getWindowId() == this.player.openContainer.windowId && packetIn.getWindowId() != 0) {
this.player.openContainer.putStackInSlot(slot, stack);
}
}
}
}
@Override
public void handleCustomPayload(@Nonnull SPacketCustomPayload packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleDisconnect(@Nonnull SPacketDisconnect packetIn) {
this.networkManager.closeChannel(packetIn.getReason());
}
@Override
public void handleUseBed(@Nonnull SPacketUseBed packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityStatus(@Nonnull SPacketEntityStatus packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityAttach(@Nonnull SPacketEntityAttach packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleSetPassengers(@Nonnull SPacketSetPassengers packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleExplosion(@Nonnull SPacketExplosion packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
// noinspection ConstantConditions
new Explosion(this.world, null, packetIn.getX(), packetIn.getY(), packetIn.getZ(), packetIn.getStrength(), packetIn.getAffectedBlockPositions()).doExplosionB(true);
this.player.motionX += (double) packetIn.getMotionX();
this.player.motionY += (double) packetIn.getMotionY();
this.player.motionZ += (double) packetIn.getMotionZ();
}
@Override
public void handleChangeGameState(@Nonnull SPacketChangeGameState packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleKeepAlive(@Nonnull SPacketKeepAlive packetIn) {
this.networkManager.sendPacket(new CPacketKeepAlive(packetIn.getId()));
}
@Override
public void handleChunkData(@Nonnull SPacketChunkData packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (packetIn.isFullChunk()) {
this.world.doPreChunk(packetIn.getChunkX(), packetIn.getChunkZ(), true);
}
Chunk chunk = this.world.getChunk(packetIn.getChunkX(), packetIn.getChunkZ());
chunk.read(packetIn.getReadBuffer(), packetIn.getExtractedSize(), packetIn.isFullChunk());
for (NBTTagCompound tag : packetIn.getTileEntityTags()) {
BlockPos pos = new BlockPos(tag.getInteger("x"), tag.getInteger("y"), tag.getInteger("z"));
TileEntity tileEntity = this.world.getTileEntity(pos);
if (tileEntity != null) {
tileEntity.readFromNBT(tag);
}
}
}
@Override
public void processChunkUnload(@Nonnull SPacketUnloadChunk packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
// TODO Unload chunks
}
@Override
public void handleEffect(@Nonnull SPacketEffect packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleJoinGame(@Nonnull SPacketJoinGame packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.playerController = new BotPlayerController(this.user);
this.world = this.user.getManager().getWorldProvider().getWorld(packetIn.getDimension());
this.player = new EntityBot(this.user, (Minecraft) this.client, this.world, this, new StatisticsManager(), new RecipeBookClient());
this.user.onWorldLoad(this.world, this.player, this.playerController);
this.player.preparePlayerToSpawn();
this.world.spawnEntity(this.player);
this.player.setEntityId(packetIn.getPlayerId());
this.player.dimension = packetIn.getDimension();
this.playerController.setGameType(packetIn.getGameType());
packetIn.getGameType().configurePlayerCapabilities(this.player.capabilities);
this.networkManager.sendPacket(new CPacketClientSettings("en_us", 8, EntityPlayer.EnumChatVisibility.FULL, true, 0, EnumHandSide.RIGHT));
this.networkManager.sendPacket(new CPacketCustomPayload("MC|Brand", new PacketBuffer(Unpooled.buffer()).writeString("vanilla")));
this.world.registerBot(packetIn.getPlayerId(), this.player);
Helper.HELPER.logDirect("Initialized Player and World");
}
@Override
public void handleEntityMovement(@Nonnull SPacketEntity packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handlePlayerPosLook(@Nonnull SPacketPlayerPosLook packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
EntityPlayer player = this.player;
double d0 = packetIn.getX();
double d1 = packetIn.getY();
double d2 = packetIn.getZ();
float f = packetIn.getYaw();
float f1 = packetIn.getPitch();
if (packetIn.getFlags().contains(SPacketPlayerPosLook.EnumFlags.X)) {
d0 += player.posX;
} else {
player.motionX = 0.0D;
}
if (packetIn.getFlags().contains(SPacketPlayerPosLook.EnumFlags.Y)) {
d1 += player.posY;
} else {
player.motionY = 0.0D;
}
if (packetIn.getFlags().contains(SPacketPlayerPosLook.EnumFlags.Z)) {
d2 += player.posZ;
} else {
player.motionZ = 0.0D;
}
if (packetIn.getFlags().contains(SPacketPlayerPosLook.EnumFlags.X_ROT)) {
f1 += player.rotationPitch;
}
if (packetIn.getFlags().contains(SPacketPlayerPosLook.EnumFlags.Y_ROT)) {
f += player.rotationYaw;
}
player.setPositionAndRotation(d0, d1, d2, f, f1);
this.networkManager.sendPacket(new CPacketConfirmTeleport(packetIn.getTeleportId()));
this.networkManager.sendPacket(new CPacketPlayer.PositionRotation(player.posX, player.getEntityBoundingBox().minY, player.posZ, player.rotationYaw, player.rotationPitch, false));
this.player.prevPosX = this.player.posX;
this.player.prevPosY = this.player.posY;
this.player.prevPosZ = this.player.posZ;
}
@Override
public void handleParticles(@Nonnull SPacketParticles packetIn) {}
@Override
public void handlePlayerAbilities(@Nonnull SPacketPlayerAbilities packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
PlayerCapabilities c = this.player.capabilities;
c.disableDamage = packetIn.isInvulnerable();
c.isFlying = packetIn.isFlying();
c.allowFlying = packetIn.isAllowFlying();
c.isCreativeMode = packetIn.isCreativeMode();
c.setFlySpeed(packetIn.getFlySpeed());
c.setPlayerWalkSpeed(packetIn.getWalkSpeed());
}
@Override
public void handlePlayerListItem(@Nonnull SPacketPlayerListItem packetIn) {
// okay now this is awesome
super.handlePlayerListItem(packetIn);
}
@Override
public void handleDestroyEntities(@Nonnull SPacketDestroyEntities packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
for (int i = 0; i < packetIn.getEntityIDs().length; ++i) {
this.world.removeEntityFromWorld(packetIn.getEntityIDs()[i]);
}
}
@Override
public void handleRemoveEntityEffect(@Nonnull SPacketRemoveEntityEffect packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = packetIn.getEntity(this.world);
if (entity instanceof EntityLivingBase) {
((EntityLivingBase) entity).removeActivePotionEffect(packetIn.getPotion());
}
}
@Override
public void handleRespawn(@Nonnull SPacketRespawn packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (packetIn.getDimensionID() != this.player.dimension) {
this.world.removeEntity(this.player);
this.world = this.user.getManager().getWorldProvider().getWorld(packetIn.getDimensionID());
}
EntityBot prev = this.player;
this.player = new EntityBot(this.user, (Minecraft) 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.world.spawnEntity(this.player);
this.player.setEntityId(prev.getEntityId());
this.player.dimension = packetIn.getDimensionID();
this.player.setServerBrand(prev.getServerBrand());
this.playerController.setGameType(packetIn.getGameType());
}
@Override
public void handleEntityHeadLook(@Nonnull SPacketEntityHeadLook packetIn) {}
@Override
public void handleHeldItemChange(@Nonnull SPacketHeldItemChange packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (InventoryPlayer.isHotbar(packetIn.getHeldItemHotbarIndex())) {
this.player.inventory.currentItem = packetIn.getHeldItemHotbarIndex();
}
}
@Override
public void handleDisplayObjective(@Nonnull SPacketDisplayObjective packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityMetadata(@Nonnull SPacketEntityMetadata packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = this.world.getEntityByID(packetIn.getEntityId());
if (entity != null && packetIn.getDataManagerEntries() != null) {
entity.getDataManager().setEntryValues(packetIn.getDataManagerEntries());
}
}
@Override
public void handleEntityVelocity(@Nonnull SPacketEntityVelocity packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = this.world.getEntityByID(packetIn.getEntityID());
if (entity != null) {
entity.setVelocity(
(double) packetIn.getMotionX() / 8000.0D,
(double) packetIn.getMotionY() / 8000.0D,
(double) packetIn.getMotionZ() / 8000.0D
);
}
}
@Override
public void handleEntityEquipment(@Nonnull SPacketEntityEquipment packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = this.world.getEntityByID(packetIn.getEntityID());
if (entity != null) {
entity.setItemStackToSlot(packetIn.getEquipmentSlot(), packetIn.getItemStack());
}
}
@Override
public void handleSetExperience(@Nonnull SPacketSetExperience packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.player.setXPStats(packetIn.getExperienceBar(), packetIn.getTotalExperience(), packetIn.getLevel());
}
@Override
public void handleUpdateHealth(@Nonnull SPacketUpdateHealth packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.player.setPlayerSPHealth(packetIn.getHealth());
this.player.getFoodStats().setFoodLevel(packetIn.getFoodLevel());
this.player.getFoodStats().setFoodSaturationLevel(packetIn.getSaturationLevel());
}
@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) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.world.setTotalWorldTime(packetIn.getTotalWorldTime());
this.world.setWorldTime(packetIn.getWorldTime());
// TODO: Calculate World TPS
}
@Override
public void handleSoundEffect(@Nonnull SPacketSoundEffect packetIn) {}
@Override
public void handleCustomSound(@Nonnull SPacketCustomSound packetIn) {}
@Override
public void handleCollectItem(@Nonnull SPacketCollectItem packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityTeleport(@Nonnull SPacketEntityTeleport packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityProperties(@Nonnull SPacketEntityProperties packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityEffect(@Nonnull SPacketEntityEffect packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = this.world.getEntityByID(packetIn.getEntityId());
if (entity instanceof EntityLivingBase) {
Potion potion = Potion.getPotionById(packetIn.getEffectId());
if (potion != null) {
PotionEffect effect = new PotionEffect(potion, packetIn.getDuration(), packetIn.getAmplifier(), packetIn.getIsAmbient(), packetIn.doesShowParticles());
effect.setPotionDurationMax(packetIn.isMaxDuration());
((EntityLivingBase) entity).addPotionEffect(effect);
}
}
}
@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));
}
}
}
@Override
public void handleServerDifficulty(@Nonnull SPacketServerDifficulty packetIn) {}
@Override
public void handleCamera(SPacketCamera packetIn) {}
@Override
public void handleWorldBorder(@Nonnull SPacketWorldBorder packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
packetIn.apply(this.world.getWorldBorder());
}
@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) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (packetIn.getTicks() == 0) { // There is no cooldown
this.player.getCooldownTracker().removeCooldown(packetIn.getItem());
} else {
this.player.getCooldownTracker().setCooldown(packetIn.getItem(), packetIn.getTicks());
}
}
@Override
public void handleMoveVehicle(@Nonnull SPacketMoveVehicle packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
/* Atm Baritone doesn't even work on vehicles that well at all, so this is a major TODO */
}
@Override
public void handleAdvancementInfo(@Nonnull SPacketAdvancementInfo packetIn) {}
@Override
public void handleSelectAdvancementsTab(@Nonnull SPacketSelectAdvancementsTab packetIn) { /* Lol global bot achievements when? */ }
@Override
public void func_194307_a(@Nonnull SPacketPlaceGhostRecipe p_194307_1_) {}
@Override
public void onDisconnect(@Nonnull ITextComponent reason) {
// TODO Maybe more world unloadinde
this.world.removeEntity(this.player);
this.user.getManager().notifyDisconnect(this.user, EnumConnectionState.PLAY);
}
@Nonnull
@Override
public ClientAdvancementManager getAdvancementManager() {
throw new UnsupportedOperationException("This method shouldn't have been called; That is unepic!");
}
public EntityBot player() {
return player;
}
public BotWorld world() {
return world;
}
}
@@ -0,0 +1,260 @@
/*
* 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.spec;
import baritone.api.bot.IBaritoneUser;
import baritone.api.utils.IPlayerController;
import net.minecraft.block.Block;
import net.minecraft.block.BlockCommandBlock;
import net.minecraft.block.BlockStructure;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.ItemStack;
import net.minecraft.network.play.client.CPacketClickWindow;
import net.minecraft.network.play.client.CPacketHeldItemChange;
import net.minecraft.network.play.client.CPacketPlayerDigging;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameType;
import net.minecraft.world.World;
/**
* @author Brady
* @since 11/14/2018
*/
public class BotPlayerController implements IPlayerController {
private final IBaritoneUser user;
private GameType gameType;
private BlockPos currentBlock;
private ItemStack currentHittingItem;
private boolean hittingBlock;
private float blockDamage;
private int blockHitDelay;
private int heldItemServer;
public BotPlayerController(IBaritoneUser user) {
this.user = user;
this.currentHittingItem = ItemStack.EMPTY;
}
@Override
public boolean onPlayerDamageBlock(BlockPos pos, EnumFacing side) {
this.syncHeldItem();
EntityPlayerSP player = this.user.getEntity();
World world = player.world;
if (this.blockHitDelay > 0) {
this.blockHitDelay--;
return true;
}
if (!this.isHittingPosition(pos)) {
return this.clickBlock(pos, side);
}
IBlockState state = world.getBlockState(pos);
if (state.getMaterial() == Material.AIR) {
this.hittingBlock = false;
return false;
}
this.blockDamage += state.getPlayerRelativeBlockHardness(player, world, pos);
if (this.blockDamage >= 1.0F) {
this.hittingBlock = false;
this.blockDamage = 0.0F;
this.blockHitDelay = 5;
player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.STOP_DESTROY_BLOCK, pos, side));
this.handleBreak(pos);
}
world.sendBlockBreakProgress(player.getEntityId(), this.currentBlock, (int) (this.blockDamage * 10.0F) - 1);
return true;
}
@Override
public void resetBlockRemoving() {
if (this.hittingBlock) {
this.hittingBlock = false;
this.blockDamage = 0.0F;
this.user.getEntity().resetCooldown();
this.user.getEntity().connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.ABORT_DESTROY_BLOCK, this.currentBlock, EnumFacing.DOWN));
}
}
@Override
public ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player) {
short transactionID = player.openContainer.getNextTransactionID(player.inventory);
ItemStack stack = player.openContainer.slotClick(slotId, mouseButton, type, player);
this.user.getEntity().connection.sendPacket(new CPacketClickWindow(windowId, slotId, mouseButton, type, stack, transactionID));
return stack;
}
@Override
public void setGameType(GameType type) {
this.gameType = type;
this.gameType.configurePlayerCapabilities(this.user.getEntity().capabilities);
}
@Override
public GameType getGameType() {
return this.gameType;
}
@Override
public boolean clickBlock(BlockPos pos, EnumFacing side) {
EntityPlayerSP player = this.user.getEntity();
World world = player.world;
if (!canBreak(player, pos)) {
return false;
}
if (!this.hittingBlock || !this.isHittingPosition(pos)) {
if (this.hittingBlock) {
player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.ABORT_DESTROY_BLOCK, this.currentBlock, side));
}
IBlockState state = world.getBlockState(pos);
player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.START_DESTROY_BLOCK, pos, side));
if (state.getMaterial() != Material.AIR) {
if (this.blockDamage == 0.0F) {
state.getBlock().onBlockClicked(world, pos, player);
}
if (state.getPlayerRelativeBlockHardness(player, player.world, pos) >= 1.0F) {
this.handleBreak(pos);
}
} else {
this.hittingBlock = true;
this.currentBlock = pos;
this.blockDamage = 0.0F;
this.currentHittingItem = player.getHeldItemMainhand();
world.sendBlockBreakProgress(player.getEntityId(), this.currentBlock, (int) (this.blockDamage * 10.0F) - 1);
}
}
return true;
}
private void handleBreak(BlockPos pos) {
EntityPlayerSP player = this.user.getEntity();
World world = player.world;
IBlockState state = world.getBlockState(pos);
Block block = state.getBlock();
if ((block instanceof BlockCommandBlock || block instanceof BlockStructure) && !player.canUseCommandBlock()) {
return;
}
if (state.getMaterial() == Material.AIR) {
return;
}
block.onBlockHarvested(world, pos, state, player);
if (world.setBlockState(pos, Blocks.AIR.getDefaultState(), 11)) {
block.onPlayerDestroy(world, pos, state);
}
this.currentBlock = new BlockPos(this.currentBlock.getX(), -1, this.currentBlock.getZ());
ItemStack stack = player.getHeldItemMainhand();
if (!stack.isEmpty()) {
stack.onBlockDestroyed(world, state, pos, player);
if (stack.isEmpty()) {
player.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY);
}
}
}
private boolean canBreak(EntityPlayer player, BlockPos pos) {
if (this.gameType.isCreative() || this.gameType == GameType.SPECTATOR) {
return false;
}
if (!player.world.getWorldBorder().contains(pos)) {
return false;
}
if (this.gameType.hasLimitedInteractions() && !player.isAllowEdit()) {
ItemStack stack = player.getHeldItemMainhand();
return !stack.isEmpty() && stack.canDestroy(player.world.getBlockState(pos).getBlock());
}
return true;
}
private boolean isHittingPosition(BlockPos pos) {
ItemStack stack = this.user.getEntity().getHeldItemMainhand();
boolean itemUnchanged = this.currentHittingItem.isEmpty() && stack.isEmpty();
if (!this.currentHittingItem.isEmpty() && !stack.isEmpty()) {
itemUnchanged = stack.getItem() == this.currentHittingItem.getItem()
&& ItemStack.areItemStackTagsEqual(stack, this.currentHittingItem)
&& (stack.isItemStackDamageable() || stack.getMetadata() == this.currentHittingItem.getMetadata());
}
return pos.equals(this.currentBlock) && itemUnchanged;
}
@Override
public void syncHeldItem() {
int heldItemClient = this.user.getEntity().inventory.currentItem;
if (heldItemClient != this.heldItemServer) {
this.heldItemServer = heldItemClient;
this.user.getEntity().connection.sendPacket(new CPacketHeldItemChange(this.heldItemServer));
}
}
@Override
public boolean hasBrokenBlock() {
return this.currentBlock.getY() == -1;
}
@Override
public EnumActionResult processRightClickBlock(EntityPlayerSP player, World world, BlockPos pos, EnumFacing direction, Vec3d vec, EnumHand hand) {
throw new AbstractMethodError("Lol");
}
@Override
public EnumActionResult processRightClick(EntityPlayerSP player, World world, EnumHand hand) {
throw new AbstractMethodError("Lol");
}
@Override
public void setHittingBlock(boolean hittingBlock) {
this.hittingBlock = hittingBlock;
}
}
@@ -0,0 +1,84 @@
/*
* 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.spec;
import net.minecraft.client.multiplayer.ChunkProviderClient;
import net.minecraft.entity.Entity;
import net.minecraft.profiler.Profiler;
import net.minecraft.world.DimensionType;
import net.minecraft.world.World;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.chunk.IChunkProvider;
import net.minecraft.world.storage.SaveHandlerMP;
import net.minecraft.world.storage.WorldInfo;
import javax.annotation.Nonnull;
/**
* @author Brady
* @since 11/7/2018
*/
public class BotWorld extends World {
private static Profiler BOT_WORLD_PROFILER = new Profiler();
private static int worldNum = 0;
private ChunkProviderClient chunkProviderClient;
public BotWorld(WorldSettings settings, int dimension) {
super(
new SaveHandlerMP(),
new WorldInfo(settings, "BotWorld" + ++worldNum),
DimensionType.getById(dimension).createDimension(),
BOT_WORLD_PROFILER,
true
);
this.provider.setWorld(this);
this.chunkProvider = this.createChunkProvider();
}
@Override
@Nonnull
protected IChunkProvider createChunkProvider() {
return (this.chunkProviderClient = new ChunkProviderClient(this));
}
@Override
protected boolean isChunkLoaded(int x, int z, boolean allowEmpty) {
return allowEmpty || !this.chunkProviderClient.provideChunk(x, z).isEmpty();
}
public void registerBot(int entityID, EntityBot entity) {
this.entitiesById.addKey(entityID, entity);
}
public void removeEntityFromWorld(int entityID) {
Entity entity = this.entitiesById.removeObject(entityID);
if (entity != null) {
this.removeEntity(entity);
}
}
public void doPreChunk(int chunkX, int chunkZ, boolean loadChunk) {
if (loadChunk) {
this.chunkProviderClient.loadChunk(chunkX, chunkZ);
} else {
this.chunkProviderClient.unloadChunk(chunkX, chunkZ);
}
}
}
@@ -0,0 +1,170 @@
/*
* 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.spec;
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.Nullable;
// Some Notes:
// startRiding references the sound manager
// onUpdateWalkingPlayer references the gameSettings autoJump flag
// notifyDataManagerChange references the sound manager
// onLivingUpdate makes a lot of references to mc fields
// - playerController
// - currentScreen
// - gameSettings
// - tutorial
// What needs to be considered
// - The server tells us what our entity id should be, the bot entity should respect this.
/**
* @author Brady
* @since 10/23/2018
*/
@SuppressWarnings("EntityConstructor")
public class EntityBot extends EntityPlayerSP {
private final IBaritoneUser user;
private NetworkPlayerInfo playerInfo;
public EntityBot(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());
}
@Override
public void closeScreenAndDropStack() {
this.inventory.setItemStack(ItemStack.EMPTY);
// EntityPlayer#closeScreen
this.openContainer = this.inventoryContainer;
}
@Override
public void sendStatusMessage(ITextComponent chatComponent, boolean actionBar) {
// TODO: Custom message handling
}
@Override
public void sendMessage(ITextComponent component) {
// TODO: Custom message handling
}
@Override
public void openEditSign(TileEntitySign signTile) {
// TODO: Custom GUI handling
}
@Override
public void displayGuiEditCommandCart(CommandBlockBaseLogic commandBlock) {
// TODO: Custom GUI handling
}
@Override
public void displayGuiCommandBlock(TileEntityCommandBlock commandBlock) {
// TODO: Custom GUI handling
}
@Override
public void openEditStructure(TileEntityStructure structure) {
// TODO: Custom GUI handling
}
@Override
public void openBook(ItemStack stack, EnumHand hand) {
// TODO: Custom GUI handling
}
@Override
public void displayGUIChest(IInventory chestInventory) {
// TODO: Custom GUI handling
}
@Override
public void openGuiHorseInventory(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(Entity entityHit) {
// Don't render
}
@Override
public void onEnchantmentCritical(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;
}
}
+1 -3
View File
@@ -184,9 +184,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
int distZ = ((region.getZ() << 9) + 256) - pruneCenter.getZ(); int distZ = ((region.getZ() << 9) + 256) - pruneCenter.getZ();
double dist = Math.sqrt(distX * distX + distZ * distZ); double dist = Math.sqrt(distX * distX + distZ * distZ);
if (dist > 1024) { if (dist > 1024) {
if (!Baritone.settings().censorCoordinates.value) { logDebug("Deleting cached region " + region.getX() + "," + region.getZ() + " from ram");
logDebug("Deleting cached region " + region.getX() + "," + region.getZ() + " from ram");
}
cachedRegions.remove(getRegionID(region.getX(), region.getZ())); cachedRegions.remove(getRegionID(region.getX(), region.getZ()));
} }
} }
@@ -22,6 +22,7 @@ import baritone.api.event.events.*;
import baritone.api.event.events.type.EventState; import baritone.api.event.events.type.EventState;
import baritone.api.event.listener.IEventBus; import baritone.api.event.listener.IEventBus;
import baritone.api.event.listener.IGameEventListener; import baritone.api.event.listener.IGameEventListener;
import baritone.bot.UserManager;
import baritone.api.utils.Helper; import baritone.api.utils.Helper;
import baritone.cache.WorldProvider; import baritone.cache.WorldProvider;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
@@ -29,6 +30,7 @@ import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.CopyOnWriteArrayList;
/** /**
@@ -66,6 +68,9 @@ public final class GameEventHandler implements IEventBus, Helper {
@Override @Override
public final void onSendChatMessage(ChatEvent event) { public final void onSendChatMessage(ChatEvent event) {
// Ensure UserManager is created to prevent a ConcurrentModificationException
Objects.requireNonNull(UserManager.INSTANCE);
listeners.forEach(l -> l.onSendChatMessage(event)); listeners.forEach(l -> l.onSendChatMessage(event));
} }
@@ -54,6 +54,10 @@ public final class PathRenderer implements IRenderer {
public static void render(RenderEvent event, PathingBehavior behavior) { public static void render(RenderEvent event, PathingBehavior behavior) {
float partialTicks = event.getPartialTicks(); float partialTicks = event.getPartialTicks();
Goal goal = behavior.getGoal(); Goal goal = behavior.getGoal();
if (behavior.baritone.getPlayerContext().world() == null) {
return;
}
if (Helper.mc.currentScreen instanceof GuiClick) { if (Helper.mc.currentScreen instanceof GuiClick) {
((GuiClick) Helper.mc.currentScreen).onRender(); ((GuiClick) Helper.mc.currentScreen).onRender();
} }
@@ -17,14 +17,15 @@
package baritone.utils; package baritone.utils;
import baritone.api.utils.IInputOverrideHandler;
import baritone.api.utils.input.Input; import baritone.api.utils.input.Input;
import net.minecraft.util.MovementInput; import net.minecraft.util.MovementInput;
public class PlayerMovementInput extends MovementInput { public class PlayerMovementInput extends MovementInput {
private final InputOverrideHandler handler; private final IInputOverrideHandler handler;
PlayerMovementInput(InputOverrideHandler handler) { public PlayerMovementInput(IInputOverrideHandler handler) {
this.handler = handler; this.handler = handler;
} }
@@ -68,6 +68,11 @@ public enum PrimaryPlayerController implements IPlayerController, Helper {
return mc.playerController.windowClick(windowId, slotId, mouseButton, type, player); return mc.playerController.windowClick(windowId, slotId, mouseButton, type, player);
} }
@Override
public void setGameType(GameType type) {
mc.playerController.setGameType(type);
}
@Override @Override
public GameType getGameType() { public GameType getGameType() {
return mc.playerController.getCurrentGameType(); return mc.playerController.getCurrentGameType();