Compare commits

..

140 Commits

Author SHA1 Message Date
Brady 9a33c5cd9f Merge branch 'master' into bot-system 2020-01-01 19:23:01 -06:00
Brady adff391e45 Merge branch 'schematic-formats' 2019-12-31 18:25:21 -06:00
Brady 4a05837b01 Requested changes 2019-12-31 17:44:20 -06:00
Leijurv a0014fda12 Merge pull request #1216 from FTC55/master
Fixed a rather obnoxious bug that would require a full restart of the client.
2019-12-31 15:35:01 -08:00
FTC55 04190af340 ...more than I thought. Autoreformatted file x2 2019-12-31 19:45:08 +01:00
FTC55 4b10904b97 Git missed some changes. Autoreformatted files. 2019-12-31 19:43:54 +01:00
FTC55 bbb25acff3 Fixed the bug, merged CancelCommand into ExecutionControlCommands 2019-12-31 19:31:30 +01:00
Brady fcfa022232 Clean up BlockOptionalMeta comment and add behavioral clarification 2019-12-30 02:27:20 -06:00
Brady 220ee30d35 Appease Codacy 2019-12-27 21:28:05 -06:00
Brady 812bc0d8c4 Remove redundant parser layer 2019-12-27 01:14:31 -06:00
Brady d712839c25 Make Schematica respect mapArtMode setting 2019-12-25 01:35:10 -06:00
Brady eee705b371 Schematic Format API support 2019-12-24 17:20:00 -06:00
Brady 77bdf6e444 Fix MapSchematic 2019-12-23 18:05:50 -06:00
Brady 0a858c040c Working 2019-12-19 22:15:14 -06:00
Brady eea5b69b6c Utilize new FillSchematic 2019-12-19 12:03:02 -06:00
Brady 6759917a2f Additional clean up 2019-12-19 11:58:47 -06:00
Brady aa3bd80ab2 Clean ups 2019-12-19 11:40:38 -06:00
Brady ea8d7fb3b9 Improve file extension fallback mechanism 2019-12-18 15:19:58 -06:00
Brady b4ddf38116 Check if state is null 2019-12-18 10:27:34 -06:00
Brady 5c9f028103 Initial sponge support 2019-12-18 10:24:43 -06:00
Leijurv 937d4cc884 whoops 2019-12-13 20:46:12 -08:00
Leijurv 2c3e1f4232 builder stuff, fixes #1059 2019-12-13 20:09:04 -08:00
Leijurv ddc681fe77 build repeat count 2019-11-24 11:11:28 -08:00
Leijurv 2b71b31cfa Merge pull request #1087 from cabaletta/ispassable-crash-fix
Fix isPassable crash
2019-11-10 22:52:29 -08:00
Leijurv ed144e995b apparently this usage of > was an invalid javadoc command lol 2019-11-10 14:04:27 -08:00
Brady 7e3a2d3c0a Create a BlockStateInterface specialized IBlockAccess wrapper 2019-11-05 18:17:10 -06:00
Leijurv 152285043d Update USAGE.md 2019-11-05 11:50:27 -08:00
Leijurv ce52201e45 Merge pull request #1097 from greg904/fix-goto-errmsg
Remove error message when running goto with less than 3 args
2019-10-29 21:33:27 -07:00
Leijurv 45ea776090 Update README.md 2019-10-28 10:47:20 -07:00
Leijurv 2ae16d8bb1 configurable block reach distance 2019-10-26 16:01:08 -07:00
Greg Depoire--Ferrer 23fc6c8b49 Add a space between sentences in error message 2019-10-25 14:49:57 +02:00
Greg Depoire--Ferrer 0db4b193e1 Remove hack, add comment, don't use default when arg is required 2019-10-25 14:49:08 +02:00
Greg Depoire--Ferrer 82d520d808 Don't print invalid type error to stderr 2019-10-25 14:42:36 +02:00
Brady 5201d39adf Retain old method signature 2019-10-24 15:20:23 -05:00
Brady f02c33d95a Fix improper tick count incrementation 2019-10-23 17:47:20 -05:00
Brady 43ab4f7d3b Fix isPassable crash 2019-10-22 15:58:10 -05:00
Leijurv 6341f9fcb4 Merge pull request #1072 from 0-x-2-2/disable-autotest-mob-spawning
Disable harmful mob spawning in Travis auto test.
2019-10-17 12:05:24 -07:00
0x22 66ffd1e0d9 Disable harmful mob spawning in Travis auto test. 2019-10-17 14:35:28 -04:00
Leijurv e65c854e6a Update USAGE.md 2019-10-15 11:25:35 -07:00
Brady 4eca960a4c Specify range in IWorldScanner#repack 2019-10-14 15:45:41 -05:00
Leijurv 69bceb43f8 Update USAGE.md 2019-10-12 13:07:12 -07:00
Leijurv 6a8807b0fa documentation stuff 2019-10-12 10:43:01 -07: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
68 changed files with 3246 additions and 340 deletions
+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)
+1 -1
View File
@@ -19,7 +19,7 @@
![Lines of Code](https://tokei.rs/b1/github/cabaletta/baritone?category=code) ![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 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/) [![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.8%20/%20v1.3.4%20/%20v1.4.1-brightgreen.svg)](https://impactclient.net/) [![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/) [![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) [![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/) [![WWE integration](https://img.shields.io/badge/WWE%20%22integration%22-master%3F-green.svg)](https://wweclient.com/)
+13 -7
View File
@@ -8,11 +8,23 @@ Baritone commands can also by default be typed in the chatbox. However if you ma
To disable direct chat control (with no prefix), turn off the `chatControl` setting. To disable chat control with the `#` prefix, turn off the `prefixControl` setting. In Impact, `.b` cannot be disabled. Be careful that you don't leave yourself with all control methods disabled (if you do, reset your settings by deleting the file `minecraft/baritone/settings.txt` and relaunching). To disable direct chat control (with no prefix), turn off the `chatControl` setting. To disable chat control with the `#` prefix, turn off the `prefixControl` setting. In Impact, `.b` cannot be disabled. Be careful that you don't leave yourself with all control methods disabled (if you do, reset your settings by deleting the file `minecraft/baritone/settings.txt` and relaunching).
# For Baritone 1.2.10+, 1.3.5+, 1.4.2+
Lots of the commands have changed, BUT `#help` is improved vastly (its clickable! commands have tab completion! oh my!).
Try `#help` I promise it won't just send you back here =)
"wtf where is cleararea" -> look at `#help sel`
"wtf where is goto death, goto waypoint" -> look at `#help wp` (a "tag" is like "home" (created automatically on right clicking a bed) or "death" (created automatically on death) or "user" (has to be created manually)). So you might want `#wp save user coolbiome` then, to set the goal `#wp goal coolbiome` then `#path` to path to it. For death, `#wp goal death` (remember stuff is clickable!).
just look at `#help` lmao
# Commands # Commands
**All** of these commands may need a prefix before them, as above ^. **All** of these commands may need a prefix before them, as above ^.
`help` for (rudimentary) help. You can see what it says [here](https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/utils/ExampleBaritoneControl.java#L47). `help`
To toggle a boolean setting, just say its name in chat (for example saying `allowBreak` toggles whether Baritone will consider breaking blocks). For a numeric setting, say its name then the new value (like `primaryTimeoutMS 250`). It's case insensitive. To reset a setting to its default value, say `acceptableThrowawayItems reset`. To reset all settings, say `reset`. To see all settings that have been modified from their default values, say `modified`. To toggle a boolean setting, just say its name in chat (for example saying `allowBreak` toggles whether Baritone will consider breaking blocks). For a numeric setting, say its name then the new value (like `primaryTimeoutMS 250`). It's case insensitive. To reset a setting to its default value, say `acceptableThrowawayItems reset`. To reset all settings, say `reset`. To see all settings that have been modified from their default values, say `modified`.
@@ -38,12 +50,6 @@ Some common examples:
- `version` to get the version of Baritone you're running - `version` to get the version of Baritone you're running
- `damn` daniel - `damn` daniel
New commands:
- `sel` to manage selections
- some others
For the rest of the commands, you can take a look at the code [here](https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/utils/ExampleBaritoneControl.java). For the rest of the commands, you can take a look at the code [here](https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/utils/ExampleBaritoneControl.java).
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/Settings.java">here</a>. If you find HTML easier to read than Javadoc, you can look <a href="https://baritone.leijurv.com/baritone/api/Settings.html#field.detail">here</a>. All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/Settings.java">here</a>. If you find HTML easier to read than Javadoc, you can look <a href="https://baritone.leijurv.com/baritone/api/Settings.html#field.detail">here</a>.
@@ -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,9 +17,11 @@
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;
import baritone.api.schematic.ISchematicSystem;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import java.util.List; import java.util.List;
@@ -68,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.
@@ -82,4 +89,9 @@ public interface IBaritoneProvider {
* @return The {@link ICommandSystem} instance. * @return The {@link ICommandSystem} instance.
*/ */
ICommandSystem getCommandSystem(); ICommandSystem getCommandSystem();
/**
* @return The {@link ISchematicSystem} instance.
*/
ISchematicSystem getSchematicSystem();
} }
+31 -1
View File
@@ -184,6 +184,20 @@ public final class Settings {
Blocks.WALL_SIGN Blocks.WALL_SIGN
))); )));
/**
* A list of blocks to be treated as if they're air.
* <p>
* If a schematic asks for air at a certain position, and that position currently contains a block on this list, it will be treated as correct.
*/
public final Setting<List<Block>> buildIgnoreBlocks = new Setting<>(new ArrayList<>(Arrays.asList(
)));
/**
* If this is true, the builder will treat all non-air blocks as correct. It will only place new blocks.
*/
public final Setting<Boolean> buildIgnoreExisting = new Setting<>(false);
/** /**
* If this setting is true, Baritone will never break a block that is adjacent to an unsupported falling block. * If this setting is true, Baritone will never break a block that is adjacent to an unsupported falling block.
* <p> * <p>
@@ -234,7 +248,7 @@ public final class Settings {
/** /**
* If we overshoot a traverse and end up one block beyond the destination, mark it as successful anyway. * If we overshoot a traverse and end up one block beyond the destination, mark it as successful anyway.
* <p> * <p>
* This helps with speed at >=20m/s * This helps with speed exceeding 20m/s
*/ */
public final Setting<Boolean> overshootTraverse = new Setting<>(true); public final Setting<Boolean> overshootTraverse = new Setting<>(true);
@@ -248,6 +262,11 @@ public final class Settings {
*/ */
public final Setting<Integer> rightClickSpeed = new Setting<>(4); public final Setting<Integer> rightClickSpeed = new Setting<>(4);
/**
* Block reach distance
*/
public final Setting<Float> blockReachDistance = new Setting<>(4.5f);
/** /**
* How many degrees to randomize the pitch and yaw every tick. Set to 0 to disable * How many degrees to randomize the pitch and yaw every tick. Set to 0 to disable
*/ */
@@ -738,6 +757,11 @@ public final class Settings {
*/ */
public final Setting<Vec3i> buildRepeat = new Setting<>(new Vec3i(0, 0, 0)); public final Setting<Vec3i> buildRepeat = new Setting<>(new Vec3i(0, 0, 0));
/**
* How many times to buildrepeat. -1 for infinite.
*/
public final Setting<Integer> buildRepeatCount = new Setting<>(-1);
/** /**
* Allow standing above a block while mining it, in BuilderProcess * Allow standing above a block while mining it, in BuilderProcess
* <p> * <p>
@@ -787,6 +811,12 @@ public final class Settings {
*/ */
public final Setting<Boolean> schematicOrientationZ = new Setting<>(false); public final Setting<Boolean> schematicOrientationZ = new Setting<>(false);
/**
* The fallback used by the build command when no extension is specified. This may be useful if schematics of a
* particular format are used often, and the user does not wish to have to specify the extension with every usage.
*/
public final Setting<String> schematicFallbackExtension = new Setting<>("schematic");
/** /**
* Distance to scan every tick for updates. Expanding this beyond player reach distance (i.e. setting it to 6 or above) * Distance to scan every tick for updates. Expanding this beyond player reach distance (i.e. setting it to 6 or above)
* is only necessary in very large schematics where rescanning the whole thing is costly. * is only necessary in very large schematics where rescanning the whole thing is costly.
@@ -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();
}
-2
View File
@@ -81,6 +81,4 @@ public interface ICachedWorld {
* in a new thread by default. * in a new thread by default.
*/ */
void save(); void save();
} }
+13 -3
View File
@@ -77,10 +77,20 @@ public interface IWorldScanner {
} }
/** /**
* Repacks 40 chunks around the player. * Overload of {@link #repack(IPlayerContext, int)} where the value of the {@code range} parameter is {@code 40}.
* *
* @param ctx The player context for that player. * @param ctx The player, describing the origin
* @return The number of chunks queued for repacking. * @return The amount of chunks successfully queued for repacking
*/ */
int repack(IPlayerContext ctx); int repack(IPlayerContext ctx);
/**
* Queues the chunks in a square formation around the specified player, using the specified
* range, which represents 1/2 the square's dimensions, where the player is in the center.
*
* @param ctx The player, describing the origin
* @param range The range to repack
* @return The amount of chunks successfully queued for repacking
*/
int repack(IPlayerContext ctx, int range);
} }
@@ -38,38 +38,26 @@ public enum RelativeGoal implements IDatatypePost<Goal, BetterBlockPos> {
if (origin == null) { if (origin == null) {
origin = BetterBlockPos.ORIGIN; origin = BetterBlockPos.ORIGIN;
} }
final IArgConsumer consumer = ctx.getConsumer(); final IArgConsumer consumer = ctx.getConsumer();
List<IDatatypePostFunction<Double, Double>> coords = new ArrayList<>(); GoalBlock goalBlock = consumer.peekDatatypePostOrNull(RelativeGoalBlock.INSTANCE, origin);
final IArgConsumer copy = consumer.copy(); // This is a hack and should be fixed in the future probably if (goalBlock != null) {
for (int i = 0; i < 3; i++) { return goalBlock;
if (copy.peekDatatypeOrNull(RelativeCoordinate.INSTANCE) != null) {
coords.add(o -> consumer.getDatatypePost(RelativeCoordinate.INSTANCE, o));
copy.get(); // Consume so we actually decrement the remaining arguments
}
} }
switch (coords.size()) { GoalXZ goalXZ = consumer.peekDatatypePostOrNull(RelativeGoalXZ.INSTANCE, origin);
case 0: if (goalXZ != null) {
return new GoalBlock(origin); return goalXZ;
case 1:
return new GoalYLevel(
MathHelper.floor(coords.get(0).apply((double) origin.y))
);
case 2:
return new GoalXZ(
MathHelper.floor(coords.get(0).apply((double) origin.x)),
MathHelper.floor(coords.get(1).apply((double) origin.z))
);
case 3:
return new GoalBlock(
MathHelper.floor(coords.get(0).apply((double) origin.x)),
MathHelper.floor(coords.get(1).apply((double) origin.y)),
MathHelper.floor(coords.get(2).apply((double) origin.z))
);
default:
throw new IllegalStateException("Unexpected coords size: " + coords.size());
} }
GoalYLevel goalYLevel = consumer.peekDatatypePostOrNull(RelativeGoalYLevel.INSTANCE, origin);
if (goalYLevel != null) {
return goalYLevel;
}
// when the user doesn't input anything, default to the origin
return new GoalBlock(origin);
} }
@Override @Override
@@ -22,4 +22,8 @@ public abstract class CommandErrorMessageException extends CommandException {
protected CommandErrorMessageException(String reason) { protected CommandErrorMessageException(String reason) {
super(reason); super(reason);
} }
protected CommandErrorMessageException(String reason, Throwable cause) {
super(reason, cause);
}
} }
@@ -22,4 +22,8 @@ public abstract class CommandException extends Exception implements ICommandExce
protected CommandException(String reason) { protected CommandException(String reason) {
super(reason); super(reason);
} }
protected CommandException(String reason, Throwable cause) {
super(reason, cause);
}
} }
@@ -23,12 +23,21 @@ public abstract class CommandInvalidArgumentException extends CommandErrorMessag
public final ICommandArgument arg; public final ICommandArgument arg;
protected CommandInvalidArgumentException(ICommandArgument arg, String reason) { protected CommandInvalidArgumentException(ICommandArgument arg, String message) {
super(String.format( super(formatMessage(arg, message));
"Error at argument #%s: %s",
arg.getIndex() == -1 ? "<unknown>" : Integer.toString(arg.getIndex() + 1),
reason
));
this.arg = arg; this.arg = arg;
} }
protected CommandInvalidArgumentException(ICommandArgument arg, String message, Throwable cause) {
super(formatMessage(arg, message), cause);
this.arg = arg;
}
private static String formatMessage(ICommandArgument arg, String message) {
return String.format(
"Error at argument #%s: %s",
arg.getIndex() == -1 ? "<unknown>" : Integer.toString(arg.getIndex() + 1),
message
);
}
} }
@@ -26,7 +26,7 @@ public class CommandInvalidTypeException extends CommandInvalidArgumentException
} }
public CommandInvalidTypeException(ICommandArgument arg, String expected, Throwable cause) { public CommandInvalidTypeException(ICommandArgument arg, String expected, Throwable cause) {
super(arg, String.format("Expected %s.\nMore details: %s", expected, cause.getMessage())); super(arg, String.format("Expected %s", expected), cause);
} }
public CommandInvalidTypeException(ICommandArgument arg, String expected, String got) { public CommandInvalidTypeException(ICommandArgument arg, String expected, String got) {
@@ -34,6 +34,6 @@ public class CommandInvalidTypeException extends CommandInvalidArgumentException
} }
public CommandInvalidTypeException(ICommandArgument arg, String expected, String got, Throwable cause) { public CommandInvalidTypeException(ICommandArgument arg, String expected, String got, Throwable cause) {
super(arg, String.format("Expected %s, but got %s instead.\nMore details: %s", expected, got, cause.getMessage())); super(arg, String.format("Expected %s, but got %s instead", expected, got), cause);
} }
} }
@@ -37,7 +37,7 @@ public class CommandUnhandledException extends RuntimeException implements IComm
@Override @Override
public void handle(ICommand command, List<ICommandArgument> args) { public void handle(ICommand command, List<ICommandArgument> args) {
HELPER.logDirect("An unhandled exception occurred." + HELPER.logDirect("An unhandled exception occurred. " +
"The error is in your game's log, please report this at https://github.com/cabaletta/baritone/issues", "The error is in your game's log, please report this at https://github.com/cabaletta/baritone/issues",
TextFormatting.RED); TextFormatting.RED);
@@ -19,22 +19,20 @@ package baritone.api.event.events;
import baritone.api.event.events.type.EventState; import baritone.api.event.events.type.EventState;
import java.util.function.BiFunction;
public final class TickEvent { public final class TickEvent {
private static int overallTickCount;
private final EventState state; private final EventState state;
private final Type type; private final Type type;
private final int count; private final int count;
private static int overallTickCount; public TickEvent(EventState state, Type type, int count) {
public TickEvent(EventState state, Type type) {
this.state = state; this.state = state;
this.type = type; this.type = type;
this.count = incrementCount(); this.count = count;
}
private static synchronized int incrementCount() {
return overallTickCount++;
} }
public int getCount() { public int getCount() {
@@ -49,6 +47,10 @@ public final class TickEvent {
return state; return state;
} }
public static synchronized BiFunction<EventState, Type, TickEvent> createNextProvider() {
final int count = overallTickCount++;
return (state, type) -> new TickEvent(state, type, count);
}
public enum Type { public enum Type {
/** /**
@@ -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.
@@ -23,6 +23,10 @@ public abstract class AbstractSchematic implements ISchematic {
protected int y; protected int y;
protected int z; protected int z;
public AbstractSchematic() {
this(0, 0, 0);
}
public AbstractSchematic(int x, int y, int z) { public AbstractSchematic(int x, int y, int z) {
this.x = x; this.x = x;
this.y = y; this.y = y;
@@ -32,6 +32,10 @@ public class FillSchematic extends AbstractSchematic {
this.bom = bom; this.bom = bom;
} }
public FillSchematic(int x, int y, int z, IBlockState state) {
this(x, y, z, new BlockOptionalMeta(state.getBlock(), state.getBlock().getMetaFromState(state)));
}
public BlockOptionalMeta getBom() { public BlockOptionalMeta getBom() {
return bom; return bom;
} }
@@ -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.schematic;
import baritone.api.command.registry.Registry;
import baritone.api.schematic.format.ISchematicFormat;
import java.io.File;
import java.util.Optional;
/**
* @author Brady
* @since 12/23/2019
*/
public interface ISchematicSystem {
/**
* @return The registry of supported schematic formats
*/
Registry<ISchematicFormat> getRegistry();
/**
* Attempts to find an {@link ISchematicFormat} that supports the specified schematic file.
*
* @param file A schematic file
* @return The corresponding format for the file, {@link Optional#empty()} if no candidates were found.
*/
Optional<ISchematicFormat> getByFile(File file);
}
@@ -0,0 +1,60 @@
/*
* 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.schematic;
import net.minecraft.block.state.IBlockState;
/**
* A static schematic is capable of providing the desired state at a given position without
* additional context. Schematics of this type are expected to have non-varying contents.
*
* @see #getDirect(int, int, int)
*
* @author Brady
* @since 12/24/2019
*/
public interface IStaticSchematic extends ISchematic {
/**
* Gets the {@link IBlockState} for a given position in this schematic. It should be guaranteed
* that the return value of this method will not change given that the parameters are the same.
*
* @param x The X block position
* @param y The Y block position
* @param z The Z block position
* @return The desired state at the specified position.
*/
IBlockState getDirect(int x, int y, int z);
/**
* Returns an {@link IBlockState} array of size {@link #heightY()} which contains all
* desired block states in the specified vertical column. The index of {@link IBlockState}s
* in the array are equivalent to their Y position in the schematic.
*
* @param x The X column position
* @param z The Z column position
* @return An {@link IBlockState} array
*/
default IBlockState[] getColumn(int x, int z) {
IBlockState[] column = new IBlockState[this.heightY()];
for (int i = 0; i < this.heightY(); i++) {
column[i] = getDirect(x, i, z);
}
return column;
}
}
@@ -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.schematic.format;
import baritone.api.schematic.ISchematic;
import baritone.api.schematic.IStaticSchematic;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
/**
* The base of a {@link ISchematic} file format
*
* @author Brady
* @since 12/23/2019
*/
public interface ISchematicFormat {
/**
* @return The parser for creating schematics of this format
*/
IStaticSchematic parse(InputStream input) throws IOException;
/**
* @param file The file to check against
* @return Whether or not the specified file matches this schematic format
*/
boolean isFileType(File file);
}
@@ -178,16 +178,27 @@ public final class BlockOptionalMeta {
normalizations = Collections.unmodifiableMap(_normalizations); normalizations = Collections.unmodifiableMap(_normalizations);
} }
private static <C extends Comparable<C>, P extends IProperty<C>> P castToIProperty(Object value) { public static <C extends Comparable<C>, P extends IProperty<C>> P castToIProperty(Object value) {
//noinspection unchecked //noinspection unchecked
return (P) value; return (P) value;
} }
private static <C extends Comparable<C>, P extends IProperty<C>> C castToIPropertyValue(P iproperty, Object value) { public static <C extends Comparable<C>, P extends IProperty<C>> C castToIPropertyValue(P iproperty, Object value) {
//noinspection unchecked //noinspection unchecked
return (C) value; return (C) value;
} }
/**
* Normalizes the specified blockstate by setting meta-affecting properties which
* are not being targeted by the meta parameter to their default values.
* <p>
* For example, block variant/color is the primary target for the meta value, so properties
* such as rotation/facing direction will be set to default values in order to nullify
* the effect that they have on the state's meta value.
*
* @param state The state to normalize
* @return The normalized block state
*/
public static IBlockState normalize(IBlockState state) { public static IBlockState normalize(IBlockState state) {
IBlockState newState = state; IBlockState newState = state;
@@ -220,6 +231,15 @@ public final class BlockOptionalMeta {
return newState; return newState;
} }
/**
* Evaluate the target meta value for the specified state. The target meta value is
* most often that which is influenced by the variant/color property of the block state.
*
* @see #normalize(IBlockState)
*
* @param state The state to check
* @return The target meta of the state
*/
public static int stateMeta(IBlockState state) { public static int stateMeta(IBlockState state) {
return state.getBlock().getMetaFromState(normalize(state)); return state.getBlock().getMetaFromState(normalize(state));
} }
@@ -17,6 +17,7 @@
package baritone.api.utils; package baritone.api.utils;
import baritone.api.BaritoneAPI;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ClickType; import net.minecraft.inventory.ClickType;
@@ -45,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);
@@ -56,6 +59,6 @@ public interface IPlayerController {
void setHittingBlock(boolean hittingBlock); void setHittingBlock(boolean hittingBlock);
default double getBlockReachDistance() { default double getBlockReachDistance() {
return this.getGameType().isCreative() ? 5.0F : 4.5F; return this.getGameType().isCreative() ? 5.0F : BaritoneAPI.getSettings().blockReachDistance.value;
} }
} }
@@ -41,6 +41,8 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.function.BiFunction;
/** /**
* @author Brady * @author Brady
* @since 7/31/2018 * @since 7/31/2018
@@ -84,13 +86,15 @@ public class MixinMinecraft {
) )
) )
private void runTick(CallbackInfo ci) { private void runTick(CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) { final BiFunction<EventState, TickEvent.Type, TickEvent> tickProvider = TickEvent.createNextProvider();
TickEvent.Type type = ibaritone.getPlayerContext().player() != null && ibaritone.getPlayerContext().world() != null for (IBaritone baritone : BaritoneAPI.getProvider().getAllBaritones()) {
TickEvent.Type type = baritone.getPlayerContext().player() != null && baritone.getPlayerContext().world() != null
? TickEvent.Type.IN ? TickEvent.Type.IN
: TickEvent.Type.OUT; : TickEvent.Type.OUT;
ibaritone.getGameEventHandler().onTick(new TickEvent(EventState.PRE, type)); baritone.getGameEventHandler().onTick(tickProvider.apply(EventState.PRE, type));
} }
} }
+3 -4
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
+24 -5
View File
@@ -19,13 +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.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 java.util.Collections; import java.util.ArrayList;
import java.util.List; import java.util.List;
/** /**
@@ -35,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);
@@ -52,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
@@ -60,8 +69,18 @@ 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;
} }
@Override
public ISchematicSystem getSchematicSystem() {
return SchematicSystem.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,7 +160,19 @@ 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
@@ -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;
}
}
+35 -22
View File
@@ -111,6 +111,41 @@ public enum WorldScanner implements IWorldScanner {
return res; return res;
} }
@Override
public int repack(IPlayerContext ctx) {
return this.repack(ctx, 40);
}
@Override
public int repack(IPlayerContext ctx, int range) {
IChunkProvider chunkProvider = ctx.world().getChunkProvider();
ICachedWorld cachedWorld = ctx.worldData().getCachedWorld();
BetterBlockPos playerPos = ctx.playerFeet();
int playerChunkX = playerPos.getX() >> 4;
int playerChunkZ = playerPos.getZ() >> 4;
int minX = playerChunkX - range;
int minZ = playerChunkZ - range;
int maxX = playerChunkX + range;
int maxZ = playerChunkZ + range;
int queued = 0;
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
Chunk chunk = chunkProvider.getLoadedChunk(x, z);
if (chunk != null && !chunk.isEmpty()) {
queued++;
cachedWorld.queueForPacking(chunk);
}
}
}
return queued;
}
private boolean scanChunkInto(int chunkX, int chunkZ, Chunk chunk, BlockOptionalMetaLookup filter, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY, int[] coordinateIterationOrder) { private boolean scanChunkInto(int chunkX, int chunkZ, Chunk chunk, BlockOptionalMetaLookup filter, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY, int[] coordinateIterationOrder) {
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
boolean foundWithinY = false; boolean foundWithinY = false;
@@ -147,26 +182,4 @@ public enum WorldScanner implements IWorldScanner {
} }
return foundWithinY; return foundWithinY;
} }
public int repack(IPlayerContext ctx) {
IChunkProvider chunkProvider = ctx.world().getChunkProvider();
ICachedWorld cachedWorld = ctx.worldData().getCachedWorld();
BetterBlockPos playerPos = ctx.playerFeet();
int playerChunkX = playerPos.getX() >> 4;
int playerChunkZ = playerPos.getZ() >> 4;
int queued = 0;
for (int x = playerChunkX - 40; x <= playerChunkX + 40; x++) {
for (int z = playerChunkZ - 40; z <= playerChunkZ + 40; z++) {
Chunk chunk = chunkProvider.getLoadedChunk(x, z);
if (chunk != null && !chunk.isEmpty()) {
queued++;
cachedWorld.queueForPacking(chunk);
}
}
}
return queued;
}
} }
@@ -316,8 +316,7 @@ public class ArgConsumer implements IArgConsumer {
try { try {
return datatype.apply(this.context, original); return datatype.apply(this.context, original);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); throw new CommandInvalidTypeException(hasAny() ? peek() : consumed(), datatype.getClass().getSimpleName(), e);
throw new CommandInvalidTypeException(hasAny() ? peek() : consumed(), datatype.getClass().getSimpleName());
} }
} }
@@ -346,7 +345,7 @@ public class ArgConsumer implements IArgConsumer {
try { try {
return datatype.get(this.context); return datatype.get(this.context);
} catch (Exception e) { } catch (Exception e) {
throw new CommandInvalidTypeException(hasAny() ? peek() : consumed(), datatype.getClass().getSimpleName()); throw new CommandInvalidTypeException(hasAny() ? peek() : consumed(), datatype.getClass().getSimpleName(), e);
} }
} }
@@ -17,6 +17,7 @@
package baritone.command.defaults; package baritone.command.defaults;
import baritone.Baritone;
import baritone.api.IBaritone; import baritone.api.IBaritone;
import baritone.api.utils.BetterBlockPos; import baritone.api.utils.BetterBlockPos;
import baritone.api.command.Command; import baritone.api.command.Command;
@@ -26,11 +27,11 @@ import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandInvalidStateException; import baritone.api.command.exception.CommandInvalidStateException;
import baritone.api.command.argument.IArgConsumer; import baritone.api.command.argument.IArgConsumer;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import org.apache.commons.io.FilenameUtils;
import java.io.File; import java.io.File;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.stream.Stream; import java.util.stream.Stream;
public class BuildCommand extends Command { public class BuildCommand extends Command {
@@ -44,8 +45,8 @@ public class BuildCommand extends Command {
@Override @Override
public void execute(String label, IArgConsumer args) throws CommandException { public void execute(String label, IArgConsumer args) throws CommandException {
File file = args.getDatatypePost(RelativeFile.INSTANCE, schematicsDir).getAbsoluteFile(); File file = args.getDatatypePost(RelativeFile.INSTANCE, schematicsDir).getAbsoluteFile();
if (!file.getName().toLowerCase(Locale.US).endsWith(".schematic")) { if (FilenameUtils.getExtension(file.getAbsolutePath()).isEmpty()) {
file = new File(file.getAbsolutePath() + ".schematic"); file = new File(file.getAbsolutePath() + "." + Baritone.settings().schematicFallbackExtension);
} }
BetterBlockPos origin = ctx.playerFeet(); BetterBlockPos origin = ctx.playerFeet();
BetterBlockPos buildOrigin; BetterBlockPos buildOrigin;
@@ -1,61 +0,0 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.command.defaults;
import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.exception.CommandException;
import baritone.api.command.argument.IArgConsumer;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;
public class CancelCommand extends Command {
public CancelCommand(IBaritone baritone) {
super(baritone, "cancel", "stop");
}
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
args.requireMax(0);
baritone.getPathingBehavior().cancelEverything();
logDirect("ok canceled");
}
@Override
public Stream<String> tabComplete(String label, IArgConsumer args) {
return Stream.empty();
}
@Override
public String getShortDesc() {
return "Cancel what Baritone is currently doing";
}
@Override
public List<String> getLongDesc() {
return Arrays.asList(
"The cancel command tells Baritone to stop whatever it's currently doing.",
"",
"Usage:",
"> cancel"
);
}
}
@@ -24,7 +24,8 @@ import java.util.*;
public final class DefaultCommands { public final class DefaultCommands {
private DefaultCommands() {} private DefaultCommands() {
}
public static List<ICommand> createAll(IBaritone baritone) { public static List<ICommand> createAll(IBaritone baritone) {
Objects.requireNonNull(baritone); Objects.requireNonNull(baritone);
@@ -43,7 +44,6 @@ public final class DefaultCommands {
new SchematicaCommand(baritone), new SchematicaCommand(baritone),
new ComeCommand(baritone), new ComeCommand(baritone),
new AxisCommand(baritone), new AxisCommand(baritone),
new CancelCommand(baritone),
new ForceCancelCommand(baritone), new ForceCancelCommand(baritone),
new GcCommand(baritone), new GcCommand(baritone),
new InvertCommand(baritone), new InvertCommand(baritone),
@@ -66,10 +66,11 @@ public final class DefaultCommands {
new CommandAlias(baritone, "home", "Set goal to your home waypoint", "waypoints goal home"), new CommandAlias(baritone, "home", "Set goal to your home waypoint", "waypoints goal home"),
new SelCommand(baritone) new SelCommand(baritone)
)); ));
PauseResumeCommands prc = new PauseResumeCommands(baritone); ExecutionControlCommands prc = new ExecutionControlCommands(baritone);
commands.add(prc.pauseCommand); commands.add(prc.pauseCommand);
commands.add(prc.resumeCommand); commands.add(prc.resumeCommand);
commands.add(prc.pausedCommand); commands.add(prc.pausedCommand);
commands.add(prc.cancelCommand);
return Collections.unmodifiableList(commands); return Collections.unmodifiableList(commands);
} }
} }
@@ -18,13 +18,13 @@
package baritone.command.defaults; package baritone.command.defaults;
import baritone.api.IBaritone; import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandInvalidStateException;
import baritone.api.process.IBaritoneProcess; import baritone.api.process.IBaritoneProcess;
import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType; import baritone.api.process.PathingCommandType;
import baritone.api.command.Command;
import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandInvalidStateException;
import baritone.api.command.argument.IArgConsumer;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
@@ -37,13 +37,14 @@ import java.util.stream.Stream;
* TO USE THIS to pause and resume Baritone. Make your own process that returns {@link PathingCommandType#REQUEST_PAUSE * TO USE THIS to pause and resume Baritone. Make your own process that returns {@link PathingCommandType#REQUEST_PAUSE
* REQUEST_PAUSE} as needed. * REQUEST_PAUSE} as needed.
*/ */
public class PauseResumeCommands { public class ExecutionControlCommands {
Command pauseCommand; Command pauseCommand;
Command resumeCommand; Command resumeCommand;
Command pausedCommand; Command pausedCommand;
Command cancelCommand;
public PauseResumeCommands(IBaritone baritone) { public ExecutionControlCommands(IBaritone baritone) {
// array for mutability, non-field so reflection can't touch it // array for mutability, non-field so reflection can't touch it
final boolean[] paused = {false}; final boolean[] paused = {false};
baritone.getPathingControlManager().registerProcess( baritone.getPathingControlManager().registerProcess(
@@ -64,7 +65,8 @@ public class PauseResumeCommands {
} }
@Override @Override
public void onLostControl() {} public void onLostControl() {
}
@Override @Override
public double priority() { public double priority() {
@@ -169,5 +171,36 @@ public class PauseResumeCommands {
); );
} }
}; };
cancelCommand = new Command(baritone, "cancel", "stop") {
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
args.requireMax(0);
if (paused[0]) {
paused[0] = false;
}
baritone.getPathingBehavior().cancelEverything();
logDirect("ok canceled");
}
@Override
public Stream<String> tabComplete(String label, IArgConsumer args) {
return Stream.empty();
}
@Override
public String getShortDesc() {
return "Cancel what Baritone is currently doing";
}
@Override
public List<String> getLongDesc() {
return Arrays.asList(
"The cancel command tells Baritone to stop whatever it's currently doing.",
"",
"Usage:",
"> cancel"
);
}
};
} }
} }
@@ -41,9 +41,13 @@ public class GotoCommand extends Command {
@Override @Override
public void execute(String label, IArgConsumer args) throws CommandException { public void execute(String label, IArgConsumer args) throws CommandException {
if (args.peekDatatypeOrNull(RelativeCoordinate.INSTANCE) != null) { // if we have a numeric first argument... // If we have a numeric first argument, then parse arguments as coordinates.
// Note: There is no reason to want to go where you're already at so there
// is no need to handle the case of empty arguments.
if (args.peekDatatypeOrNull(RelativeCoordinate.INSTANCE) != null) {
args.requireMax(3);
BetterBlockPos origin = baritone.getPlayerContext().playerFeet(); BetterBlockPos origin = baritone.getPlayerContext().playerFeet();
Goal goal = args.getDatatypePostOrNull(RelativeGoal.INSTANCE, origin); Goal goal = args.getDatatypePost(RelativeGoal.INSTANCE, origin);
logDirect(String.format("Going to: %s", goal.toString())); logDirect(String.format("Going to: %s", goal.toString()));
baritone.getCustomGoalProcess().setGoalAndPath(goal); baritone.getCustomGoalProcess().setGoalAndPath(goal);
return; return;
@@ -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));
} }
@@ -35,6 +35,7 @@ import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.IBlockAccess;
import java.util.Optional; import java.util.Optional;
@@ -132,10 +133,8 @@ public interface MovementHelper extends ActionCosts, Helper {
} }
return block == Blocks.WATER || block == Blocks.FLOWING_WATER; return block == Blocks.WATER || block == Blocks.FLOWING_WATER;
} }
// every block that overrides isPassable with anything more complicated than a "return true;" or "return false;"
// has already been accounted for above return block.isPassable(bsi.access, bsi.isPassableBlockPos.setPos(x, y, z));
// therefore it's safe to not construct a blockpos from our x, y, z ints and instead just pass null
return block.isPassable(null, BlockPos.ORIGIN);
} }
/** /**
@@ -149,10 +148,18 @@ public interface MovementHelper extends ActionCosts, Helper {
* @return Whether or not the block at the specified position * @return Whether or not the block at the specified position
*/ */
static boolean fullyPassable(CalculationContext context, int x, int y, int z) { static boolean fullyPassable(CalculationContext context, int x, int y, int z) {
return fullyPassable(context.get(x, y, z)); return fullyPassable(
context.bsi.access,
context.bsi.isPassableBlockPos.setPos(x, y, z),
context.bsi.get0(x, y, z)
);
} }
static boolean fullyPassable(IBlockState state) { static boolean fullyPassable(IPlayerContext ctx, BlockPos pos) {
return fullyPassable(ctx.world(), pos, ctx.world().getBlockState(pos));
}
static boolean fullyPassable(IBlockAccess access, BlockPos pos, IBlockState state) {
Block block = state.getBlock(); Block block = state.getBlock();
if (block == Blocks.AIR) { // early return for most common case if (block == Blocks.AIR) { // early return for most common case
return true; return true;
@@ -174,7 +181,7 @@ public interface MovementHelper extends ActionCosts, Helper {
return false; return false;
} }
// door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters // door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters
return block.isPassable(null, null); return block.isPassable(access, pos);
} }
static boolean isReplaceable(int x, int y, int z, IBlockState state, BlockStateInterface bsi) { static boolean isReplaceable(int x, int y, int z, IBlockState state, BlockStateInterface bsi) {
@@ -114,7 +114,7 @@ public class MovementParkour extends Movement {
return; return;
} }
IBlockState destInto = context.bsi.get0(destX, y, destZ); IBlockState destInto = context.bsi.get0(destX, y, destZ);
if (!MovementHelper.fullyPassable(destInto)) { if (!MovementHelper.fullyPassable(context.bsi.access, context.bsi.isPassableBlockPos.setPos(destX, y, destZ), destInto)) {
if (i <= 3 && context.allowParkourAscend && context.canSprint && MovementHelper.canWalkOn(context.bsi, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) { if (i <= 3 && context.allowParkourAscend && context.canSprint && MovementHelper.canWalkOn(context.bsi, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) {
res.x = destX; res.x = destX;
res.y = y + 1; res.y = y + 1;
@@ -466,7 +466,7 @@ public class PathExecutor implements IPathExecutor, Helper {
} }
for (int y = next.getDest().y; y <= movement.getSrc().y + 1; y++) { for (int y = next.getDest().y; y <= movement.getSrc().y + 1; y++) {
BlockPos chk = new BlockPos(next.getDest().x, y, next.getDest().z); BlockPos chk = new BlockPos(next.getDest().x, y, next.getDest().z);
if (!MovementHelper.fullyPassable(ctx.world().getBlockState(chk))) { if (!MovementHelper.fullyPassable(ctx, chk)) {
break outer; break outer;
} }
} }
@@ -491,7 +491,7 @@ public class PathExecutor implements IPathExecutor, Helper {
} }
// we are centered // we are centered
BlockPos headBonk = current.getSrc().subtract(current.getDirection()).up(2); BlockPos headBonk = current.getSrc().subtract(current.getDirection()).up(2);
if (MovementHelper.fullyPassable(ctx.world().getBlockState(headBonk))) { if (MovementHelper.fullyPassable(ctx, headBonk)) {
return true; return true;
} }
// wait 0.3 // wait 0.3
@@ -524,7 +524,7 @@ public class PathExecutor implements IPathExecutor, Helper {
if (x == 1) { if (x == 1) {
chk = chk.add(current.getDirection()); chk = chk.add(current.getDirection());
} }
if (!MovementHelper.fullyPassable(ctx.world().getBlockState(chk))) { if (!MovementHelper.fullyPassable(ctx, chk)) {
return false; return false;
} }
} }
@@ -25,8 +25,14 @@ import baritone.api.pathing.goals.GoalGetToBlock;
import baritone.api.process.IBuilderProcess; import baritone.api.process.IBuilderProcess;
import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType; import baritone.api.process.PathingCommandType;
import baritone.api.schematic.FillSchematic;
import baritone.api.schematic.ISchematic; import baritone.api.schematic.ISchematic;
import baritone.api.utils.*; import baritone.api.schematic.IStaticSchematic;
import baritone.api.schematic.format.ISchematicFormat;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.RayTraceUtils;
import baritone.api.utils.Rotation;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.input.Input; import baritone.api.utils.input.Input;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement; import baritone.pathing.movement.Movement;
@@ -34,9 +40,8 @@ import baritone.pathing.movement.MovementHelper;
import baritone.utils.BaritoneProcessHelper; import baritone.utils.BaritoneProcessHelper;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.PathingCommandContext; import baritone.utils.PathingCommandContext;
import baritone.utils.schematic.FillSchematic;
import baritone.utils.schematic.MapArtSchematic; import baritone.utils.schematic.MapArtSchematic;
import baritone.utils.schematic.Schematic; import baritone.utils.schematic.SchematicSystem;
import baritone.utils.schematic.schematica.SchematicaHelper; import baritone.utils.schematic.schematica.SchematicaHelper;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import net.minecraft.block.BlockAir; import net.minecraft.block.BlockAir;
@@ -45,15 +50,12 @@ import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.item.ItemBlock; import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.Tuple; import net.minecraft.util.Tuple;
import net.minecraft.util.math.*; import net.minecraft.util.math.*;
import java.io.File; import java.io.File;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException;
import java.util.*; import java.util.*;
import static baritone.api.pathing.movement.ActionCosts.COST_INF; import static baritone.api.pathing.movement.ActionCosts.COST_INF;
@@ -69,6 +71,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
private int ticks; private int ticks;
private boolean paused; private boolean paused;
private int layer; private int layer;
private int numRepeats;
private List<IBlockState> approxPlaceable; private List<IBlockState> approxPlaceable;
public BuilderProcess(Baritone baritone) { public BuilderProcess(Baritone baritone) {
@@ -95,6 +98,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
this.origin = new Vec3i(x, y, z); this.origin = new Vec3i(x, y, z);
this.paused = false; this.paused = false;
this.layer = 0; this.layer = 0;
this.numRepeats = 0;
this.observedCompleted = new LongOpenHashSet(); this.observedCompleted = new LongOpenHashSet();
} }
@@ -113,27 +117,38 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
@Override @Override
public boolean build(String name, File schematic, Vec3i origin) { public boolean build(String name, File schematic, Vec3i origin) {
NBTTagCompound tag; Optional<ISchematicFormat> format = SchematicSystem.INSTANCE.getByFile(schematic);
try (FileInputStream fileIn = new FileInputStream(schematic)) { if (!format.isPresent()) {
tag = CompressedStreamTools.readCompressed(fileIn); return false;
} catch (IOException e) { }
ISchematic parsed;
try {
parsed = format.get().parse(new FileInputStream(schematic));
} catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
return false; return false;
} }
//noinspection ConstantConditions
if (tag == null) { if (Baritone.settings().mapArtMode.value) {
return false; parsed = new MapArtSchematic((IStaticSchematic) parsed);
} }
build(name, parse(tag), origin);
build(name, parsed, origin);
return true; return true;
} }
@Override @Override
public void buildOpenSchematic() { public void buildOpenSchematic() {
if (SchematicaHelper.isSchematicaPresent()) { if (SchematicaHelper.isSchematicaPresent()) {
Optional<Tuple<ISchematic, BlockPos>> schematic = SchematicaHelper.getOpenSchematic(); Optional<Tuple<IStaticSchematic, BlockPos>> schematic = SchematicaHelper.getOpenSchematic();
if (schematic.isPresent()) { if (schematic.isPresent()) {
this.build(schematic.get().getFirst().toString(), schematic.get().getFirst(), schematic.get().getSecond()); IStaticSchematic s = schematic.get().getFirst();
this.build(
schematic.get().getFirst().toString(),
Baritone.settings().mapArtMode.value ? new MapArtSchematic(s) : s,
schematic.get().getSecond()
);
} else { } else {
logDirect("No schematic currently open"); logDirect("No schematic currently open");
} }
@@ -155,10 +170,6 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
return new ArrayList<>(approxPlaceable); return new ArrayList<>(approxPlaceable);
} }
private static ISchematic parse(NBTTagCompound schematic) {
return Baritone.settings().mapArtMode.value ? new MapArtSchematic(schematic) : new Schematic(schematic);
}
@Override @Override
public boolean isActive() { public boolean isActive() {
return schematic != null; return schematic != null;
@@ -391,7 +402,9 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
return onTick(calcFailed, isSafeToCancel); return onTick(calcFailed, isSafeToCancel);
} }
Vec3i repeat = Baritone.settings().buildRepeat.value; Vec3i repeat = Baritone.settings().buildRepeat.value;
if (repeat.equals(new Vec3i(0, 0, 0))) { int max = Baritone.settings().buildRepeatCount.value;
numRepeats++;
if (repeat.equals(new Vec3i(0, 0, 0)) || (max != -1 && numRepeats >= max)) {
logDirect("Done building"); logDirect("Done building");
onLostControl(); onLostControl();
return null; return null;
@@ -731,6 +744,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
schematic = null; schematic = null;
realSchematic = null; realSchematic = null;
layer = 0; layer = 0;
numRepeats = 0;
paused = false; paused = false;
observedCompleted = null; observedCompleted = null;
} }
@@ -756,11 +770,20 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
} }
private boolean valid(IBlockState current, IBlockState desired) { private boolean valid(IBlockState current, IBlockState desired) {
if (desired == null) {
return true;
}
// TODO more complicated comparison logic I guess // TODO more complicated comparison logic I guess
if (current.getBlock() instanceof BlockLiquid && Baritone.settings().okIfWater.value) { if (current.getBlock() instanceof BlockLiquid && Baritone.settings().okIfWater.value) {
return true; return true;
} }
return desired == null || current.equals(desired); if (desired.getBlock() instanceof BlockAir && Baritone.settings().buildIgnoreBlocks.value.contains(current.getBlock())) {
return true;
}
if (!(current.getBlock() instanceof BlockAir) && Baritone.settings().buildIgnoreExisting.value) {
return true;
}
return current.equals(desired);
} }
public class BuilderCalculationContext extends CalculationContext { public class BuilderCalculationContext extends CalculationContext {
@@ -29,9 +29,7 @@ import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.settings.GameSettings; import net.minecraft.client.settings.GameSettings;
import net.minecraft.client.tutorial.TutorialSteps; import net.minecraft.client.tutorial.TutorialSteps;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameType; import net.minecraft.world.*;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldType;
/** /**
* Responsible for automatically testing Baritone's pathing algorithm by automatically creating a world with a specific * Responsible for automatically testing Baritone's pathing algorithm by automatically creating a world with a specific
@@ -85,15 +83,21 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
if (mc.currentScreen instanceof GuiMainMenu) { if (mc.currentScreen instanceof GuiMainMenu) {
System.out.println("Beginning Baritone automatic test routine"); System.out.println("Beginning Baritone automatic test routine");
mc.displayGuiScreen(null); mc.displayGuiScreen(null);
WorldSettings worldsettings = new WorldSettings(TEST_SEED, GameType.getByName("survival"), true, false, WorldType.DEFAULT); WorldSettings worldsettings = new WorldSettings(TEST_SEED, GameType.SURVIVAL, true, false, WorldType.DEFAULT);
mc.launchIntegratedServer("BaritoneAutoTest", "BaritoneAutoTest", worldsettings); mc.launchIntegratedServer("BaritoneAutoTest", "BaritoneAutoTest", worldsettings);
} }
// If the integrated server is launched and the world has initialized, set the spawn point // If the integrated server is running, set the difficulty to peaceful
// to our defined starting position if (mc.getIntegratedServer() != null) {
if (mc.getIntegratedServer() != null && mc.getIntegratedServer().worlds[0] != null) { mc.getIntegratedServer().setDifficultyForAllWorlds(EnumDifficulty.PEACEFUL);
mc.getIntegratedServer().worlds[0].setSpawnPoint(STARTING_POSITION);
mc.getIntegratedServer().worlds[0].getGameRules().setOrCreateGameRule("spawnRadius", "0"); for (final WorldServer world : mc.getIntegratedServer().worlds) {
// If the world has initialized, set the spawn point to our defined starting position
if (world != null) {
world.setSpawnPoint(STARTING_POSITION);
world.getGameRules().setOrCreateGameRule("spawnRadius", "0");
}
}
} }
if (event.getType() == TickEvent.Type.IN) { // If we're in-game if (event.getType() == TickEvent.Type.IN) { // If we're in-game
@@ -101,7 +105,7 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
// Force the integrated server to share the world to LAN so that // Force the integrated server to share the world to LAN so that
// the ingame pause menu gui doesn't actually pause our game // the ingame pause menu gui doesn't actually pause our game
if (mc.isSingleplayer() && !mc.getIntegratedServer().getPublic()) { if (mc.isSingleplayer() && !mc.getIntegratedServer().getPublic()) {
mc.getIntegratedServer().shareToLAN(GameType.getByName("survival"), false); mc.getIntegratedServer().shareToLAN(GameType.SURVIVAL, false);
} }
// For the first 200 ticks, wait for the world to generate // For the first 200 ticks, wait for the world to generate
@@ -30,6 +30,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
@@ -42,6 +43,9 @@ public class BlockStateInterface {
private final Long2ObjectMap<Chunk> loadedChunks; private final Long2ObjectMap<Chunk> loadedChunks;
private final WorldData worldData; private final WorldData worldData;
protected final IBlockAccess world;
public final BlockPos.MutableBlockPos isPassableBlockPos;
public final IBlockAccess access;
private Chunk prev = null; private Chunk prev = null;
private CachedRegion prevCached = null; private CachedRegion prevCached = null;
@@ -59,6 +63,7 @@ public class BlockStateInterface {
} }
public BlockStateInterface(World world, WorldData worldData, boolean copyLoadedChunks) { public BlockStateInterface(World world, WorldData worldData, boolean copyLoadedChunks) {
this.world = world;
this.worldData = worldData; this.worldData = worldData;
Long2ObjectMap<Chunk> worldLoaded = ((IChunkProviderClient) world.getChunkProvider()).loadedChunks(); Long2ObjectMap<Chunk> worldLoaded = ((IChunkProviderClient) world.getChunkProvider()).loadedChunks();
if (copyLoadedChunks) { if (copyLoadedChunks) {
@@ -70,6 +75,8 @@ public class BlockStateInterface {
if (!Minecraft.getMinecraft().isCallingFromMinecraftThread()) { if (!Minecraft.getMinecraft().isCallingFromMinecraftThread()) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
this.isPassableBlockPos = new BlockPos.MutableBlockPos();
this.access = new BlockStateInterfaceAccessWrapper(this);
} }
public boolean worldContainsLoadedChunk(int blockX, int blockZ) { public boolean worldContainsLoadedChunk(int blockX, int blockZ) {
@@ -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.utils;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockAccess;
import net.minecraft.world.WorldType;
import net.minecraft.world.biome.Biome;
import javax.annotation.Nullable;
/**
* @author Brady
* @since 11/5/2019
*/
@SuppressWarnings("NullableProblems")
public final class BlockStateInterfaceAccessWrapper implements IBlockAccess {
private final BlockStateInterface bsi;
BlockStateInterfaceAccessWrapper(BlockStateInterface bsi) {
this.bsi = bsi;
}
@Nullable
@Override
public TileEntity getTileEntity(BlockPos pos) {
throw new UnsupportedOperationException("getTileEntity not supported by BlockStateInterfaceAccessWrapper");
}
@Override
public int getCombinedLight(BlockPos pos, int lightValue) {
throw new UnsupportedOperationException("getCombinedLight not supported by BlockStateInterfaceAccessWrapper");
}
@Override
public IBlockState getBlockState(BlockPos pos) {
// BlockStateInterface#get0(BlockPos) btfo!
return this.bsi.get0(pos.getX(), pos.getY(), pos.getZ());
}
@Override
public boolean isAirBlock(BlockPos pos) {
return this.bsi.get0(pos.getX(), pos.getY(), pos.getZ()).getMaterial() == Material.AIR;
}
@Override
public Biome getBiome(BlockPos pos) {
throw new UnsupportedOperationException("getBiome not supported by BlockStateInterfaceAccessWrapper");
}
@Override
public int getStrongPower(BlockPos pos, EnumFacing direction) {
throw new UnsupportedOperationException("getStrongPower not supported by BlockStateInterfaceAccessWrapper");
}
@Override
public WorldType getWorldType() {
return this.bsi.world.getWorldType();
}
}
@@ -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();
@@ -17,24 +17,34 @@
package baritone.utils.schematic; package baritone.utils.schematic;
import baritone.api.schematic.IStaticSchematic;
import baritone.api.schematic.MaskSchematic;
import net.minecraft.block.BlockAir; import net.minecraft.block.BlockAir;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound;
import java.util.OptionalInt; import java.util.OptionalInt;
import java.util.function.Predicate; import java.util.function.Predicate;
public class MapArtSchematic extends Schematic { public class MapArtSchematic extends MaskSchematic {
private final int[][] heightMap; private final int[][] heightMap;
public MapArtSchematic(NBTTagCompound schematic) { public MapArtSchematic(IStaticSchematic schematic) {
super(schematic); super(schematic);
heightMap = new int[widthX][lengthZ]; this.heightMap = generateHeightMap(schematic);
}
for (int x = 0; x < widthX; x++) { @Override
for (int z = 0; z < lengthZ; z++) { protected boolean partOfMask(int x, int y, int z, IBlockState currentState) {
IBlockState[] column = states[x][z]; return y >= this.heightMap[x][z];
}
private static int[][] generateHeightMap(IStaticSchematic schematic) {
int[][] heightMap = new int[schematic.widthX()][schematic.lengthZ()];
for (int x = 0; x < schematic.widthX(); x++) {
for (int z = 0; z < schematic.lengthZ(); z++) {
IBlockState[] column = schematic.getColumn(x, z);
OptionalInt lowestBlockY = lastIndexMatching(column, state -> !(state.getBlock() instanceof BlockAir)); OptionalInt lowestBlockY = lastIndexMatching(column, state -> !(state.getBlock() instanceof BlockAir));
if (lowestBlockY.isPresent()) { if (lowestBlockY.isPresent()) {
@@ -44,9 +54,9 @@ public class MapArtSchematic extends Schematic {
System.out.println("Letting it be whatever"); System.out.println("Letting it be whatever");
heightMap[x][z] = 256; heightMap[x][z] = 256;
} }
} }
} }
return heightMap;
} }
private static <T> OptionalInt lastIndexMatching(T[] arr, Predicate<? super T> predicate) { private static <T> OptionalInt lastIndexMatching(T[] arr, Predicate<? super T> predicate) {
@@ -57,10 +67,4 @@ public class MapArtSchematic extends Schematic {
} }
return OptionalInt.empty(); return OptionalInt.empty();
} }
@Override
public boolean inSchematic(int x, int y, int z, IBlockState currentState) {
// in map art, we only care about coordinates in or above the art
return super.inSchematic(x, y, z, currentState) && y >= heightMap[x][z];
}
} }
@@ -0,0 +1,51 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils.schematic;
import baritone.api.command.registry.Registry;
import baritone.api.schematic.ISchematicSystem;
import baritone.api.schematic.format.ISchematicFormat;
import baritone.utils.schematic.format.DefaultSchematicFormats;
import java.io.File;
import java.util.Arrays;
import java.util.Optional;
/**
* @author Brady
* @since 12/24/2019
*/
public enum SchematicSystem implements ISchematicSystem {
INSTANCE;
private final Registry<ISchematicFormat> registry = new Registry<>();
SchematicSystem() {
Arrays.stream(DefaultSchematicFormats.values()).forEach(this.registry::register);
}
@Override
public Registry<ISchematicFormat> getRegistry() {
return this.registry;
}
@Override
public Optional<ISchematicFormat> getByFile(File file) {
return this.registry.stream().filter(format -> format.isFileType(file)).findFirst();
}
}
@@ -17,42 +17,34 @@
package baritone.utils.schematic; package baritone.utils.schematic;
import baritone.api.schematic.ISchematic; import baritone.api.schematic.AbstractSchematic;
import baritone.api.schematic.IStaticSchematic;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import java.util.List; import java.util.List;
public class FillSchematic implements ISchematic { /**
* Default implementation of {@link IStaticSchematic}
*
* @author Brady
* @since 12/23/2019
*/
public class StaticSchematic extends AbstractSchematic implements IStaticSchematic {
private final int widthX; protected IBlockState[][][] states;
private final int heightY;
private final int lengthZ;
private final IBlockState state;
public FillSchematic(int widthX, int heightY, int lengthZ, IBlockState state) {
this.widthX = widthX;
this.heightY = heightY;
this.lengthZ = lengthZ;
this.state = state;
}
@Override @Override
public IBlockState desiredState(int x, int y, int z, IBlockState current, List<IBlockState> approxPlaceable) { public IBlockState desiredState(int x, int y, int z, IBlockState current, List<IBlockState> approxPlaceable) {
return state; return this.states[x][z][y];
} }
@Override @Override
public int widthX() { public IBlockState getDirect(int x, int y, int z) {
return widthX; return this.states[x][z][y];
} }
@Override @Override
public int heightY() { public IBlockState[] getColumn(int x, int z) {
return heightY; return this.states[x][z];
}
@Override
public int lengthZ() {
return lengthZ;
} }
} }
@@ -0,0 +1,82 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils.schematic.format;
import baritone.api.schematic.IStaticSchematic;
import baritone.api.schematic.format.ISchematicFormat;
import baritone.utils.schematic.format.defaults.MCEditSchematic;
import baritone.utils.schematic.format.defaults.SpongeSchematic;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
/**
* Default implementations of {@link ISchematicFormat}
*
* @author Brady
* @since 12/13/2019
*/
public enum DefaultSchematicFormats implements ISchematicFormat {
/**
* The MCEdit schematic specification. Commonly denoted by the ".schematic" file extension.
*/
MCEDIT("schematic") {
@Override
public IStaticSchematic parse(InputStream input) throws IOException {
return new MCEditSchematic(CompressedStreamTools.readCompressed(input));
}
},
/**
* The SpongePowered Schematic Specification. Commonly denoted by the ".schem" file extension.
*
* @see <a href="https://github.com/SpongePowered/Schematic-Specification">Sponge Schematic Specification</a>
*/
SPONGE("schem") {
@Override
public IStaticSchematic parse(InputStream input) throws IOException {
NBTTagCompound nbt = CompressedStreamTools.readCompressed(input);
int version = nbt.getInteger("Version");
switch (version) {
case 1:
case 2:
return new SpongeSchematic(nbt);
default:
throw new UnsupportedOperationException("Unsupported Version of a Sponge Schematic");
}
}
};
private final String extension;
DefaultSchematicFormats(String extension) {
this.extension = extension;
}
@Override
public boolean isFileType(File file) {
return this.extension.equalsIgnoreCase(FilenameUtils.getExtension(file.getAbsolutePath()));
}
}
@@ -15,30 +15,27 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>. * along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/ */
package baritone.utils.schematic; package baritone.utils.schematic.format.defaults;
import baritone.api.schematic.ISchematic; import baritone.utils.schematic.StaticSchematic;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagCompound;
import java.util.List; /**
* @author Brady
* @since 12/27/2019
*/
public final class MCEditSchematic extends StaticSchematic {
public class Schematic implements ISchematic { public MCEditSchematic(NBTTagCompound schematic) {
public final int widthX;
public final int heightY;
public final int lengthZ;
protected final IBlockState[][][] states;
public Schematic(NBTTagCompound schematic) {
String type = schematic.getString("Materials"); String type = schematic.getString("Materials");
if (!type.equals("Alpha")) { if (!type.equals("Alpha")) {
throw new IllegalStateException("bad schematic " + type); throw new IllegalStateException("bad schematic " + type);
} }
widthX = schematic.getInteger("Width"); this.x = schematic.getInteger("Width");
heightY = schematic.getInteger("Height"); this.y = schematic.getInteger("Height");
lengthZ = schematic.getInteger("Length"); this.z = schematic.getInteger("Length");
byte[] blocks = schematic.getByteArray("Blocks"); byte[] blocks = schematic.getByteArray("Blocks");
byte[] metadata = schematic.getByteArray("Data"); byte[] metadata = schematic.getByteArray("Data");
@@ -51,11 +48,11 @@ public class Schematic implements ISchematic {
additional[i * 2 + 1] = (byte) ((addBlocks[i] >> 0) & 0xF); // upper nibble additional[i * 2 + 1] = (byte) ((addBlocks[i] >> 0) & 0xF); // upper nibble
} }
} }
states = new IBlockState[widthX][lengthZ][heightY]; this.states = new IBlockState[this.x][this.z][this.y];
for (int y = 0; y < heightY; y++) { for (int y = 0; y < this.y; y++) {
for (int z = 0; z < lengthZ; z++) { for (int z = 0; z < this.z; z++) {
for (int x = 0; x < widthX; x++) { for (int x = 0; x < this.x; x++) {
int blockInd = (y * lengthZ + z) * widthX + x; int blockInd = (y * this.z + z) * this.x + x;
int blockID = blocks[blockInd] & 0xFF; int blockID = blocks[blockInd] & 0xFF;
if (additional != null) { if (additional != null) {
@@ -64,29 +61,9 @@ public class Schematic implements ISchematic {
} }
Block block = Block.REGISTRY.getObjectById(blockID); Block block = Block.REGISTRY.getObjectById(blockID);
int meta = metadata[blockInd] & 0xFF; int meta = metadata[blockInd] & 0xFF;
states[x][z][y] = block.getStateFromMeta(meta); this.states[x][z][y] = block.getStateFromMeta(meta);
} }
} }
} }
} }
@Override
public IBlockState desiredState(int x, int y, int z, IBlockState current, List<IBlockState> approxPlaceable) {
return states[x][z][y];
}
@Override
public int widthX() {
return widthX;
}
@Override
public int heightY() {
return heightY;
}
@Override
public int lengthZ() {
return lengthZ;
}
} }
@@ -0,0 +1,157 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils.schematic.format.defaults;
import baritone.utils.schematic.StaticSchematic;
import baritone.utils.type.VarInt;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import net.minecraft.block.Block;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.IBlockState;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.ResourceLocation;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Brady
* @since 12/27/2019
*/
public final class SpongeSchematic extends StaticSchematic {
public SpongeSchematic(NBTTagCompound nbt) {
this.x = nbt.getInteger("Width");
this.y = nbt.getInteger("Height");
this.z = nbt.getInteger("Length");
this.states = new IBlockState[this.x][this.z][this.y];
Int2ObjectArrayMap<IBlockState> palette = new Int2ObjectArrayMap<>();
NBTTagCompound paletteTag = nbt.getCompoundTag("Palette");
for (String tag : paletteTag.getKeySet()) {
int index = paletteTag.getInteger(tag);
SerializedBlockState serializedState = SerializedBlockState.getFromString(tag);
if (serializedState == null) {
throw new IllegalArgumentException("Unable to parse palette tag");
}
IBlockState state = serializedState.deserialize();
if (state == null) {
throw new IllegalArgumentException("Unable to deserialize palette tag");
}
palette.put(index, state);
}
// BlockData is stored as an NBT byte[], however, the actual data that is represented is a varint[]
byte[] rawBlockData = nbt.getByteArray("BlockData");
int[] blockData = new int[this.x * this.y * this.z];
int offset = 0;
for (int i = 0; i < blockData.length; i++) {
if (offset >= rawBlockData.length) {
throw new IllegalArgumentException("No remaining bytes in BlockData for complete schematic");
}
VarInt varInt = VarInt.read(rawBlockData, offset);
blockData[i] = varInt.getValue();
offset += varInt.getSize();
}
for (int y = 0; y < this.y; y++) {
for (int z = 0; z < this.z; z++) {
for (int x = 0; x < this.x; x++) {
int index = (y * this.z + z) * this.x + x;
IBlockState state = palette.get(blockData[index]);
if (state == null) {
throw new IllegalArgumentException("Invalid Palette Index " + index);
}
this.states[x][z][y] = state;
}
}
}
}
private static final class SerializedBlockState {
private static final Pattern REGEX = Pattern.compile("(?<location>(\\w+:)?\\w+)(\\[(?<properties>(\\w+=\\w+,?)+)])?");
private final ResourceLocation resourceLocation;
private final Map<String, String> properties;
private IBlockState blockState;
private SerializedBlockState(ResourceLocation resourceLocation, Map<String, String> properties) {
this.resourceLocation = resourceLocation;
this.properties = properties;
}
private IBlockState deserialize() {
if (this.blockState == null) {
Block block = Block.REGISTRY.getObject(this.resourceLocation);
this.blockState = block.getDefaultState();
this.properties.keySet().stream().sorted(String::compareTo).forEachOrdered(key -> {
IProperty<?> property = block.getBlockState().getProperty(key);
if (property != null) {
this.blockState = setPropertyValue(this.blockState, property, this.properties.get(key));
}
});
}
return this.blockState;
}
private static SerializedBlockState getFromString(String s) {
Matcher m = REGEX.matcher(s);
if (!m.matches()) {
return null;
}
try {
String location = m.group("location");
String properties = m.group("properties");
ResourceLocation resourceLocation = new ResourceLocation(location);
Map<String, String> propertiesMap = new HashMap<>();
if (properties != null) {
for (String property : properties.split(",")) {
String[] split = property.split("=");
propertiesMap.put(split[0], split[1]);
}
}
return new SerializedBlockState(resourceLocation, propertiesMap);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
private static <T extends Comparable<T>> IBlockState setPropertyValue(IBlockState state, IProperty<T> property, String value) {
Optional<T> parsed = property.parseValue(value).toJavaUtil();
if (parsed.isPresent()) {
return state.withProperty(property, parsed.get());
} else {
throw new IllegalArgumentException("Invalid value for property " + property);
}
}
}
}
@@ -17,14 +17,14 @@
package baritone.utils.schematic.schematica; package baritone.utils.schematic.schematica;
import baritone.api.schematic.ISchematic; import baritone.api.schematic.IStaticSchematic;
import com.github.lunatrius.schematica.client.world.SchematicWorld; import com.github.lunatrius.schematica.client.world.SchematicWorld;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import java.util.List; import java.util.List;
public final class SchematicAdapter implements ISchematic { public final class SchematicAdapter implements IStaticSchematic {
private final SchematicWorld schematic; private final SchematicWorld schematic;
@@ -34,7 +34,12 @@ public final class SchematicAdapter implements ISchematic {
@Override @Override
public IBlockState desiredState(int x, int y, int z, IBlockState current, List<IBlockState> approxPlaceable) { public IBlockState desiredState(int x, int y, int z, IBlockState current, List<IBlockState> approxPlaceable) {
return schematic.getSchematic().getBlockState(new BlockPos(x, y, z)); return this.getDirect(x, y, z);
}
@Override
public IBlockState getDirect(int x, int y, int z) {
return this.schematic.getSchematic().getBlockState(new BlockPos(x, y, z));
} }
@Override @Override
@@ -17,7 +17,7 @@
package baritone.utils.schematic.schematica; package baritone.utils.schematic.schematica;
import baritone.api.schematic.ISchematic; import baritone.api.schematic.IStaticSchematic;
import com.github.lunatrius.schematica.Schematica; import com.github.lunatrius.schematica.Schematica;
import com.github.lunatrius.schematica.proxy.ClientProxy; import com.github.lunatrius.schematica.proxy.ClientProxy;
import net.minecraft.util.Tuple; import net.minecraft.util.Tuple;
@@ -37,7 +37,7 @@ public enum SchematicaHelper {
} }
} }
public static Optional<Tuple<ISchematic, BlockPos>> getOpenSchematic() { public static Optional<Tuple<IStaticSchematic, BlockPos>> getOpenSchematic() {
return Optional.ofNullable(ClientProxy.schematic) return Optional.ofNullable(ClientProxy.schematic)
.map(world -> new Tuple<>(new SchematicAdapter(world), world.position)); .map(world -> new Tuple<>(new SchematicAdapter(world), world.position));
} }
@@ -0,0 +1,95 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils.type;
import it.unimi.dsi.fastutil.bytes.ByteArrayList;
import it.unimi.dsi.fastutil.bytes.ByteList;
/**
* @author Brady
* @since 12/19/2019
*/
public final class VarInt {
private final int value;
private final byte[] serialized;
private final int size;
public VarInt(int value) {
this.value = value;
this.serialized = serialize0(this.value);
this.size = this.serialized.length;
}
/**
* @return The integer value that is represented by this {@link VarInt}.
*/
public final int getValue() {
return this.value;
}
/**
* @return The size of this {@link VarInt}, in bytes, once serialized.
*/
public final int getSize() {
return this.size;
}
public final byte[] serialize() {
return this.serialized;
}
private static byte[] serialize0(int valueIn) {
ByteList bytes = new ByteArrayList();
int value = valueIn;
while ((value & 0x80) != 0) {
bytes.add((byte) (value & 0x7F | 0x80));
value >>>= 7;
}
bytes.add((byte) (value & 0xFF));
return bytes.toByteArray();
}
public static VarInt read(byte[] bytes) {
return read(bytes, 0);
}
public static VarInt read(byte[] bytes, int start) {
int value = 0;
int size = 0;
int index = start;
while (true) {
byte b = bytes[index++];
value |= (b & 0x7F) << size++ * 7;
if (size > 5) {
throw new IllegalArgumentException("VarInt size cannot exceed 5 bytes");
}
// Most significant bit denotes another byte is to be read.
if ((b & 0x80) == 0) {
break;
}
}
return new VarInt(value);
}
}