diff --git a/.idea/copyright/Baritone.xml b/.idea/copyright/Baritone.xml index c0916294..77f2d5b1 100644 --- a/.idea/copyright/Baritone.xml +++ b/.idea/copyright/Baritone.xml @@ -1,6 +1,7 @@ - \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 20fca03c..dece8bf4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,9 +5,26 @@ sudo: required services: - docker -install: true +install: +- sudo apt-get update +- sudo apt-get install jshon +- ./gradlew test script: - docker build -t cabaletta/baritone . -- docker run cabaletta/baritone /bin/sh -c "./gradlew test" -- docker run cabaletta/baritone /bin/sh -c "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 128x128x24 -ac +extension GLX +render; DISPLAY=:99 BARITONE_AUTO_TEST=true ./gradlew runClient" \ No newline at end of file +- docker run cabaletta/baritone /bin/sh -c "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 128x128x24 -ac +extension GLX +render; DISPLAY=:99 BARITONE_AUTO_TEST=true ./gradlew runClient" +- sh scripts/build.sh + +deploy: + provider: releases + api_key: + secure: YOuiXoJNpB4bW89TQoY2IGXg0tqOKls55YMXsSPU6Mx8WzRu8CjjO/A8KA9nGfNrKM+NucjiKr/h53O2Dp2uyy0i0SLvav/G0MaBMeB1NlPRwFopi6tVPNaoZsvr8NW4BIURhspckYLpOTYWnfmOkIv8q7AxrjUZWPKDlq0dte20UxEqUE6msHJ7U9XlKo/4fX40kvWMfwGI2hTyAtL0cRT1QPsd+uW3OQjAPcQj+jKaWld46V8pBK8g9Qde9mo8HC9NBv97zw1bBF1EFkynW569kElHvaS2Opl2QLGaf66guDbpnqDpGHMhQrDdxsZHJ4RksyITn+8A9UArmbkU35BxKqBeQqOWxod2+M0axdLh1pvX43Q1t9n7RiZBf7GvV8vkXL5Sjf8v6Y4LqkJGhvQkTUwpH+0knwrE761DMCtBC34AiWG70D4u7msmhurkflr9kmRHSj/3lyJ1Q2lkt8L+FOAlQBVs64vXTsfgc6Yge7N0O3UD5hCkrDNoz3BzhNBdCkbdxdKCGip71UZgUNkPy9o3ui8jATNj9ypx3+U8ovqP0XWlJqUZmyeXyNGW9NrLeCkRLTlLnZ/dv6OPONa1oAu4TwF1w5A+TGRFZcZjH/PnZKZDQ1OYQOR6drLKRYdr2unvuf5KUKUGqZ7aYtLGhP0rBvGWddRV7DSmX/s= + all_branches: true + file_glob: true + file: + - dist/* + body: $(jshon -s "$(cat dist/checksums.txt)") + skip_cleanup: true + on: + tags: true + repo: cabaletta/baritone diff --git a/Dockerfile b/Dockerfile index 5e435e7d..9d5d1d7f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -17,7 +17,7 @@ ADD . /code RUN echo "\nrunClient {\nargs \"--width\",\"128\",\"--height\",\"128\"\n}" >> /code/build.gradle -RUN dpkg -i /code/xvfb_1.16.4-1_amd64.deb +RUN dpkg -i /code/scripts/xvfb_1.16.4-1_amd64.deb WORKDIR /code diff --git a/FEATURES.md b/FEATURES.md index 8147fc22..172b2f87 100644 --- a/FEATURES.md +++ b/FEATURES.md @@ -2,12 +2,14 @@ - **Long distance pathing and splicing** Baritone calculates paths in segments, and precalculates the next segment when the current one is about to end, so that it's moving towards the goal at all times. - **Chunk caching** Baritone simplifies chunks to a compacted internal 2-bit representation (AIR, SOLID, WATER, AVOID) and stores them in RAM for better very-long-distance pathing. There is also an option to save these cached chunks to disk. Example - **Block breaking** Baritone considers breaking blocks as part of its path. It also takes into account your current tool set and hot bar. For example, if you have a Eff V diamond pick, it may choose to mine through a stone barrier, while if you only had a wood pick it might be faster to climb over it. -- **Block placing** Baritone considers placing blocks as part of its path. This includes sneak-back-placing, pillaring, etc. It has a configurable penalty of placing a block (set to 1 second by default), to conserve its resources. The list of acceptable throwaway blocks is also configurable, and is cobble, dirt, or netherrack by default. +- **Block placing** Baritone considers placing blocks as part of its path. This includes sneak-back-placing, pillaring, etc. It has a configurable penalty of placing a block (set to 1 second by default), to conserve its resources. The list of acceptable throwaway blocks is also configurable, and is cobble, dirt, or netherrack by default. Example - **Falling** Baritone will fall up to 3 blocks onto solid ground (configurable, if you have Feather Falling and/or don't mind taking a little damage). If you have a water bucket on your hotbar, it will fall up to 23 blocks and place the bucket beneath it. It will fall an unlimited distance into existing still water. - **Vines and ladders** Baritone understands how to climb and descend vines and ladders. There is experimental support for more advanced maneuvers, like strafing to a different ladder / vine column in midair (off by default, setting named `allowVines`). -- **Fence gates and doors** +- **Opening fence gates and doors** +- **Slabs and stairs** - **Falling blocks** Baritone understands the costs of breaking blocks with falling blocks on top, and includes all of their break costs. Additionally, since it avoids breaking any blocks touching a liquid, it won't break the bottom of a gravel stack below a lava lake (anymore). - **Avoiding dangerous blocks** Obviously, it knows not to walk through fire or on magma, not to corner over lava (that deals some damage), not to break any blocks touching a liquid (it might drown), etc. +- **Parkour** Sprint jumping over 1, 2, or 3 block gaps # Pathing method Baritone uses a modified version of A*. @@ -35,15 +37,13 @@ And finally `GoalComposite`. `GoalComposite` is a list of other goals, any one o # Future features Things it doesn't have yet - Trapdoors -- Slabs (double, top, and bottom) - Sprint jumping in a 1x2 corridor -- Stairs +- Parkour (jumping over gaps of any length) [IN PROGRESS] See issues for more. Things it may not ever have, from most likely to least likely =( -- Parkour (jumping over gaps of any length) -- Boats - Pigs +- Boats - Horses (2x3 path instead of 1x2) - Elytra diff --git a/IMPACT.md b/IMPACT.md new file mode 100644 index 00000000..3ae9a790 --- /dev/null +++ b/IMPACT.md @@ -0,0 +1,86 @@ +# Integration between Baritone and Impact +Impact 4.4 will have Baritone included on release, however, if you're impatient, you can install Baritone into Impact 4.3 right now! + +## An Introduction +There are some basic steps to getting Baritone setup with Impact. +- Acquiring a build of Baritone +- Placing Baritone in the libraries directory +- Modifying the Impact Profile JSON to run baritone +- How to use Baritone + +## Acquiring a build of Baritone +There are 3 methods of acquiring a build of Baritone (While it is still in development) + +### Official Build (Not always up to date) +Download the "official" jar (as of commit 61cf103, +built on September 24) from here. + +### Building Baritone yourself +There are a few steps to this +- Clone this repository +- Setup the project as instructed in the README +- Run the ``build`` gradle task. You can either do this using IntelliJ's gradle UI or through a +command line + - Windows: ``gradlew build`` + - Mac/Linux: ``./gradlew build`` +- The build should be exported into ``/build/libs/baritone-X.Y.Z.jar`` + +### Cutting Edge Release +If you want to trust @Plutie#9079, you can download an automatically generated build of the latest commit +from his Jenkins server, found here. + +## Placing Baritone in the libraries directory +``/libraries`` is a neat directory in your Minecraft Installation Directory +that contains all of the dependencies that are required from the game and some mods. This is where we will be +putting baritone. +- Locate the ``libraries`` folder, it should be in the Minecraft Installation Directory +- Create 3 new subdirectories starting from ``libraries`` + - ``cabaletta`` + - ``baritone`` + - ``X.Y.Z`` + - Copy the build of Baritone that was acquired earlier, and place it into the ``X.Y.Z`` folder + - The full path should look like ``/libraries/cabaletta/baritone/X.Y.Z/baritone-X.Y.Z.jar`` + +## Modifying the Impact Profile JSON to run baritone +The final step is "registering" the Baritone library with Impact, so that it loads on launch. +- Ensure your Minecraft launcher is closed +- Navigate back to the Minecraft Installation Directory +- Find the ``versions`` directory, and open in +- In here there should be a ``1.12.2-Impact_4.3`` folder. + - If you don't have any Impact folder or have a version older than 4.3, you can download Impact here. +- Open the folder and inside there should be a file called ``1.12.2-Impact_4.3.json`` +- Open the JSON file with a text editor that supports your system's line endings + - For example, Notepad on Windows likely will NOT work for this. You should instead use a Text Editor like + Notepad++ if you're on Windows. (For other systems, I'm not sure + what would work the best so you may have to do some research.) +- Find the ``libraries`` array in the JSON. It should look something like this. + ``` + "libraries": [ + { + "name": "net.minecraft:launchwrapper:1.12" + }, + { + "name": "com.github.ImpactDevelopment:Impact:4.3-1.12.2", + "url": "https://impactdevelopment.github.io/maven/" + }, + { + "name": "com.github.ImpactDeveloment:ClientAPI:3.0.2", + "url": "https://impactdevelopment.github.io/maven/" + }, + ... + ``` +- Create a new object in the array, between the ``Impact`` and ``ClientAPI`` dependencies preferably. + ``` + { + "name": "cabaletta:baritone:X.Y.Z" + }, + ``` +- Now find the ``"minecraftArguments": "..."`` text near the top. +- At the very end of the quotes where it says ``--tweakClass clientapi.load.ClientTweaker"``, add on the following so it looks like: + - ``--tweakClass clientapi.load.ClientTweaker --tweakClass baritone.launch.BaritoneTweakerOptifine"`` +- If you didn't close your launcher for this step, restart it now. +- You can now launch Impact 4.3 as normal, and Baritone should start up + + ## How to use Baritone + Instructions on how to use Baritone are limited, and you may have to read a little bit of code (Really nothing much + just plain English), you can view that here. diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..153d416d --- /dev/null +++ b/LICENSE @@ -0,0 +1,165 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. \ No newline at end of file diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index da125cc9..00000000 --- a/LICENSE.txt +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Baritone Copyright (C) 2018 Cabaletta - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/README.md b/README.md index 29771860..2a198c40 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,29 @@ # Baritone -A Minecraft bot. This project is an updated version of [Minebot](https://github.com/leijurv/MineBot/), -the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. +[![Build Status](https://travis-ci.com/cabaletta/baritone.svg?branch=master)](https://travis-ci.com/cabaletta/baritone) +[![License](https://img.shields.io/github/license/cabaletta/baritone.svg)](LICENSE) +[![Codacy Badge](https://api.codacy.com/project/badge/Grade/7150d8ccf6094057b1782aa7a8f92d7d)](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&utm_medium=referral&utm_content=cabaletta/baritone&utm_campaign=Badge_Grade) -Features + + +Unofficial Jenkins: [![Jenkins Status](https://img.shields.io/badge/jenkins-offline-red.svg)]() + +A Minecraft pathfinder bot. This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/), +the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [29x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths). + +Here are some links to help to get started: + +- [Features](FEATURES.md) + +- [Baritone + Impact](IMPACT.md) + +There's also some useful information down below # Setup + +## IntelliJ's Gradle UI - Open the project in IntelliJ as a Gradle project - Run the Gradle task `setupDecompWorkspace` - Run the Gradle task `genIntellijRuns` @@ -13,6 +32,14 @@ the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. ## Command Line On Mac OSX and Linux, use `./gradlew` instead of `gradlew`. + +Running Baritone: + +``` +$ gradlew run +``` + +Setting up for IntelliJ: ``` $ gradlew setupDecompWorkspace $ gradlew --refresh-dependencies @@ -20,24 +47,30 @@ $ gradlew genIntellijRuns ``` # Chat control -Defined here +[Defined Here](src/main/java/baritone/utils/ExampleBaritoneControl.java) Quick start example: `thisway 1000` or `goal 70` to set the goal, `path` to actually start pathing. Also try `mine diamond_ore`. `cancel` to cancel. # API example ``` -Baritone.settings().allowSprint.value = true; -Baritone.settings().pathTimeoutMS.value = 2000L; +BaritoneAPI.getSettings().allowSprint.value = true; +BaritoneAPI.getSettings().pathTimeoutMS.value = 2000L; -PathingBehavior.INSTANCE.setGoal(new GoalXZ(10000, 20000)); -PathingBehavior.INSTANCE.path(); +BaritoneAPI.getPathingBehavior().setGoal(new GoalXZ(10000, 20000)); +BaritoneAPI.getPathingBehavior().path(); ``` -# Can I use Baritone as a library in my hacked client? +# FAQ -Sure! +## Can I use Baritone as a library in my hacked client? -# How is it so fast? +Sure! (As long as usage is in compliance with the LGPL 3 License) -Magic \ No newline at end of file +## How is it so fast? + +Magic. (Hours of [Leijurv](https://github.com/leijurv) enduring excruciating pain) + +## Why is it called Baritone? + +It's named for FitMC's deep sultry voice. \ No newline at end of file diff --git a/build.gradle b/build.gradle index bdb3c311..0a1bb804 100755 --- a/build.gradle +++ b/build.gradle @@ -2,21 +2,21 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ group 'baritone' -version '1.0.0' +version '0.0.3' buildscript { repositories { @@ -38,14 +38,19 @@ buildscript { } apply plugin: 'java' +apply plugin: 'net.minecraftforge.gradle.tweaker-client' +apply plugin: 'org.spongepowered.mixin' sourceCompatibility = targetCompatibility = '1.8' compileJava { sourceCompatibility = targetCompatibility = '1.8' } -apply plugin: 'net.minecraftforge.gradle.tweaker-client' -apply plugin: 'org.spongepowered.mixin' +sourceSets { + launch { + compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output + } +} minecraft { version = '1.12.2' @@ -65,7 +70,7 @@ repositories { } dependencies { - runtime implementation('org.spongepowered:mixin:0.7.11-SNAPSHOT') { + runtime launchCompile('org.spongepowered:mixin:0.7.11-SNAPSHOT') { // Mixin includes a lot of dependencies that are too up-to-date exclude module: 'launchwrapper' exclude module: 'guava' @@ -78,5 +83,9 @@ dependencies { mixin { defaultObfuscationEnv notch - add sourceSets.main, 'mixins.baritone.refmap.json' + add sourceSets.launch, 'mixins.baritone.refmap.json' +} + +jar { + from sourceSets.launch.output, sourceSets.api.output } diff --git a/scripts/build.sh b/scripts/build.sh new file mode 100644 index 00000000..c5131692 --- /dev/null +++ b/scripts/build.sh @@ -0,0 +1,23 @@ +set -e # this makes the whole script fail immediately if any one of these commands fails +./gradlew build +export VERSION=$(cat build.gradle | grep "version '" | cut -d "'" -f 2-2) +wget https://downloads.sourceforge.net/project/proguard/proguard/6.0/proguard6.0.3.zip +unzip proguard6.0.3.zip 2>&1 > /dev/null +cd build/libs +echo "-injars 'baritone-$VERSION.jar'" >> api.pro # insert current version +cat ../../scripts/proguard.pro | grep -v "this is the rt jar" | grep -v "\-injars" >> api.pro # remove default rt jar and injar lines +echo "-libraryjars '$(java -verbose 2>/dev/null | sed -ne '1 s/\[Opened \(.*\)\]/\1/p')'" >> api.pro # insert correct rt.jar location +tail api.pro # debug, print out what the previous two commands generated +cat api.pro | grep -v "\-keep class baritone.api" > standalone.pro # standalone doesn't keep baritone api +wget https://www.dropbox.com/s/zmc2l3jnwdvzvak/tempLibraries.zip?dl=1 # i'm sorry +mv tempLibraries.zip?dl=1 tempLibraries.zip +unzip tempLibraries.zip +mkdir ../../dist +java -jar ../../proguard6.0.3/lib/proguard.jar @api.pro +mv Obfuscated/baritone-$VERSION.jar ../../dist/baritone-api-$VERSION.jar +java -jar ../../proguard6.0.3/lib/proguard.jar @standalone.pro +mv Obfuscated/baritone-$VERSION.jar ../../dist/baritone-standalone-$VERSION.jar +mv baritone-$VERSION.jar ../../dist/baritone-unoptimized-$VERSION.jar +cd ../.. +shasum dist/* | tee dist/checksums.txt +jshon -s "$(cat dist/checksums.txt)" \ No newline at end of file diff --git a/scripts/proguard.pro b/scripts/proguard.pro new file mode 100644 index 00000000..bafdfc90 --- /dev/null +++ b/scripts/proguard.pro @@ -0,0 +1,368 @@ +-injars baritone-0.0.2.jar +-outjars Obfuscated + + +-keepattributes Signature +-keepattributes *Annotation* + +-optimizationpasses 10 +-verbose + +-allowaccessmodification # anything not kept can be changed from public to private and inlined etc +-overloadaggressively +-dontusemixedcaseclassnames + +# instead of obfing to a, b, c, obf to baritone.a, baritone.b, baritone.c so as to not conflict with minecraft's obfd classes +-flattenpackagehierarchy +-repackageclasses 'baritone' + +#-keep class baritone.behavior.** { *; } +-keep class baritone.api.** { *; } +#-keep class baritone.* { *; } +#-keep class baritone.pathing.goals.** { *; } + +# setting names are reflected from field names, so keep field names +-keepclassmembers class baritone.api.Settings { + public ; +} + +# need to keep mixin names +-keep class baritone.launch.** { *; } + +# copy all necessary libraries into tempLibraries to build +-libraryjars '/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/rt.jar' # this is the rt jar + +-libraryjars 'tempLibraries/1.12.2.jar' + +-libraryjars 'tempLibraries/authlib-1.5.25.jar' +-libraryjars 'tempLibraries/codecjorbis-20101023.jar' +-libraryjars 'tempLibraries/codecwav-20101023.jar' +-libraryjars 'tempLibraries/commons-codec-1.10.jar' +-libraryjars 'tempLibraries/commons-compress-1.8.1.jar' +-libraryjars 'tempLibraries/commons-io-2.5.jar' +-libraryjars 'tempLibraries/commons-lang3-3.5.jar' +-libraryjars 'tempLibraries/commons-logging-1.1.3.jar' +-libraryjars 'tempLibraries/fastutil-7.1.0.jar' +-libraryjars 'tempLibraries/gson-2.8.0.jar' +-libraryjars 'tempLibraries/guava-21.0.jar' +-libraryjars 'tempLibraries/httpclient-4.3.3.jar' +-libraryjars 'tempLibraries/httpcore-4.3.2.jar' +-libraryjars 'tempLibraries/icu4j-core-mojang-51.2.jar' +-libraryjars 'tempLibraries/java-objc-bridge-1.0.0-natives-osx.jar' +-libraryjars 'tempLibraries/java-objc-bridge-1.0.0.jar' +-libraryjars 'tempLibraries/jinput-2.0.5.jar' +-libraryjars 'tempLibraries/jinput-platform-2.0.5-natives-osx.jar' +-libraryjars 'tempLibraries/jna-4.4.0.jar' +-libraryjars 'tempLibraries/jopt-simple-5.0.3.jar' +-libraryjars 'tempLibraries/jsr305-3.0.1-sources.jar' +-libraryjars 'tempLibraries/jsr305-3.0.1.jar' +-libraryjars 'tempLibraries/jutils-1.0.0.jar' +-libraryjars 'tempLibraries/libraryjavasound-20101123.jar' +-libraryjars 'tempLibraries/librarylwjglopenal-20100824.jar' +-libraryjars 'tempLibraries/log4j-api-2.8.1.jar' +-libraryjars 'tempLibraries/log4j-core-2.8.1.jar' +-libraryjars 'tempLibraries/lwjgl-2.9.2-nightly-20140822.jar' +-libraryjars 'tempLibraries/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar' +-libraryjars 'tempLibraries/lwjgl_util-2.9.2-nightly-20140822.jar' +-libraryjars 'tempLibraries/netty-all-4.1.9.Final.jar' +-libraryjars 'tempLibraries/oshi-core-1.1.jar' +-libraryjars 'tempLibraries/patchy-1.1.jar' +-libraryjars 'tempLibraries/platform-3.4.0.jar' +-libraryjars 'tempLibraries/realms-1.10.22.jar' +-libraryjars 'tempLibraries/soundsystem-20120107.jar' +-libraryjars 'tempLibraries/text2speech-1.10.3.jar' + +-libraryjars 'tempLibraries/mixin-0.7.8-SNAPSHOT.jar' +-libraryjars 'tempLibraries/launchwrapper-1.12.jar' + + + + +# Keep - Applications. Keep all application classes, along with their 'main' +# methods. +-keepclasseswithmembers public class * { + public static void main(java.lang.String[]); +} + +# Also keep - Enumerations. Keep the special static methods that are required in +# enumeration classes. +-keepclassmembers enum * { + public static **[] values(); + public static ** valueOf(java.lang.String); +} + +# Also keep - Database drivers. Keep all implementations of java.sql.Driver. +-keep class * extends java.sql.Driver + +# Also keep - Swing UI L&F. Keep all extensions of javax.swing.plaf.ComponentUI, +# along with the special 'createUI' method. +-keep class * extends javax.swing.plaf.ComponentUI { + public static javax.swing.plaf.ComponentUI createUI(javax.swing.JComponent); +} + +# Keep names - Native method names. Keep all native class/method names. +-keepclasseswithmembers,includedescriptorclasses,allowshrinking class * { + native ; +} + +# Remove - System method calls. Remove all invocations of System +# methods without side effects whose return values are not used. +-assumenosideeffects public class java.lang.System { + public static long currentTimeMillis(); + static java.lang.Class getCallerClass(); + public static int identityHashCode(java.lang.Object); + public static java.lang.SecurityManager getSecurityManager(); + public static java.util.Properties getProperties(); + public static java.lang.String getProperty(java.lang.String); + public static java.lang.String getenv(java.lang.String); + public static java.lang.String mapLibraryName(java.lang.String); + public static java.lang.String getProperty(java.lang.String,java.lang.String); +} + +# Remove - Math method calls. Remove all invocations of Math +# methods without side effects whose return values are not used. +-assumenosideeffects public class java.lang.Math { + public static double sin(double); + public static double cos(double); + public static double tan(double); + public static double asin(double); + public static double acos(double); + public static double atan(double); + public static double toRadians(double); + public static double toDegrees(double); + public static double exp(double); + public static double log(double); + public static double log10(double); + public static double sqrt(double); + public static double cbrt(double); + public static double IEEEremainder(double,double); + public static double ceil(double); + public static double floor(double); + public static double rint(double); + public static double atan2(double,double); + public static double pow(double,double); + public static int round(float); + public static long round(double); + public static double random(); + public static int abs(int); + public static long abs(long); + public static float abs(float); + public static double abs(double); + public static int max(int,int); + public static long max(long,long); + public static float max(float,float); + public static double max(double,double); + public static int min(int,int); + public static long min(long,long); + public static float min(float,float); + public static double min(double,double); + public static double ulp(double); + public static float ulp(float); + public static double signum(double); + public static float signum(float); + public static double sinh(double); + public static double cosh(double); + public static double tanh(double); + public static double hypot(double,double); + public static double expm1(double); + public static double log1p(double); +} + +# Remove - Number method calls. Remove all invocations of Number +# methods without side effects whose return values are not used. +-assumenosideeffects public class java.lang.* extends java.lang.Number { + public static java.lang.String toString(byte); + public static java.lang.Byte valueOf(byte); + public static byte parseByte(java.lang.String); + public static byte parseByte(java.lang.String,int); + public static java.lang.Byte valueOf(java.lang.String,int); + public static java.lang.Byte valueOf(java.lang.String); + public static java.lang.Byte decode(java.lang.String); + public int compareTo(java.lang.Byte); + public static java.lang.String toString(short); + public static short parseShort(java.lang.String); + public static short parseShort(java.lang.String,int); + public static java.lang.Short valueOf(java.lang.String,int); + public static java.lang.Short valueOf(java.lang.String); + public static java.lang.Short valueOf(short); + public static java.lang.Short decode(java.lang.String); + public static short reverseBytes(short); + public int compareTo(java.lang.Short); + public static java.lang.String toString(int,int); + public static java.lang.String toHexString(int); + public static java.lang.String toOctalString(int); + public static java.lang.String toBinaryString(int); + public static java.lang.String toString(int); + public static int parseInt(java.lang.String,int); + public static int parseInt(java.lang.String); + public static java.lang.Integer valueOf(java.lang.String,int); + public static java.lang.Integer valueOf(java.lang.String); + public static java.lang.Integer valueOf(int); + public static java.lang.Integer getInteger(java.lang.String); + public static java.lang.Integer getInteger(java.lang.String,int); + public static java.lang.Integer getInteger(java.lang.String,java.lang.Integer); + public static java.lang.Integer decode(java.lang.String); + public static int highestOneBit(int); + public static int lowestOneBit(int); + public static int numberOfLeadingZeros(int); + public static int numberOfTrailingZeros(int); + public static int bitCount(int); + public static int rotateLeft(int,int); + public static int rotateRight(int,int); + public static int reverse(int); + public static int signum(int); + public static int reverseBytes(int); + public int compareTo(java.lang.Integer); + public static java.lang.String toString(long,int); + public static java.lang.String toHexString(long); + public static java.lang.String toOctalString(long); + public static java.lang.String toBinaryString(long); + public static java.lang.String toString(long); + public static long parseLong(java.lang.String,int); + public static long parseLong(java.lang.String); + public static java.lang.Long valueOf(java.lang.String,int); + public static java.lang.Long valueOf(java.lang.String); + public static java.lang.Long valueOf(long); + public static java.lang.Long decode(java.lang.String); + public static java.lang.Long getLong(java.lang.String); + public static java.lang.Long getLong(java.lang.String,long); + public static java.lang.Long getLong(java.lang.String,java.lang.Long); + public static long highestOneBit(long); + public static long lowestOneBit(long); + public static int numberOfLeadingZeros(long); + public static int numberOfTrailingZeros(long); + public static int bitCount(long); + public static long rotateLeft(long,int); + public static long rotateRight(long,int); + public static long reverse(long); + public static int signum(long); + public static long reverseBytes(long); + public int compareTo(java.lang.Long); + public static java.lang.String toString(float); + public static java.lang.String toHexString(float); + public static java.lang.Float valueOf(java.lang.String); + public static java.lang.Float valueOf(float); + public static float parseFloat(java.lang.String); + public static boolean isNaN(float); + public static boolean isInfinite(float); + public static int floatToIntBits(float); + public static int floatToRawIntBits(float); + public static float intBitsToFloat(int); + public static int compare(float,float); + public boolean isNaN(); + public boolean isInfinite(); + public int compareTo(java.lang.Float); + public static java.lang.String toString(double); + public static java.lang.String toHexString(double); + public static java.lang.Double valueOf(java.lang.String); + public static java.lang.Double valueOf(double); + public static double parseDouble(java.lang.String); + public static boolean isNaN(double); + public static boolean isInfinite(double); + public static long doubleToLongBits(double); + public static long doubleToRawLongBits(double); + public static double longBitsToDouble(long); + public static int compare(double,double); + public boolean isNaN(); + public boolean isInfinite(); + public int compareTo(java.lang.Double); + public byte byteValue(); + public short shortValue(); + public int intValue(); + public long longValue(); + public float floatValue(); + public double doubleValue(); + public int compareTo(java.lang.Object); + public boolean equals(java.lang.Object); + public int hashCode(); + public java.lang.String toString(); +} + +# Remove - String method calls. Remove all invocations of String +# methods without side effects whose return values are not used. +-assumenosideeffects public class java.lang.String { + public static java.lang.String copyValueOf(char[]); + public static java.lang.String copyValueOf(char[],int,int); + public static java.lang.String valueOf(boolean); + public static java.lang.String valueOf(char); + public static java.lang.String valueOf(char[]); + public static java.lang.String valueOf(char[],int,int); + public static java.lang.String valueOf(double); + public static java.lang.String valueOf(float); + public static java.lang.String valueOf(int); + public static java.lang.String valueOf(java.lang.Object); + public static java.lang.String valueOf(long); + public boolean contentEquals(java.lang.StringBuffer); + public boolean endsWith(java.lang.String); + public boolean equalsIgnoreCase(java.lang.String); + public boolean equals(java.lang.Object); + public boolean matches(java.lang.String); + public boolean regionMatches(boolean,int,java.lang.String,int,int); + public boolean regionMatches(int,java.lang.String,int,int); + public boolean startsWith(java.lang.String); + public boolean startsWith(java.lang.String,int); + public byte[] getBytes(); + public byte[] getBytes(java.lang.String); + public char charAt(int); + public char[] toCharArray(); + public int compareToIgnoreCase(java.lang.String); + public int compareTo(java.lang.Object); + public int compareTo(java.lang.String); + public int hashCode(); + public int indexOf(int); + public int indexOf(int,int); + public int indexOf(java.lang.String); + public int indexOf(java.lang.String,int); + public int lastIndexOf(int); + public int lastIndexOf(int,int); + public int lastIndexOf(java.lang.String); + public int lastIndexOf(java.lang.String,int); + public int length(); + public java.lang.CharSequence subSequence(int,int); + public java.lang.String concat(java.lang.String); + public java.lang.String replaceAll(java.lang.String,java.lang.String); + public java.lang.String replace(char,char); + public java.lang.String replaceFirst(java.lang.String,java.lang.String); + public java.lang.String[] split(java.lang.String); + public java.lang.String[] split(java.lang.String,int); + public java.lang.String substring(int); + public java.lang.String substring(int,int); + public java.lang.String toLowerCase(); + public java.lang.String toLowerCase(java.util.Locale); + public java.lang.String toString(); + public java.lang.String toUpperCase(); + public java.lang.String toUpperCase(java.util.Locale); + public java.lang.String trim(); +} + +# Remove - StringBuffer method calls. Remove all invocations of StringBuffer +# methods without side effects whose return values are not used. +-assumenosideeffects public class java.lang.StringBuffer { + public java.lang.String toString(); + public char charAt(int); + public int capacity(); + public int codePointAt(int); + public int codePointBefore(int); + public int indexOf(java.lang.String,int); + public int lastIndexOf(java.lang.String); + public int lastIndexOf(java.lang.String,int); + public int length(); + public java.lang.String substring(int); + public java.lang.String substring(int,int); +} + +# Remove - StringBuilder method calls. Remove all invocations of StringBuilder +# methods without side effects whose return values are not used. +-assumenosideeffects public class java.lang.StringBuilder { + public java.lang.String toString(); + public char charAt(int); + public int capacity(); + public int codePointAt(int); + public int codePointBefore(int); + public int indexOf(java.lang.String,int); + public int lastIndexOf(java.lang.String); + public int lastIndexOf(java.lang.String,int); + public int length(); + public java.lang.String substring(int); + public java.lang.String substring(int,int); +} diff --git a/xvfb_1.16.4-1_amd64.deb b/scripts/xvfb_1.16.4-1_amd64.deb similarity index 100% rename from xvfb_1.16.4-1_amd64.deb rename to scripts/xvfb_1.16.4-1_amd64.deb diff --git a/settings.gradle b/settings.gradle index c627d750..baa9dfc9 100755 --- a/settings.gradle +++ b/settings.gradle @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/api/java/baritone/api/BaritoneAPI.java b/src/api/java/baritone/api/BaritoneAPI.java new file mode 100644 index 00000000..aa9491db --- /dev/null +++ b/src/api/java/baritone/api/BaritoneAPI.java @@ -0,0 +1,99 @@ +/* + * 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 . + */ + +package baritone.api; + +import baritone.api.behavior.*; +import baritone.api.cache.IWorldProvider; + +/** + * API exposure for various things implemented in Baritone. + *

+ * W.I.P + * + * @author Brady + * @since 9/23/2018 + */ +public class BaritoneAPI { + + // General + private static final Settings settings = new Settings(); + private static IWorldProvider worldProvider; + + // Behaviors + private static IFollowBehavior followBehavior; + private static ILookBehavior lookBehavior; + private static IMemoryBehavior memoryBehavior; + private static IMineBehavior mineBehavior; + private static IPathingBehavior pathingBehavior; + + public static IFollowBehavior getFollowBehavior() { + return followBehavior; + } + + public static ILookBehavior getLookBehavior() { + return lookBehavior; + } + + public static IMemoryBehavior getMemoryBehavior() { + return memoryBehavior; + } + + public static IMineBehavior getMineBehavior() { + return mineBehavior; + } + + public static IPathingBehavior getPathingBehavior() { + return pathingBehavior; + } + + public static Settings getSettings() { + return settings; + } + + public static IWorldProvider getWorldProvider() { + return worldProvider; + } + + /** + * FOR INTERNAL USE ONLY + */ + public static void registerProviders( + IWorldProvider worldProvider + ) { + BaritoneAPI.worldProvider = worldProvider; + } + + /** + * FOR INTERNAL USE ONLY + */ + // @formatter:off + public static void registerDefaultBehaviors( + IFollowBehavior followBehavior, + ILookBehavior lookBehavior, + IMemoryBehavior memoryBehavior, + IMineBehavior mineBehavior, + IPathingBehavior pathingBehavior + ) { + BaritoneAPI.followBehavior = followBehavior; + BaritoneAPI.lookBehavior = lookBehavior; + BaritoneAPI.memoryBehavior = memoryBehavior; + BaritoneAPI.mineBehavior = mineBehavior; + BaritoneAPI.pathingBehavior = pathingBehavior; + } + // @formatter:on +} diff --git a/src/main/java/baritone/Settings.java b/src/api/java/baritone/api/Settings.java similarity index 63% rename from src/main/java/baritone/Settings.java rename to src/api/java/baritone/api/Settings.java index 78c2d4b3..ab758f40 100644 --- a/src/main/java/baritone/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -2,26 +2,31 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone; +package baritone.api; +import net.minecraft.client.Minecraft; import net.minecraft.init.Blocks; import net.minecraft.item.Item; +import net.minecraft.util.text.ITextComponent; +import java.awt.*; import java.lang.reflect.Field; import java.util.*; +import java.util.List; +import java.util.function.Consumer; /** * Baritone's settings @@ -29,6 +34,7 @@ import java.util.*; * @author leijurv */ public class Settings { + /** * Allow Baritone to break blocks */ @@ -62,6 +68,20 @@ public class Settings { */ public Setting assumeWalkOnWater = new Setting<>(false); + /** + * Assume step functionality; don't jump on an Ascend. + */ + public Setting assumeStep = new Setting<>(false); + + /** + * Assume safe walk functionality; don't sneak on a backplace traverse. + *

+ * Warning: if you do something janky like sneak-backplace from an ender chest, if this is true + * it won't sneak right click, it'll just right click, which means it'll open the chest instead of placing + * against it. That's why this defaults to off. + */ + public Setting assumeSafeWalk = new Setting<>(false); + /** * Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.) */ @@ -77,6 +97,29 @@ public class Settings { */ public Setting allowVines = new Setting<>(false); + /** + * Slab behavior is complicated, disable this for higher path reliability. Leave enabled if you have bottom slabs + * everywhere in your base. + */ + public Setting allowWalkOnBottomSlab = new Setting<>(true); + + /** + * You know what it is + *

+ * But it's very unreliable and falls off when cornering like all the time so. + */ + public Setting allowParkour = new Setting<>(false); + + /** + * Like parkour, but even more unreliable! + */ + public Setting allowParkourPlace = new Setting<>(false); + + /** + * For example, if you have Mining Fatigue or Haste, adjust the costs of breaking blocks accordingly. + */ + public Setting considerPotionEffects = new Setting<>(true); + /** * This is the big A* setting. * As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path. @@ -92,7 +135,7 @@ public class Settings { *

* Finding the optimal path is worth it, so it's the default. */ - public Setting costHeuristic = this.new Setting(3.5D); + public Setting costHeuristic = new Setting<>(3.5D); // a bunch of obscure internal A* settings that you probably don't want to change /** @@ -102,8 +145,9 @@ public class Settings { public Setting pathingMaxChunkBorderFetch = new Setting<>(50); /** - * See issue #18 * Set to 1.0 to effectively disable this feature + * + * @see Issue #18 */ public Setting backtrackCostFavoringCoefficient = new Setting<>(0.9); @@ -113,19 +157,20 @@ public class Settings { */ public Setting minimumImprovementRepropagation = new Setting<>(true); - /** - * Use a pythagorean metric (as opposed to the more accurate hybrid diagonal / traverse). - * You probably don't want this. It roughly triples nodes considered for no real advantage. - */ - public Setting pythagoreanMetric = new Setting<>(false); - /** * After calculating a path (potentially through cached chunks), artificially cut it off to just the part that is * entirely within currently loaded chunks. Improves path safety because cached chunks are heavily simplified. - * See issue #114 for why this is disabled. + * + * @see Issue #144 */ public Setting cutoffAtLoadBoundary = new Setting<>(false); + /** + * If a movement's cost increases by more than this amount between calculation and execution (due to changes + * in the environment / world), cancel and recalculate + */ + public Setting maxCostIncrease = new Setting<>(10D); + /** * Stop 5 movements before anything that made the path COST_INF. * For example, if lava has spread across the path, don't walk right up to it then recalculate, it might @@ -185,12 +230,12 @@ public class Settings { /** * Pathing can never take longer than this */ - public Setting pathTimeoutMS = new Setting<>(2000L); + public Setting pathTimeoutMS = new Setting<>(2000L); /** * Planning ahead while executing a segment can never take longer than this */ - public Setting planAheadTimeoutMS = new Setting<>(4000L); + public Setting planAheadTimeoutMS = new Setting<>(4000L); /** * For debugging, consider nodes much much slower @@ -200,12 +245,12 @@ public class Settings { /** * Milliseconds between each node */ - public Setting slowPathTimeDelayMS = new Setting<>(100L); + public Setting slowPathTimeDelayMS = new Setting<>(100L); /** * The alternative timeout number when slowPath is on */ - public Setting slowPathTimeoutMS = new Setting<>(40000L); + public Setting slowPathTimeoutMS = new Setting<>(40000L); /** * The big one. Download all chunks in simplified 2-bit format and save them for better very-long-distance pathing. @@ -277,6 +322,123 @@ public class Settings { */ public Setting prefix = new Setting<>(false); + /** + * {@code true}: can mine blocks when in inventory, chat, or tabbed away in ESC menu + *

+ * {@code false}: works on cosmic prisons + *

+ * LOL + */ + public Setting leftClickWorkaround = new Setting<>(true); + + /** + * Don't stop walking forward when you need to break blocks in your way + */ + public Setting walkWhileBreaking = new Setting<>(true); + + /** + * Rescan for the goal once every 5 ticks. + * Set to 0 to disable. + */ + public Setting mineGoalUpdateInterval = new Setting<>(5); + + /** + * Cancel the current path if the goal has changed, and the path originally ended in the goal but doesn't anymore. + *

+ * Currently only runs when either MineBehavior or FollowBehavior is active. + *

+ * For example, if Baritone is doing "mine iron_ore", the instant it breaks the ore (and it becomes air), that location + * is no longer a goal. This means that if this setting is true, it will stop there. If this setting were off, it would + * continue with its path, and walk into that location. The tradeoff is if this setting is true, it mines ores much faster + * since it doesn't waste any time getting into locations that no longer contain ores, but on the other hand, it misses + * some drops, and continues on without ever picking them up. + *

+ * Also on cosmic prisons this should be set to true since you don't actually mine the ore it just gets replaced with stone. + */ + public Setting cancelOnGoalInvalidation = new Setting<>(true); + + /** + * The "axis" command (aka GoalAxis) will go to a axis, or diagonal axis, at this Y level. + */ + public Setting axisHeight = new Setting<>(120); + + /** + * When mining block of a certain type, try to mine two at once instead of one. + * If the block above is also a goal block, set GoalBlock instead of GoalTwoBlocks + * If the block below is also a goal block, set GoalBlock to the position one down instead of GoalTwoBlocks + */ + public Setting forceInternalMining = new Setting<>(true); + + /** + * Modification to the previous setting, only has effect if forceInternalMining is true + * If true, only apply the previous setting if the block adjacent to the goal isn't air. + */ + public Setting internalMiningAirException = new Setting<>(true); + + /** + * The actual GoalNear is set this distance away from the entity you're following + *

+ * For example, set followOffsetDistance to 5 and followRadius to 0 to always stay precisely 5 blocks north of your follow target. + */ + public Setting followOffsetDistance = new Setting<>(0D); + + /** + * The actual GoalNear is set in this direction from the entity you're following + */ + public Setting followOffsetDirection = new Setting<>(0F); + + /** + * The radius (for the GoalNear) of how close to your target position you actually have to be + */ + public Setting followRadius = new Setting<>(3); + + /** + * The function that is called when Baritone will log to chat. This function can be added to + * via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting + * {@link Setting#value}; + */ + public Setting> logger = new Setting<>(Minecraft.getMinecraft().ingameGUI.getChatGUI()::printChatMessage); + + /** + * The color of the current path + */ + public Setting colorCurrentPath = new Setting<>(Color.RED); + + /** + * The color of the next path + */ + public Setting colorNextPath = new Setting<>(Color.MAGENTA); + + /** + * The color of the blocks to break + */ + public Setting colorBlocksToBreak = new Setting<>(Color.RED); + + /** + * The color of the blocks to place + */ + public Setting colorBlocksToPlace = new Setting<>(Color.GREEN); + + /** + * The color of the blocks to walk into + */ + public Setting colorBlocksToWalkInto = new Setting<>(Color.MAGENTA); + + /** + * The color of the best path so far + */ + public Setting colorBestPathSoFar = new Setting<>(Color.BLUE); + + /** + * The color of the path to the most recent considered node + */ + public Setting colorMostRecentConsidered = new Setting<>(Color.CYAN); + + /** + * The color of the goal box + */ + public Setting colorGoalBox = new Setting<>(Color.GREEN); + public final Map> byLowerName; public final List> allSettings; @@ -333,7 +495,7 @@ public class Settings { } } } catch (IllegalAccessException e) { - throw new RuntimeException(e); + throw new IllegalStateException(e); } byLowerName = Collections.unmodifiableMap(tmpByName); allSettings = Collections.unmodifiableList(tmpAll); diff --git a/src/api/java/baritone/api/behavior/IBehavior.java b/src/api/java/baritone/api/behavior/IBehavior.java new file mode 100644 index 00000000..aee144e2 --- /dev/null +++ b/src/api/java/baritone/api/behavior/IBehavior.java @@ -0,0 +1,27 @@ +/* + * 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 . + */ + +package baritone.api.behavior; + +import baritone.api.event.listener.AbstractGameEventListener; +import baritone.api.utils.interfaces.Toggleable; + +/** + * @author Brady + * @since 9/23/2018 + */ +public interface IBehavior extends AbstractGameEventListener, Toggleable {} diff --git a/src/api/java/baritone/api/behavior/IFollowBehavior.java b/src/api/java/baritone/api/behavior/IFollowBehavior.java new file mode 100644 index 00000000..c960fab3 --- /dev/null +++ b/src/api/java/baritone/api/behavior/IFollowBehavior.java @@ -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 . + */ + +package baritone.api.behavior; + +import net.minecraft.entity.Entity; + +/** + * @author Brady + * @since 9/23/2018 + */ +public interface IFollowBehavior extends IBehavior { + + /** + * Set the follow target to the specified entity; + * + * @param entity The entity to follow + */ + void follow(Entity entity); + + /** + * @return The entity that is currently being followed + */ + Entity following(); + + /** + * Cancels the follow behavior, this will clear the current follow target. + */ + void cancel(); +} diff --git a/src/api/java/baritone/api/behavior/ILookBehavior.java b/src/api/java/baritone/api/behavior/ILookBehavior.java new file mode 100644 index 00000000..b5b5d63b --- /dev/null +++ b/src/api/java/baritone/api/behavior/ILookBehavior.java @@ -0,0 +1,39 @@ +/* + * 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 . + */ + +package baritone.api.behavior; + +import baritone.api.utils.Rotation; + +/** + * @author Brady + * @since 9/23/2018 + */ +public interface ILookBehavior extends IBehavior { + + /** + * Updates the current {@link ILookBehavior} target to target + * the specified rotations on the next tick. If force is {@code true}, + * then freeLook will be overriden and angles will be set regardless. + * If any sort of block interaction is required, force should be {@code true}, + * otherwise, it should be {@code false}; + * + * @param rotation The target rotations + * @param force Whether or not to "force" the rotations + */ + void updateTarget(Rotation rotation, boolean force); +} diff --git a/src/api/java/baritone/api/behavior/IMemoryBehavior.java b/src/api/java/baritone/api/behavior/IMemoryBehavior.java new file mode 100644 index 00000000..ea5e9007 --- /dev/null +++ b/src/api/java/baritone/api/behavior/IMemoryBehavior.java @@ -0,0 +1,36 @@ +/* + * 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 . + */ + +package baritone.api.behavior; + +import baritone.api.behavior.memory.IRememberedInventory; +import net.minecraft.util.math.BlockPos; + +/** + * @author Brady + * @since 9/23/2018 + */ +public interface IMemoryBehavior extends IBehavior { + + /** + * Gets a remembered inventory by its block position. + * + * @param pos The position of the container block + * @return The remembered inventory + */ + IRememberedInventory getInventoryByPos(BlockPos pos); +} diff --git a/src/api/java/baritone/api/behavior/IMineBehavior.java b/src/api/java/baritone/api/behavior/IMineBehavior.java new file mode 100644 index 00000000..78ab6d6a --- /dev/null +++ b/src/api/java/baritone/api/behavior/IMineBehavior.java @@ -0,0 +1,70 @@ +/* + * 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 . + */ + +package baritone.api.behavior; + +import net.minecraft.block.Block; + +/** + * @author Brady + * @since 9/23/2018 + */ +public interface IMineBehavior extends IBehavior { + + /** + * Begin to search for and mine the specified blocks until + * the number of specified items to get from the blocks that + * are mined. This is based on the first target block to mine. + * + * @param quantity The number of items to get from blocks mined + * @param blocks The blocks to mine + */ + void mine(int quantity, String... blocks); + + /** + * Begin to search for and mine the specified blocks until + * the number of specified items to get from the blocks that + * are mined. This is based on the first target block to mine. + * + * @param quantity The number of items to get from blocks mined + * @param blocks The blocks to mine + */ + void mine(int quantity, Block... blocks); + + /** + * Begin to search for and mine the specified blocks. + * + * @param blocks The blocks to mine + */ + default void mine(String... blocks) { + this.mine(0, blocks); + } + + /** + * Begin to search for and mine the specified blocks. + * + * @param blocks The blocks to mine + */ + default void mine(Block... blocks) { + this.mine(0, blocks); + } + + /** + * Cancels the current mining task + */ + void cancel(); +} diff --git a/src/api/java/baritone/api/behavior/IPathingBehavior.java b/src/api/java/baritone/api/behavior/IPathingBehavior.java new file mode 100644 index 00000000..e21d999d --- /dev/null +++ b/src/api/java/baritone/api/behavior/IPathingBehavior.java @@ -0,0 +1,68 @@ +/* + * 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 . + */ + +package baritone.api.behavior; + +import baritone.api.pathing.goals.Goal; + +import java.util.Optional; + +/** + * @author Brady + * @since 9/23/2018 + */ +public interface IPathingBehavior extends IBehavior { + + /** + * Returns the estimated remaining ticks in the current pathing + * segment. Given that the return type is an optional, {@link Optional#empty()} + * will be returned in the case that there is no current segment being pathed. + * + * @return The estimated remaining ticks in the current segment. + */ + Optional ticksRemainingInSegment(); + + /** + * Sets the pathing goal. + * + * @param goal The pathing goal + */ + void setGoal(Goal goal); + + /** + * @return The current pathing goal + */ + Goal getGoal(); + + /** + * Begins pathing. Calculation will start in a new thread, and once completed, + * movement will commence. Returns whether or not the operation was successful. + * + * @return Whether or not the operation was successful + */ + boolean path(); + + /** + * @return Whether or not a path is currently being executed. + */ + boolean isPathing(); + + /** + * Cancels the pathing behavior or the current path calculation. + */ + void cancel(); +} diff --git a/src/api/java/baritone/api/behavior/memory/IRememberedInventory.java b/src/api/java/baritone/api/behavior/memory/IRememberedInventory.java new file mode 100644 index 00000000..c57ded91 --- /dev/null +++ b/src/api/java/baritone/api/behavior/memory/IRememberedInventory.java @@ -0,0 +1,39 @@ +/* + * 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 . + */ + +package baritone.api.behavior.memory; + +import net.minecraft.item.ItemStack; + +import java.util.List; + +/** + * @author Brady + * @since 9/23/2018 + */ +public interface IRememberedInventory { + + /** + * @return The contents of this inventory + */ + List getContents(); + + /** + * @return The number of slots in this inventory + */ + int getSize(); +} diff --git a/src/main/java/baritone/utils/pathing/IBlockTypeAccess.java b/src/api/java/baritone/api/cache/IBlockTypeAccess.java similarity index 72% rename from src/main/java/baritone/utils/pathing/IBlockTypeAccess.java rename to src/api/java/baritone/api/cache/IBlockTypeAccess.java index 2bd29cfd..242ff154 100644 --- a/src/main/java/baritone/utils/pathing/IBlockTypeAccess.java +++ b/src/api/java/baritone/api/cache/IBlockTypeAccess.java @@ -2,22 +2,21 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.utils.pathing; +package baritone.api.cache; -import baritone.utils.Helper; import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; @@ -25,7 +24,7 @@ import net.minecraft.util.math.BlockPos; * @author Brady * @since 8/4/2018 2:01 AM */ -public interface IBlockTypeAccess extends Helper { +public interface IBlockTypeAccess { IBlockState getBlock(int x, int y, int z); diff --git a/src/api/java/baritone/api/cache/ICachedRegion.java b/src/api/java/baritone/api/cache/ICachedRegion.java new file mode 100644 index 00000000..5f9199fa --- /dev/null +++ b/src/api/java/baritone/api/cache/ICachedRegion.java @@ -0,0 +1,49 @@ +/* + * 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 . + */ + +package baritone.api.cache; + +/** + * @author Brady + * @since 9/24/2018 + */ +public interface ICachedRegion extends IBlockTypeAccess { + + /** + * Returns whether or not the block at the specified X and Z coordinates + * is cached in this world. Similar to {@link ICachedWorld#isCached(int, int)}, + * however, the block coordinates should in on a scale from 0 to 511 (inclusive) + * because region sizes are 512x512 blocks. + * + * @see ICachedWorld#isCached(int, int) + * + * @param blockX The block X coordinate + * @param blockZ The block Z coordinate + * @return Whether or not the specified XZ location is cached + */ + boolean isCached(int blockX, int blockZ); + + /** + * The X coordinate of this region + */ + int getX(); + + /** + * The Z coordinate of this region + */ + int getZ(); +} diff --git a/src/api/java/baritone/api/cache/ICachedWorld.java b/src/api/java/baritone/api/cache/ICachedWorld.java new file mode 100644 index 00000000..f8196ebb --- /dev/null +++ b/src/api/java/baritone/api/cache/ICachedWorld.java @@ -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 . + */ + +package baritone.api.cache; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.Chunk; + +import java.util.LinkedList; + +/** + * @author Brady + * @since 9/24/2018 + */ +public interface ICachedWorld { + + /** + * Returns the region at the specified region coordinates + * + * @param regionX The region X coordinate + * @param regionZ The region Z coordinate + * @return The region located at the specified coordinates + */ + ICachedRegion getRegion(int regionX, int regionZ); + + /** + * Queues the specified chunk for packing. This entails reading the contents + * of the chunk, then packing the data into the 2-bit format, and storing that + * in this cached world. + * + * @param chunk The chunk to pack and store + */ + void queueForPacking(Chunk chunk); + + /** + * Returns whether or not the block at the specified X and Z coordinates + * is cached in this world. + * + * @param blockX The block X coordinate + * @param blockZ The block Z coordinate + * @return Whether or not the specified XZ location is cached + */ + boolean isCached(int blockX, int blockZ); + + /** + * Scans the cached chunks for location of the specified special block. The + * information that is returned by this method may not be up to date, because + * older cached chunks can contain data that is much more likely to have changed. + * + * @param block The special block to search for + * @param maximum The maximum number of position results to receive + * @param maxRegionDistanceSq The maximum region distance, squared + * @return The locations found that match the special block + */ + LinkedList getLocationsOf(String block, int maximum, int maxRegionDistanceSq); + + /** + * Reloads all of the cached regions in this world from disk. Anything that is not saved + * will be lost. This operation does not execute in a new thread by default. + */ + void reloadAllFromDisk(); + + /** + * Saves all of the cached regions in this world to disk. This operation does not execute + * in a new thread by default. + */ + void save(); +} diff --git a/src/api/java/baritone/api/cache/IWaypoint.java b/src/api/java/baritone/api/cache/IWaypoint.java new file mode 100644 index 00000000..01df2a48 --- /dev/null +++ b/src/api/java/baritone/api/cache/IWaypoint.java @@ -0,0 +1,111 @@ +/* + * 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 . + */ + +package baritone.api.cache; + +import net.minecraft.util.math.BlockPos; +import org.apache.commons.lang3.ArrayUtils; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +/** + * A marker for a position in the world. + * + * @author Brady + * @since 9/24/2018 + */ +public interface IWaypoint { + + /** + * @return The label for this waypoint + */ + String getName(); + + /** + * Returns the tag for this waypoint. The tag is a category + * for the waypoint in a sense, it describes the source of + * the waypoint. + * + * @return The waypoint tag + */ + Tag getTag(); + + /** + * Returns the unix epoch time in milliseconds that this waypoint + * was created. This value should only be set once, when the waypoint + * is initially created, and not when it is being loaded from file. + * + * @return The unix epoch milliseconds that this waypoint was created + */ + long getCreationTimestamp(); + + /** + * Returns the actual block position of this waypoint. + * + * @return The block position of this waypoint + */ + BlockPos getLocation(); + + enum Tag { + + /** + * Tag indicating a position explictly marked as a home base + */ + HOME("home", "base"), + + /** + * Tag indicating a position that the local player has died at + */ + DEATH("death"), + + /** + * Tag indicating a bed position + */ + BED("bed", "spawn"), + + /** + * Tag indicating that the waypoint was user-created + */ + USER("user"); + + /** + * A list of all of the + */ + private static final List TAG_LIST = Collections.unmodifiableList(Arrays.asList(Tag.values())); + + /** + * The names for the tag, anything that the tag can be referred to as. + */ + private final String[] names; + + Tag(String... names) { + this.names = names; + } + + /** + * Finds a tag from one of the names that could be used to identify said tag. + * + * @param name The name of the tag + * @return The tag, if one is found, otherwise, {@code null} + */ + public static Tag fromString(String name) { + return TAG_LIST.stream().filter(tag -> ArrayUtils.contains(tag.names, name.toLowerCase())).findFirst().orElse(null); + } + } +} diff --git a/src/api/java/baritone/api/cache/IWaypointCollection.java b/src/api/java/baritone/api/cache/IWaypointCollection.java new file mode 100644 index 00000000..051b199e --- /dev/null +++ b/src/api/java/baritone/api/cache/IWaypointCollection.java @@ -0,0 +1,68 @@ +/* + * 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 . + */ + +package baritone.api.cache; + +import java.util.Set; + +/** + * @author Brady + * @since 9/24/2018 + */ +public interface IWaypointCollection { + + /** + * Adds a waypoint to this collection + * + * @param waypoint The waypoint + */ + void addWaypoint(IWaypoint waypoint); + + /** + * Removes a waypoint from this collection + * + * @param waypoint The waypoint + */ + void removeWaypoint(IWaypoint waypoint); + + /** + * Gets the most recently created waypoint by the specified {@link IWaypoint.Tag} + * + * @param tag The tag + * @return The most recently created waypoint with the specified tag + */ + IWaypoint getMostRecentByTag(IWaypoint.Tag tag); + + /** + * Gets all of the waypoints that have the specified tag + * + * @see IWaypointCollection#getAllWaypoints() + * + * @param tag The tag + * @return All of the waypoints with the specified tag + */ + Set getByTag(IWaypoint.Tag tag); + + /** + * Gets all of the waypoints in this collection, regardless of the tag. + * + * @see IWaypointCollection#getByTag(IWaypoint.Tag) + * + * @return All of the waypoints in this collection + */ + Set getAllWaypoints(); +} diff --git a/src/api/java/baritone/api/cache/IWorldData.java b/src/api/java/baritone/api/cache/IWorldData.java new file mode 100644 index 00000000..1031ba92 --- /dev/null +++ b/src/api/java/baritone/api/cache/IWorldData.java @@ -0,0 +1,39 @@ +/* + * 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 . + */ + +package baritone.api.cache; + +/** + * @author Brady + * @since 9/24/2018 + */ +public interface IWorldData { + + /** + * Returns the cached world for this world. A cached world is a simplified format + * of a regular world, intended for use on multiplayer servers where chunks are not + * traditionally stored to disk, allowing for long distance pathing with minimal disk usage. + */ + ICachedWorld getCachedWorld(); + + /** + * Returns the waypoint collection for this world. + * + * @return The waypoint collection for this world + */ + IWaypointCollection getWaypoints(); +} diff --git a/src/api/java/baritone/api/cache/IWorldProvider.java b/src/api/java/baritone/api/cache/IWorldProvider.java new file mode 100644 index 00000000..0e54ef46 --- /dev/null +++ b/src/api/java/baritone/api/cache/IWorldProvider.java @@ -0,0 +1,32 @@ +/* + * 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 . + */ + +package baritone.api.cache; + +/** + * @author Brady + * @since 9/24/2018 + */ +public interface IWorldProvider { + + /** + * Returns the data of the currently loaded world + * + * @return The current world data + */ + IWorldData getCurrentWorld(); +} diff --git a/src/main/java/baritone/api/event/events/BlockInteractEvent.java b/src/api/java/baritone/api/event/events/BlockInteractEvent.java similarity index 87% rename from src/main/java/baritone/api/event/events/BlockInteractEvent.java rename to src/api/java/baritone/api/event/events/BlockInteractEvent.java index 2c57952c..cc98a6ba 100644 --- a/src/main/java/baritone/api/event/events/BlockInteractEvent.java +++ b/src/api/java/baritone/api/event/events/BlockInteractEvent.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/java/baritone/api/event/events/ChatEvent.java b/src/api/java/baritone/api/event/events/ChatEvent.java similarity index 82% rename from src/main/java/baritone/api/event/events/ChatEvent.java rename to src/api/java/baritone/api/event/events/ChatEvent.java index 87a81e70..e103377f 100644 --- a/src/main/java/baritone/api/event/events/ChatEvent.java +++ b/src/api/java/baritone/api/event/events/ChatEvent.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/java/baritone/api/event/events/ChunkEvent.java b/src/api/java/baritone/api/event/events/ChunkEvent.java similarity index 90% rename from src/main/java/baritone/api/event/events/ChunkEvent.java rename to src/api/java/baritone/api/event/events/ChunkEvent.java index 1f8c6c39..5c22d830 100644 --- a/src/main/java/baritone/api/event/events/ChunkEvent.java +++ b/src/api/java/baritone/api/event/events/ChunkEvent.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/java/baritone/api/event/events/PacketEvent.java b/src/api/java/baritone/api/event/events/PacketEvent.java similarity index 84% rename from src/main/java/baritone/api/event/events/PacketEvent.java rename to src/api/java/baritone/api/event/events/PacketEvent.java index 77310994..9516db4b 100644 --- a/src/main/java/baritone/api/event/events/PacketEvent.java +++ b/src/api/java/baritone/api/event/events/PacketEvent.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/java/baritone/api/event/events/PathEvent.java b/src/api/java/baritone/api/event/events/PathEvent.java similarity index 77% rename from src/main/java/baritone/api/event/events/PathEvent.java rename to src/api/java/baritone/api/event/events/PathEvent.java index a3fee3f8..0eef0665 100644 --- a/src/main/java/baritone/api/event/events/PathEvent.java +++ b/src/api/java/baritone/api/event/events/PathEvent.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -28,5 +28,6 @@ public enum PathEvent { AT_GOAL, PATH_FINISHED_NEXT_STILL_CALCULATING, NEXT_CALC_FAILED, - DISCARD_NEXT + DISCARD_NEXT, + CANCELED; } diff --git a/src/main/java/baritone/api/event/events/PlayerUpdateEvent.java b/src/api/java/baritone/api/event/events/PlayerUpdateEvent.java similarity index 82% rename from src/main/java/baritone/api/event/events/PlayerUpdateEvent.java rename to src/api/java/baritone/api/event/events/PlayerUpdateEvent.java index 59bdf702..6ac08bdd 100644 --- a/src/main/java/baritone/api/event/events/PlayerUpdateEvent.java +++ b/src/api/java/baritone/api/event/events/PlayerUpdateEvent.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/java/baritone/api/event/events/RenderEvent.java b/src/api/java/baritone/api/event/events/RenderEvent.java similarity index 81% rename from src/main/java/baritone/api/event/events/RenderEvent.java rename to src/api/java/baritone/api/event/events/RenderEvent.java index ef693e2a..b5a77276 100644 --- a/src/main/java/baritone/api/event/events/RenderEvent.java +++ b/src/api/java/baritone/api/event/events/RenderEvent.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/api/java/baritone/api/event/events/RotationMoveEvent.java b/src/api/java/baritone/api/event/events/RotationMoveEvent.java new file mode 100644 index 00000000..ef6d9b7e --- /dev/null +++ b/src/api/java/baritone/api/event/events/RotationMoveEvent.java @@ -0,0 +1,75 @@ +/* + * 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 . + */ + +package baritone.api.event.events; + +import baritone.api.event.events.type.EventState; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; + +/** + * @author Brady + * @since 8/21/2018 + */ +public final class RotationMoveEvent { + + /** + * The type of event + */ + private final Type type; + + /** + * The state of the event + */ + private final EventState state; + + public RotationMoveEvent(EventState state, Type type) { + this.state = state; + this.type = type; + } + + /** + * @return The state of the event + */ + public final EventState getState() { + return this.state; + } + + /** + * @return The type of the event + */ + public final Type getType() { + return this.type; + } + + public enum Type { + + /** + * Called when the player's motion is updated. + * + * @see Entity#moveRelative(float, float, float, float) + */ + MOTION_UPDATE, + + /** + * Called when the player jumps. + * + * @see EntityLivingBase#jump + */ + JUMP + } +} diff --git a/src/main/java/baritone/api/event/events/TickEvent.java b/src/api/java/baritone/api/event/events/TickEvent.java similarity index 72% rename from src/main/java/baritone/api/event/events/TickEvent.java rename to src/api/java/baritone/api/event/events/TickEvent.java index e82c31ad..da8f8878 100644 --- a/src/main/java/baritone/api/event/events/TickEvent.java +++ b/src/api/java/baritone/api/event/events/TickEvent.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -23,10 +23,22 @@ public final class TickEvent { private final EventState state; private final Type type; + private final int count; + + private static int overallTickCount; public TickEvent(EventState state, Type type) { this.state = state; this.type = type; + this.count = incrementCount(); + } + + private static synchronized int incrementCount() { + return overallTickCount++; + } + + public int getCount() { + return count; } public Type getType() { diff --git a/src/main/java/baritone/api/event/events/WorldEvent.java b/src/api/java/baritone/api/event/events/WorldEvent.java similarity index 86% rename from src/main/java/baritone/api/event/events/WorldEvent.java rename to src/api/java/baritone/api/event/events/WorldEvent.java index 454755fe..c7c7e102 100644 --- a/src/main/java/baritone/api/event/events/WorldEvent.java +++ b/src/api/java/baritone/api/event/events/WorldEvent.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/java/baritone/api/event/events/type/Cancellable.java b/src/api/java/baritone/api/event/events/type/Cancellable.java similarity index 82% rename from src/main/java/baritone/api/event/events/type/Cancellable.java rename to src/api/java/baritone/api/event/events/type/Cancellable.java index 4c26f8f8..331870c6 100644 --- a/src/main/java/baritone/api/event/events/type/Cancellable.java +++ b/src/api/java/baritone/api/event/events/type/Cancellable.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/java/baritone/api/event/events/type/EventState.java b/src/api/java/baritone/api/event/events/type/EventState.java similarity index 75% rename from src/main/java/baritone/api/event/events/type/EventState.java rename to src/api/java/baritone/api/event/events/type/EventState.java index a7fccff1..10b633bd 100644 --- a/src/main/java/baritone/api/event/events/type/EventState.java +++ b/src/api/java/baritone/api/event/events/type/EventState.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -31,7 +31,7 @@ public enum EventState { /** * Indicates that whatever movement the event is being - * dispatched as a result of has already occured. + * dispatched as a result of has already occurred. */ POST } diff --git a/src/main/java/baritone/api/event/listener/AbstractGameEventListener.java b/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java similarity index 62% rename from src/main/java/baritone/api/event/listener/AbstractGameEventListener.java rename to src/api/java/baritone/api/event/listener/AbstractGameEventListener.java index b47468bd..6af8e402 100644 --- a/src/main/java/baritone/api/event/listener/AbstractGameEventListener.java +++ b/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java @@ -2,33 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -75,10 +58,7 @@ public interface AbstractGameEventListener extends IGameEventListener { default void onReceivePacket(PacketEvent event) {} @Override - default void onQueryItemSlotForBlocks(ItemSlotEvent event) {} - - @Override - default void onPlayerRelativeMove(RelativeMoveEvent event) {} + default void onPlayerRotationMove(RotationMoveEvent event) {} @Override default void onBlockInteract(BlockInteractEvent event) {} diff --git a/src/main/java/baritone/api/event/listener/IGameEventListener.java b/src/api/java/baritone/api/event/listener/IGameEventListener.java similarity index 73% rename from src/main/java/baritone/api/event/listener/IGameEventListener.java rename to src/api/java/baritone/api/event/listener/IGameEventListener.java index 9be19aab..b1dda0de 100644 --- a/src/main/java/baritone/api/event/listener/IGameEventListener.java +++ b/src/api/java/baritone/api/event/listener/IGameEventListener.java @@ -2,33 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -36,7 +19,6 @@ package baritone.api.event.listener; import baritone.api.event.events.*; import io.netty.util.concurrent.GenericFutureListener; -import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.gui.GuiGameOver; @@ -44,7 +26,7 @@ import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.settings.GameSettings; import net.minecraft.entity.Entity; -import net.minecraft.entity.player.InventoryPlayer; +import net.minecraft.entity.EntityLivingBase; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.util.text.ITextComponent; @@ -110,6 +92,8 @@ public interface IGameEventListener { * Runs before a outbound packet is sent * * @see NetworkManager#dispatchPacket(Packet, GenericFutureListener[]) + * @see Packet + * @see GenericFutureListener */ void onSendPacket(PacketEvent event); @@ -117,23 +101,19 @@ public interface IGameEventListener { * Runs before an inbound packet is processed * * @see NetworkManager#dispatchPacket(Packet, GenericFutureListener[]) + * @see Packet + * @see GenericFutureListener */ void onReceivePacket(PacketEvent event); - /** - * Run when a query is made for a player's inventory current slot in the context of blocks - * - * @see InventoryPlayer#getDestroySpeed(IBlockState) - * @see InventoryPlayer#canHarvestBlock(IBlockState) - */ - void onQueryItemSlotForBlocks(ItemSlotEvent event); - /** * Run once per game tick from before and after the player's moveRelative method is called + * and before and after the player jumps. * * @see Entity#moveRelative(float, float, float, float) + * @see EntityLivingBase#jump() */ - void onPlayerRelativeMove(RelativeMoveEvent event); + void onPlayerRotationMove(RotationMoveEvent event); /** * Called when the local player interacts with a block, whether it is breaking or opening/placing. @@ -147,6 +127,7 @@ public interface IGameEventListener { * Called when the local player dies, as indicated by the creation of the {@link GuiGameOver} screen. * * @see GuiGameOver(ITextComponent) + * @see ITextComponent */ void onPlayerDeath(); diff --git a/src/main/java/baritone/pathing/goals/Goal.java b/src/api/java/baritone/api/pathing/goals/Goal.java similarity index 63% rename from src/main/java/baritone/pathing/goals/Goal.java rename to src/api/java/baritone/api/pathing/goals/Goal.java index 4057a733..38cfb9d7 100644 --- a/src/main/java/baritone/pathing/goals/Goal.java +++ b/src/api/java/baritone/api/pathing/goals/Goal.java @@ -2,22 +2,21 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.pathing.goals; +package baritone.api.pathing.goals; -import baritone.pathing.movement.ActionCosts; import net.minecraft.util.math.BlockPos; /** @@ -25,22 +24,28 @@ import net.minecraft.util.math.BlockPos; * * @author leijurv */ -public interface Goal extends ActionCosts { +public interface Goal { /** * Returns whether or not the specified position * meets the requirement for this goal based. * - * @param pos The position * @return Whether or not it satisfies this goal */ - boolean isInGoal(BlockPos pos); + boolean isInGoal(int x, int y, int z); /** * Estimate the number of ticks it will take to get to the goal * - * @param pos The * @return The estimate number of ticks to satisfy the goal */ - double heuristic(BlockPos pos); + double heuristic(int x, int y, int z); + + default boolean isInGoal(BlockPos pos) { + return isInGoal(pos.getX(), pos.getY(), pos.getZ()); + } + + default double heuristic(BlockPos pos) { + return heuristic(pos.getX(), pos.getY(), pos.getZ()); + } } diff --git a/src/api/java/baritone/api/pathing/goals/GoalAxis.java b/src/api/java/baritone/api/pathing/goals/GoalAxis.java new file mode 100644 index 00000000..d8811cf9 --- /dev/null +++ b/src/api/java/baritone/api/pathing/goals/GoalAxis.java @@ -0,0 +1,49 @@ +/* + * 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 . + */ + +package baritone.api.pathing.goals; + +import baritone.api.BaritoneAPI; + +public class GoalAxis implements Goal { + + private static final double SQRT_2_OVER_2 = Math.sqrt(2) / 2; + + @Override + public boolean isInGoal(int x, int y, int z) { + return y == BaritoneAPI.getSettings().axisHeight.get() && (x == 0 || z == 0 || Math.abs(x) == Math.abs(z)); + } + + @Override + public double heuristic(int x0, int y, int z0) { + int x = Math.abs(x0); + int z = Math.abs(z0); + + int shrt = Math.min(x, z); + int lng = Math.max(x, z); + int diff = lng - shrt; + + double flatAxisDistance = Math.min(x, Math.min(z, diff * SQRT_2_OVER_2)); + + return flatAxisDistance * BaritoneAPI.getSettings().costHeuristic.get() + GoalYLevel.calculate(BaritoneAPI.getSettings().axisHeight.get(), y); + } + + @Override + public String toString() { + return "GoalAxis"; + } +} diff --git a/src/main/java/baritone/pathing/goals/GoalBlock.java b/src/api/java/baritone/api/pathing/goals/GoalBlock.java similarity index 64% rename from src/main/java/baritone/pathing/goals/GoalBlock.java rename to src/api/java/baritone/api/pathing/goals/GoalBlock.java index 78d7b87d..e0a60b59 100644 --- a/src/main/java/baritone/pathing/goals/GoalBlock.java +++ b/src/api/java/baritone/api/pathing/goals/GoalBlock.java @@ -2,21 +2,22 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.pathing.goals; +package baritone.api.pathing.goals; +import baritone.api.utils.interfaces.IGoalRenderPos; import net.minecraft.util.math.BlockPos; /** @@ -24,7 +25,7 @@ import net.minecraft.util.math.BlockPos; * * @author leijurv */ -public class GoalBlock implements Goal { +public class GoalBlock implements Goal, IGoalRenderPos { /** * The X block position of this goal @@ -52,36 +53,27 @@ public class GoalBlock implements Goal { } @Override - public boolean isInGoal(BlockPos pos) { - return pos.getX() == this.x && pos.getY() == this.y && pos.getZ() == this.z; + public boolean isInGoal(int x, int y, int z) { + return x == this.x && y == this.y && z == this.z; } - /** - * The min range value over which to begin considering Y coordinate in the heuristic - */ - private static final double MIN = 20; - - /** - * The max range value over which to begin considering Y coordinate in the heuristic - */ - private static final double MAX = 150; - @Override - public double heuristic(BlockPos pos) { - int xDiff = pos.getX() - this.x; - int yDiff = pos.getY() - this.y; - int zDiff = pos.getZ() - this.z; + public double heuristic(int x, int y, int z) { + int xDiff = x - this.x; + int yDiff = y - this.y; + int zDiff = z - this.z; return calculate(xDiff, yDiff, zDiff); } @Override public String toString() { - return "Goal{x=" + x + ",y=" + y + ",z=" + z + "}"; + return "GoalBlock{x=" + x + ",y=" + y + ",z=" + z + "}"; } /** * @return The position of this goal as a {@link BlockPos} */ + @Override public BlockPos getGoalPos() { return new BlockPos(x, y, z); } @@ -91,7 +83,7 @@ public class GoalBlock implements Goal { // if yDiff is 1 that means that pos.getY()-this.y==1 which means that we're 1 block below where we should be // therefore going from 0,0,0 to a GoalYLevel of pos.getY()-this.y is accurate - heuristic += new GoalYLevel(yDiff).heuristic(new BlockPos(0, 0, 0)); + heuristic += GoalYLevel.calculate(yDiff, 0); //use the pythagorean and manhattan mixture from GoalXZ heuristic += GoalXZ.calculate(xDiff, zDiff); diff --git a/src/main/java/baritone/pathing/goals/GoalComposite.java b/src/api/java/baritone/api/pathing/goals/GoalComposite.java similarity index 70% rename from src/main/java/baritone/pathing/goals/GoalComposite.java rename to src/api/java/baritone/api/pathing/goals/GoalComposite.java index 558e124e..2926b852 100644 --- a/src/main/java/baritone/pathing/goals/GoalComposite.java +++ b/src/api/java/baritone/api/pathing/goals/GoalComposite.java @@ -2,24 +2,25 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.pathing.goals; +package baritone.api.pathing.goals; + +import net.minecraft.util.math.BlockPos; import java.util.Arrays; import java.util.Collection; -import net.minecraft.util.math.BlockPos; /** * A composite of many goals, any one of which satisfies the composite. @@ -33,7 +34,7 @@ public class GoalComposite implements Goal { /** * An array of goals that any one of must be satisfied */ - public final Goal[] goals; + private final Goal[] goals; public GoalComposite(Goal... goals) { this.goals = goals; @@ -48,15 +49,21 @@ public class GoalComposite implements Goal { } @Override - public boolean isInGoal(BlockPos pos) { - return Arrays.stream(this.goals).anyMatch(goal -> goal.isInGoal(pos)); + public boolean isInGoal(int x, int y, int z) { + for (Goal goal : goals) { + if (goal.isInGoal(x, y, z)) { + return true; + } + } + return false; } @Override - public double heuristic(BlockPos pos) { + public double heuristic(int x, int y, int z) { double min = Double.MAX_VALUE; for (Goal g : goals) { - min = Math.min(min, g.heuristic(pos)); // whichever is closest + // TODO technically this isn't admissible...? + min = Math.min(min, g.heuristic(x, y, z)); // whichever is closest } return min; } diff --git a/src/api/java/baritone/api/pathing/goals/GoalGetToBlock.java b/src/api/java/baritone/api/pathing/goals/GoalGetToBlock.java new file mode 100644 index 00000000..959b6fcc --- /dev/null +++ b/src/api/java/baritone/api/pathing/goals/GoalGetToBlock.java @@ -0,0 +1,69 @@ +/* + * 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 . + */ + +package baritone.api.pathing.goals; + +import baritone.api.utils.interfaces.IGoalRenderPos; +import net.minecraft.util.math.BlockPos; + + +/** + * Don't get into the block, but get directly adjacent to it. Useful for chests. + * + * @author avecowa + */ +public class GoalGetToBlock implements Goal, IGoalRenderPos { + + private final int x; + private final int y; + private final int z; + + public GoalGetToBlock(BlockPos pos) { + this.x = pos.getX(); + this.y = pos.getY(); + this.z = pos.getZ(); + } + + @Override + public BlockPos getGoalPos() { + return new BlockPos(x, y, z); + } + + @Override + public boolean isInGoal(int x, int y, int z) { + int xDiff = x - this.x; + int yDiff = y - this.y; + int zDiff = z - this.z; + if (yDiff < 0) { + yDiff++; + } + return Math.abs(xDiff) + Math.abs(yDiff) + Math.abs(zDiff) <= 1; + } + + @Override + public double heuristic(int x, int y, int z) { + int xDiff = x - this.x; + int yDiff = y - this.y; + int zDiff = z - this.z; + return GoalBlock.calculate(xDiff, yDiff, zDiff); + } + + @Override + public String toString() { + return "GoalGetToBlock{x=" + x + ",y=" + y + ",z=" + z + "}"; + } +} diff --git a/src/main/java/baritone/pathing/goals/GoalNear.java b/src/api/java/baritone/api/pathing/goals/GoalNear.java similarity index 54% rename from src/main/java/baritone/pathing/goals/GoalNear.java rename to src/api/java/baritone/api/pathing/goals/GoalNear.java index 2ec6bf1d..6befda6b 100644 --- a/src/main/java/baritone/pathing/goals/GoalNear.java +++ b/src/api/java/baritone/api/pathing/goals/GoalNear.java @@ -2,28 +2,29 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.pathing.goals; +package baritone.api.pathing.goals; +import baritone.api.utils.interfaces.IGoalRenderPos; import net.minecraft.util.math.BlockPos; -public class GoalNear implements Goal { - final int x; - final int y; - final int z; - final int rangeSq; +public class GoalNear implements Goal, IGoalRenderPos { + private final int x; + private final int y; + private final int z; + private final int rangeSq; public GoalNear(BlockPos pos, int range) { this.x = pos.getX(); @@ -33,21 +34,22 @@ public class GoalNear implements Goal { } @Override - public boolean isInGoal(BlockPos pos) { - int diffX = x - pos.getX(); - int diffY = y - pos.getY(); - int diffZ = z - pos.getZ(); - return diffX * diffX + diffY * diffY + diffZ * diffZ <= rangeSq; + public boolean isInGoal(int x, int y, int z) { + int xDiff = x - this.x; + int yDiff = y - this.y; + int zDiff = z - this.z; + return xDiff * xDiff + yDiff * yDiff + zDiff * zDiff <= rangeSq; } @Override - public double heuristic(BlockPos pos) { - int diffX = x - pos.getX(); - int diffY = y - pos.getY(); - int diffZ = z - pos.getZ(); - return GoalBlock.calculate(diffX, diffY, diffZ); + public double heuristic(int x, int y, int z) { + int xDiff = x - this.x; + int yDiff = y - this.y; + int zDiff = z - this.z; + return GoalBlock.calculate(xDiff, yDiff, zDiff); } + @Override public BlockPos getGoalPos() { return new BlockPos(x, y, z); } diff --git a/src/main/java/baritone/pathing/goals/GoalRunAway.java b/src/api/java/baritone/api/pathing/goals/GoalRunAway.java similarity index 68% rename from src/main/java/baritone/pathing/goals/GoalRunAway.java rename to src/api/java/baritone/api/pathing/goals/GoalRunAway.java index 620794d2..cb7a000e 100644 --- a/src/main/java/baritone/pathing/goals/GoalRunAway.java +++ b/src/api/java/baritone/api/pathing/goals/GoalRunAway.java @@ -2,33 +2,35 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.pathing.goals; +package baritone.api.pathing.goals; + +import net.minecraft.util.math.BlockPos; import java.util.Arrays; -import net.minecraft.util.math.BlockPos; /** * Useful for automated combat (retreating specifically) + * * @author leijurv */ public class GoalRunAway implements Goal { - public final BlockPos[] from; + private final BlockPos[] from; - final double distanceSq; + private final double distanceSq; public GoalRunAway(double distance, BlockPos... from) { if (from.length == 0) { @@ -39,10 +41,10 @@ public class GoalRunAway implements Goal { } @Override - public boolean isInGoal(BlockPos pos) { + public boolean isInGoal(int x, int y, int z) { for (BlockPos p : from) { - int diffX = pos.getX() - p.getX(); - int diffZ = pos.getZ() - p.getZ(); + int diffX = x - p.getX(); + int diffZ = z - p.getZ(); double distSq = diffX * diffX + diffZ * diffZ; if (distSq < distanceSq) { return false; @@ -52,10 +54,10 @@ public class GoalRunAway implements Goal { } @Override - public double heuristic(BlockPos pos) {//mostly copied from GoalBlock + public double heuristic(int x, int y, int z) {//mostly copied from GoalBlock double min = Double.MAX_VALUE; for (BlockPos p : from) { - double h = GoalXZ.calculate(p.getX() - pos.getX(), p.getZ() - pos.getZ()); + double h = GoalXZ.calculate(p.getX() - x, p.getZ() - z); if (h < min) { min = h; } @@ -65,6 +67,6 @@ public class GoalRunAway implements Goal { @Override public String toString() { - return "GoalRunAwayFrom[" + Arrays.asList(from) + "]"; + return "GoalRunAwayFrom" + Arrays.asList(from); } } diff --git a/src/main/java/baritone/pathing/goals/GoalTwoBlocks.java b/src/api/java/baritone/api/pathing/goals/GoalTwoBlocks.java similarity index 70% rename from src/main/java/baritone/pathing/goals/GoalTwoBlocks.java rename to src/api/java/baritone/api/pathing/goals/GoalTwoBlocks.java index 65571a49..4ed1bf5e 100644 --- a/src/main/java/baritone/pathing/goals/GoalTwoBlocks.java +++ b/src/api/java/baritone/api/pathing/goals/GoalTwoBlocks.java @@ -2,21 +2,22 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.pathing.goals; +package baritone.api.pathing.goals; +import baritone.api.utils.interfaces.IGoalRenderPos; import net.minecraft.util.math.BlockPos; /** @@ -25,7 +26,7 @@ import net.minecraft.util.math.BlockPos; * * @author leijurv */ -public class GoalTwoBlocks implements Goal { +public class GoalTwoBlocks implements Goal, IGoalRenderPos { /** * The X block position of this goal @@ -53,21 +54,22 @@ public class GoalTwoBlocks implements Goal { } @Override - public boolean isInGoal(BlockPos pos) { - return pos.getX() == this.x && (pos.getY() == this.y || pos.getY() == this.y - 1) && pos.getZ() == this.z; + public boolean isInGoal(int x, int y, int z) { + return x == this.x && (y == this.y || y == this.y - 1) && z == this.z; } @Override - public double heuristic(BlockPos pos) { - double xDiff = pos.getX() - this.x; - int yDiff = pos.getY() - this.y; + public double heuristic(int x, int y, int z) { + int xDiff = x - this.x; + int yDiff = y - this.y; + int zDiff = z - this.z; if (yDiff < 0) { yDiff++; } - double zDiff = pos.getZ() - this.z; return GoalBlock.calculate(xDiff, yDiff, zDiff); } + @Override public BlockPos getGoalPos() { return new BlockPos(x, y, z); } diff --git a/src/main/java/baritone/pathing/goals/GoalXZ.java b/src/api/java/baritone/api/pathing/goals/GoalXZ.java similarity index 70% rename from src/main/java/baritone/pathing/goals/GoalXZ.java rename to src/api/java/baritone/api/pathing/goals/GoalXZ.java index 8abfb221..636c649f 100644 --- a/src/main/java/baritone/pathing/goals/GoalXZ.java +++ b/src/api/java/baritone/api/pathing/goals/GoalXZ.java @@ -2,24 +2,22 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.pathing.goals; +package baritone.api.pathing.goals; -import baritone.Baritone; -import baritone.utils.Utils; -import net.minecraft.util.math.BlockPos; +import baritone.api.BaritoneAPI; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -48,26 +46,23 @@ public class GoalXZ implements Goal { } @Override - public boolean isInGoal(BlockPos pos) { - return pos.getX() == x && pos.getZ() == z; + public boolean isInGoal(int x, int y, int z) { + return x == this.x && z == this.z; } @Override - public double heuristic(BlockPos pos) {//mostly copied from GoalBlock - double xDiff = pos.getX() - this.x; - double zDiff = pos.getZ() - this.z; + public double heuristic(int x, int y, int z) {//mostly copied from GoalBlock + int xDiff = x - this.x; + int zDiff = z - this.z; return calculate(xDiff, zDiff); } @Override public String toString() { - return "Goal{x=" + x + ",z=" + z + "}"; + return "GoalXZ{x=" + x + ",z=" + z + "}"; } public static double calculate(double xDiff, double zDiff) { - if (Baritone.settings().pythagoreanMetric.get()) { - return Math.sqrt(xDiff * xDiff + zDiff * zDiff) * Baritone.settings().costHeuristic.get(); - } //This is a combination of pythagorean and manhattan distance //It takes into account the fact that pathing can either walk diagonally or forwards @@ -85,11 +80,11 @@ public class GoalXZ implements Goal { diagonal = z; } diagonal *= SQRT_2; - return (diagonal + straight) * Baritone.settings().costHeuristic.get(); // big TODO tune + return (diagonal + straight) * BaritoneAPI.getSettings().costHeuristic.get(); // big TODO tune } public static GoalXZ fromDirection(Vec3d origin, float yaw, double distance) { - float theta = (float) Utils.degToRad(yaw); + float theta = (float) Math.toRadians(yaw); double x = origin.x - MathHelper.sin(theta) * distance; double z = origin.z + MathHelper.cos(theta) * distance; return new GoalXZ((int) x, (int) z); diff --git a/src/main/java/baritone/pathing/goals/GoalYLevel.java b/src/api/java/baritone/api/pathing/goals/GoalYLevel.java similarity index 52% rename from src/main/java/baritone/pathing/goals/GoalYLevel.java rename to src/api/java/baritone/api/pathing/goals/GoalYLevel.java index 89cef250..ce54eebb 100644 --- a/src/main/java/baritone/pathing/goals/GoalYLevel.java +++ b/src/api/java/baritone/api/pathing/goals/GoalYLevel.java @@ -2,29 +2,29 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.pathing.goals; +package baritone.api.pathing.goals; -import net.minecraft.util.math.BlockPos; +import baritone.api.pathing.movement.ActionCosts; /** * Useful for mining (getting to diamond / iron level) * * @author leijurv */ -public class GoalYLevel implements Goal { +public class GoalYLevel implements Goal, ActionCosts { /** * The target Y level @@ -36,25 +36,29 @@ public class GoalYLevel implements Goal { } @Override - public boolean isInGoal(BlockPos pos) { - return pos.getY() == level; + public boolean isInGoal(int x, int y, int z) { + return y == level; } @Override - public double heuristic(BlockPos pos) { - if (pos.getY() > level) { + public double heuristic(int x, int y, int z) { + return calculate(level, y); + } + + public static double calculate(int goalY, int currentY) { + if (currentY > goalY) { // need to descend - return FALL_N_BLOCKS_COST[2] / 2 * (pos.getY() - level); + return FALL_N_BLOCKS_COST[2] / 2 * (currentY - goalY); } - if (pos.getY() < level) { + if (currentY < goalY) { // need to ascend - return (level - pos.getY()) * JUMP_ONE_BLOCK_COST; + return (goalY - currentY) * JUMP_ONE_BLOCK_COST; } return 0; } @Override public String toString() { - return "Goal{y=" + level + "}"; + return "GoalYLevel{y=" + level + "}"; } } diff --git a/src/main/java/baritone/pathing/movement/ActionCostsButOnlyTheOnesThatMakeMickeyDieInside.java b/src/api/java/baritone/api/pathing/movement/ActionCosts.java similarity index 60% rename from src/main/java/baritone/pathing/movement/ActionCostsButOnlyTheOnesThatMakeMickeyDieInside.java rename to src/api/java/baritone/api/pathing/movement/ActionCosts.java index c2481cda..e1f72dfa 100644 --- a/src/main/java/baritone/pathing/movement/ActionCostsButOnlyTheOnesThatMakeMickeyDieInside.java +++ b/src/api/java/baritone/api/pathing/movement/ActionCosts.java @@ -2,22 +2,49 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.pathing.movement; +package baritone.api.pathing.movement; + +public interface ActionCosts { + + /** + * These costs are measured roughly in ticks btw + */ + double WALK_ONE_BLOCK_COST = 20 / 4.317; // 4.633 + double WALK_ONE_IN_WATER_COST = 20 / 2.2; + double WALK_ONE_OVER_SOUL_SAND_COST = WALK_ONE_BLOCK_COST * 2; // 0.4 in BlockSoulSand but effectively about half + double SPRINT_ONE_OVER_SOUL_SAND_COST = WALK_ONE_OVER_SOUL_SAND_COST * 0.75; + double LADDER_UP_ONE_COST = 20 / 2.35; + double LADDER_DOWN_ONE_COST = 20 / 3.0; + double SNEAK_ONE_BLOCK_COST = 20 / 1.3; + double SPRINT_ONE_BLOCK_COST = 20 / 5.612; // 3.564 + /** + * To walk off an edge you need to walk 0.5 to the edge then 0.3 to start falling off + */ + double WALK_OFF_BLOCK_COST = WALK_ONE_BLOCK_COST * 0.8; + /** + * To walk the rest of the way to be centered on the new block + */ + double CENTER_AFTER_FALL_COST = WALK_ONE_BLOCK_COST - WALK_OFF_BLOCK_COST; + + /** + * don't make this Double.MAX_VALUE because it's added to other things, maybe other COST_INFs, + * and that would make it overflow to negative + */ + double COST_INF = 1000000; -public interface ActionCostsButOnlyTheOnesThatMakeMickeyDieInside { double[] FALL_N_BLOCKS_COST = generateFallNBlocksCost(); double FALL_1_25_BLOCKS_COST = distanceToTicks(1.25); @@ -57,16 +84,15 @@ public interface ActionCostsButOnlyTheOnesThatMakeMickeyDieInside { if (distance == 0) { return 0; // Avoid 0/0 NaN } + double tmpDistance = distance; int tickCount = 0; while (true) { double fallDistance = velocity(tickCount); - if (distance <= fallDistance) { - return tickCount + distance / fallDistance; + if (tmpDistance <= fallDistance) { + return tickCount + tmpDistance / fallDistance; } - distance -= fallDistance; + tmpDistance -= fallDistance; tickCount++; } } - - } diff --git a/src/main/java/baritone/utils/Rotation.java b/src/api/java/baritone/api/utils/Logger.java similarity index 56% rename from src/main/java/baritone/utils/Rotation.java rename to src/api/java/baritone/api/utils/Logger.java index 762d9cab..c2f6c99a 100644 --- a/src/main/java/baritone/utils/Rotation.java +++ b/src/api/java/baritone/api/utils/Logger.java @@ -2,26 +2,26 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.utils; +package baritone.api.utils; -import net.minecraft.util.Tuple; +/** + * @author Brady + * @since 9/23/2018 + */ +public class Logger { -public class Rotation extends Tuple { - public Rotation(Float yaw, Float pitch) { - super(yaw, pitch); - } } diff --git a/src/api/java/baritone/api/utils/Rotation.java b/src/api/java/baritone/api/utils/Rotation.java new file mode 100644 index 00000000..dc697169 --- /dev/null +++ b/src/api/java/baritone/api/utils/Rotation.java @@ -0,0 +1,112 @@ +/* + * 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 . + */ + +package baritone.api.utils; + +/** + * @author Brady + * @since 9/25/2018 + */ +public class Rotation { + + /** + * The yaw angle of this Rotation + */ + private float yaw; + + /** + * The pitch angle of this Rotation + */ + private float pitch; + + public Rotation(float yaw, float pitch) { + this.yaw = yaw; + this.pitch = pitch; + } + + /** + * @return The yaw of this rotation + */ + public float getYaw() { + return this.yaw; + } + + /** + * @return The pitch of this rotation + */ + public float getPitch() { + return this.pitch; + } + + /** + * Adds the yaw/pitch of the specified rotations to this + * rotation's yaw/pitch, and returns the result. + * + * @param other Another rotation + * @return The result from adding the other rotation to this rotation + */ + public Rotation add(Rotation other) { + return new Rotation( + this.yaw + other.yaw, + this.pitch + other.pitch + ); + } + + /** + * Subtracts the yaw/pitch of the specified rotations from this + * rotation's yaw/pitch, and returns the result. + * + * @param other Another rotation + * @return The result from subtracting the other rotation from this rotation + */ + public Rotation subtract(Rotation other) { + return new Rotation( + this.yaw - other.yaw, + this.pitch - other.pitch + ); + } + + /** + * @return A copy of this rotation with the pitch clamped + */ + public Rotation clamp() { + return new Rotation( + this.yaw, + RotationUtils.clampPitch(this.pitch) + ); + } + + /** + * @return A copy of this rotation with the yaw normalized + */ + public Rotation normalize() { + return new Rotation( + RotationUtils.normalizeYaw(this.yaw), + this.pitch + ); + } + + /** + * @return A copy of this rotation with the pitch clamped and the yaw normalized + */ + public Rotation normalizeAndClamp() { + return new Rotation( + RotationUtils.normalizeYaw(this.yaw), + RotationUtils.clampPitch(this.pitch) + ); + } +} diff --git a/src/api/java/baritone/api/utils/RotationUtils.java b/src/api/java/baritone/api/utils/RotationUtils.java new file mode 100644 index 00000000..0df4b38d --- /dev/null +++ b/src/api/java/baritone/api/utils/RotationUtils.java @@ -0,0 +1,54 @@ +/* + * 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 . + */ + +package baritone.api.utils; + +/** + * @author Brady + * @since 9/25/2018 + */ +public final class RotationUtils { + + private RotationUtils() {} + + /** + * Clamps the specified pitch value between -90 and 90. + * + * @param pitch The input pitch + * @return The clamped pitch + */ + public static float clampPitch(float pitch) { + return Math.max(-90, Math.min(90, pitch)); + } + + /** + * Normalizes the specified yaw value between -180 and 180. + * + * @param yaw The input yaw + * @return The normalized yaw + */ + public static float normalizeYaw(float yaw) { + float newYaw = yaw % 360F; + if (newYaw < -180F) { + newYaw += 360F; + } + if (newYaw >= 180F) { + newYaw -= 360F; + } + return newYaw; + } +} diff --git a/src/api/java/baritone/api/utils/interfaces/IGoalRenderPos.java b/src/api/java/baritone/api/utils/interfaces/IGoalRenderPos.java new file mode 100644 index 00000000..5bbbc007 --- /dev/null +++ b/src/api/java/baritone/api/utils/interfaces/IGoalRenderPos.java @@ -0,0 +1,24 @@ +/* + * 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 . + */ + +package baritone.api.utils.interfaces; + +import net.minecraft.util.math.BlockPos; + +public interface IGoalRenderPos { + BlockPos getGoalPos(); +} diff --git a/src/main/java/baritone/utils/interfaces/Toggleable.java b/src/api/java/baritone/api/utils/interfaces/Toggleable.java similarity index 67% rename from src/main/java/baritone/utils/interfaces/Toggleable.java rename to src/api/java/baritone/api/utils/interfaces/Toggleable.java index ba23bd34..359d6ee1 100644 --- a/src/main/java/baritone/utils/interfaces/Toggleable.java +++ b/src/api/java/baritone/api/utils/interfaces/Toggleable.java @@ -2,20 +2,20 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.utils.interfaces; +package baritone.api.utils.interfaces; /** * @author Brady @@ -41,4 +41,14 @@ public interface Toggleable { * @return Whether or not this {@link Toggleable} object is enabled */ boolean isEnabled(); + + /** + * Called when the state changes from disabled to enabled + */ + default void onEnable() {} + + /** + * Called when the state changes from enabled to disabled + */ + default void onDisable() {} } diff --git a/src/main/java/baritone/launch/BaritoneTweaker.java b/src/launch/java/baritone/launch/BaritoneTweaker.java old mode 100755 new mode 100644 similarity index 80% rename from src/main/java/baritone/launch/BaritoneTweaker.java rename to src/launch/java/baritone/launch/BaritoneTweaker.java index 04941f79..536ecf95 --- a/src/main/java/baritone/launch/BaritoneTweaker.java +++ b/src/launch/java/baritone/launch/BaritoneTweaker.java @@ -1,71 +1,77 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.launch; - -import net.minecraft.launchwrapper.ITweaker; -import net.minecraft.launchwrapper.LaunchClassLoader; -import org.spongepowered.asm.launch.MixinBootstrap; -import org.spongepowered.asm.mixin.MixinEnvironment; -import org.spongepowered.asm.mixin.Mixins; -import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Brady - * @since 7/31/2018 9:59 PM - */ -public class BaritoneTweaker implements ITweaker { - - List args; - - @Override - public void acceptOptions(List args, File gameDir, File assetsDir, String profile) { - this.args = new ArrayList<>(args); - if (gameDir != null) addArg("gameDir", gameDir.getAbsolutePath()); - if (assetsDir != null) addArg("assetsDir", assetsDir.getAbsolutePath()); - if (profile != null) addArg("version", profile); - } - - @Override - public void injectIntoClassLoader(LaunchClassLoader classLoader) { - MixinBootstrap.init(); - MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT); - MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.NOTCH); - Mixins.addConfiguration("mixins.baritone.json"); - } - - @Override - public final String getLaunchTarget() { - return "net.minecraft.client.main.Main"; - } - - @Override - public final String[] getLaunchArguments() { - return this.args.toArray(new String[0]); - } - - private void addArg(String label, String value) { - if (!args.contains("--" + label) && value != null) { - this.args.add("--" + label); - this.args.add(value); - } - } -} +/* + * 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 . + */ + +package baritone.launch; + +import net.minecraft.launchwrapper.ITweaker; +import net.minecraft.launchwrapper.LaunchClassLoader; +import org.spongepowered.asm.launch.MixinBootstrap; +import org.spongepowered.asm.mixin.MixinEnvironment; +import org.spongepowered.asm.mixin.Mixins; +import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Brady + * @since 7/31/2018 9:59 PM + */ +public class BaritoneTweaker implements ITweaker { + + List args; + + @Override + public void acceptOptions(List args, File gameDir, File assetsDir, String profile) { + this.args = new ArrayList<>(args); + if (gameDir != null) { + addArg("gameDir", gameDir.getAbsolutePath()); + } + if (assetsDir != null) { + addArg("assetsDir", assetsDir.getAbsolutePath()); + } + if (profile != null) { + addArg("version", profile); + } + } + + @Override + public void injectIntoClassLoader(LaunchClassLoader classLoader) { + MixinBootstrap.init(); + MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT); + MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.NOTCH); + Mixins.addConfiguration("mixins.baritone.json"); + } + + @Override + public final String getLaunchTarget() { + return "net.minecraft.client.main.Main"; + } + + @Override + public final String[] getLaunchArguments() { + return this.args.toArray(new String[0]); + } + + private void addArg(String label, String value) { + if (!args.contains("--" + label) && value != null) { + this.args.add("--" + label); + this.args.add(value); + } + } +} diff --git a/src/main/java/baritone/launch/BaritoneTweakerForge.java b/src/launch/java/baritone/launch/BaritoneTweakerForge.java old mode 100755 new mode 100644 similarity index 84% rename from src/main/java/baritone/launch/BaritoneTweakerForge.java rename to src/launch/java/baritone/launch/BaritoneTweakerForge.java index 9a45520c..7623eed5 --- a/src/main/java/baritone/launch/BaritoneTweakerForge.java +++ b/src/launch/java/baritone/launch/BaritoneTweakerForge.java @@ -1,44 +1,44 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.launch; - -import net.minecraft.launchwrapper.LaunchClassLoader; -import org.spongepowered.asm.mixin.MixinEnvironment; -import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Brady - * @since 7/31/2018 10:09 PM - */ -public class BaritoneTweakerForge extends BaritoneTweaker { - - @Override - public final void acceptOptions(List args, File gameDir, File assetsDir, String profile) { - this.args = new ArrayList<>(); - } - - @Override - public final void injectIntoClassLoader(LaunchClassLoader classLoader) { - super.injectIntoClassLoader(classLoader); - MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.SEARGE); - } -} +/* + * 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 . + */ + +package baritone.launch; + +import net.minecraft.launchwrapper.LaunchClassLoader; +import org.spongepowered.asm.mixin.MixinEnvironment; +import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Brady + * @since 7/31/2018 10:09 PM + */ +public class BaritoneTweakerForge extends BaritoneTweaker { + + @Override + public final void acceptOptions(List args, File gameDir, File assetsDir, String profile) { + this.args = new ArrayList<>(); + } + + @Override + public final void injectIntoClassLoader(LaunchClassLoader classLoader) { + super.injectIntoClassLoader(classLoader); + MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.SEARGE); + } +} diff --git a/src/main/java/baritone/launch/BaritoneTweakerOptifine.java b/src/launch/java/baritone/launch/BaritoneTweakerOptifine.java old mode 100755 new mode 100644 similarity index 79% rename from src/main/java/baritone/launch/BaritoneTweakerOptifine.java rename to src/launch/java/baritone/launch/BaritoneTweakerOptifine.java index 380a0b0f..9f4f8380 --- a/src/main/java/baritone/launch/BaritoneTweakerOptifine.java +++ b/src/launch/java/baritone/launch/BaritoneTweakerOptifine.java @@ -1,34 +1,34 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.launch; - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -/** - * @author Brady - * @since 7/31/2018 10:10 PM - */ -public class BaritoneTweakerOptifine extends BaritoneTweaker { - - @Override - public final void acceptOptions(List args, File gameDir, File assetsDir, String profile) { - this.args = new ArrayList<>(); - } -} +/* + * 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 . + */ + +package baritone.launch; + +import java.io.File; +import java.util.ArrayList; +import java.util.List; + +/** + * @author Brady + * @since 7/31/2018 10:10 PM + */ +public class BaritoneTweakerOptifine extends BaritoneTweaker { + + @Override + public final void acceptOptions(List args, File gameDir, File assetsDir, String profile) { + this.args = new ArrayList<>(); + } +} diff --git a/src/launch/java/baritone/launch/mixins/MixinAnvilChunkLoader.java b/src/launch/java/baritone/launch/mixins/MixinAnvilChunkLoader.java new file mode 100644 index 00000000..4ffb5abc --- /dev/null +++ b/src/launch/java/baritone/launch/mixins/MixinAnvilChunkLoader.java @@ -0,0 +1,41 @@ +/* + * 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 . + */ + +package baritone.launch.mixins; + +import baritone.utils.accessor.IAnvilChunkLoader; +import net.minecraft.world.chunk.storage.AnvilChunkLoader; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +import java.io.File; + +/** + * @author Brady + * @since 9/4/2018 + */ +@Mixin(AnvilChunkLoader.class) +public class MixinAnvilChunkLoader implements IAnvilChunkLoader { + + @Shadow @Final private File chunkSaveLocation; + + @Override + public File getChunkSaveLocation() { + return this.chunkSaveLocation; + } +} diff --git a/src/main/java/baritone/launch/mixins/MixinBlockPos.java b/src/launch/java/baritone/launch/mixins/MixinBlockPos.java similarity index 81% rename from src/main/java/baritone/launch/mixins/MixinBlockPos.java rename to src/launch/java/baritone/launch/mixins/MixinBlockPos.java index 1cf52132..013980a9 100644 --- a/src/main/java/baritone/launch/mixins/MixinBlockPos.java +++ b/src/launch/java/baritone/launch/mixins/MixinBlockPos.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -29,7 +29,7 @@ import javax.annotation.Nonnull; * @since 8/25/2018 */ @Mixin(BlockPos.class) -public abstract class MixinBlockPos extends Vec3i { +public class MixinBlockPos extends Vec3i { public MixinBlockPos(int xIn, int yIn, int zIn) { super(xIn, yIn, zIn); diff --git a/src/launch/java/baritone/launch/mixins/MixinChunkProviderServer.java b/src/launch/java/baritone/launch/mixins/MixinChunkProviderServer.java new file mode 100644 index 00000000..246c368e --- /dev/null +++ b/src/launch/java/baritone/launch/mixins/MixinChunkProviderServer.java @@ -0,0 +1,40 @@ +/* + * 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 . + */ + +package baritone.launch.mixins; + +import baritone.utils.accessor.IChunkProviderServer; +import net.minecraft.world.chunk.storage.IChunkLoader; +import net.minecraft.world.gen.ChunkProviderServer; +import org.spongepowered.asm.mixin.Final; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +/** + * @author Brady + * @since 9/4/2018 + */ +@Mixin(ChunkProviderServer.class) +public class MixinChunkProviderServer implements IChunkProviderServer { + + @Shadow @Final private IChunkLoader chunkLoader; + + @Override + public IChunkLoader getChunkLoader() { + return this.chunkLoader; + } +} diff --git a/src/main/java/baritone/launch/mixins/MixinEntity.java b/src/launch/java/baritone/launch/mixins/MixinEntity.java similarity index 73% rename from src/main/java/baritone/launch/mixins/MixinEntity.java rename to src/launch/java/baritone/launch/mixins/MixinEntity.java index 2a0134d3..b96b5b41 100644 --- a/src/main/java/baritone/launch/mixins/MixinEntity.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntity.java @@ -2,23 +2,23 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.launch.mixins; import baritone.Baritone; -import baritone.api.event.events.RelativeMoveEvent; +import baritone.api.event.events.RotationMoveEvent; import baritone.api.event.events.type.EventState; import net.minecraft.client.Minecraft; import net.minecraft.entity.Entity; @@ -41,7 +41,7 @@ public class MixinEntity { private void preMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) { Entity _this = (Entity) (Object) this; if (_this == Minecraft.getMinecraft().player) - Baritone.INSTANCE.getGameEventHandler().onPlayerRelativeMove(new RelativeMoveEvent(EventState.PRE)); + Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.PRE, RotationMoveEvent.Type.MOTION_UPDATE)); } @Inject( @@ -51,6 +51,6 @@ public class MixinEntity { private void postMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) { Entity _this = (Entity) (Object) this; if (_this == Minecraft.getMinecraft().player) - Baritone.INSTANCE.getGameEventHandler().onPlayerRelativeMove(new RelativeMoveEvent(EventState.POST)); + Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.POST, RotationMoveEvent.Type.MOTION_UPDATE)); } } diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java new file mode 100644 index 00000000..e840576e --- /dev/null +++ b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java @@ -0,0 +1,57 @@ +/* + * 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 . + */ + +package baritone.launch.mixins; + +import baritone.Baritone; +import baritone.api.event.events.RotationMoveEvent; +import baritone.api.event.events.type.EventState; +import net.minecraft.client.Minecraft; +import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityLivingBase; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +/** + * @author Brady + * @since 9/10/2018 + */ +@Mixin(EntityLivingBase.class) +public class MixinEntityLivingBase { + + @Inject( + method = "jump", + at = @At("HEAD") + ) + private void preJump(CallbackInfo ci) { + Entity _this = (Entity) (Object) this; + if (_this == Minecraft.getMinecraft().player) + Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.PRE, RotationMoveEvent.Type.JUMP)); + } + + @Inject( + method = "jump", + at = @At("RETURN") + ) + private void postJump(CallbackInfo ci) { + Entity _this = (Entity) (Object) this; + if (_this == Minecraft.getMinecraft().player) + Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.POST, RotationMoveEvent.Type.JUMP)); + } +} diff --git a/src/main/java/baritone/launch/mixins/MixinEntityPlayerSP.java b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java similarity index 90% rename from src/main/java/baritone/launch/mixins/MixinEntityPlayerSP.java rename to src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java index 9da39df3..e9a575c5 100644 --- a/src/main/java/baritone/launch/mixins/MixinEntityPlayerSP.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -42,8 +42,9 @@ public class MixinEntityPlayerSP { private void sendChatMessage(String msg, CallbackInfo ci) { ChatEvent event = new ChatEvent(msg); Baritone.INSTANCE.getGameEventHandler().onSendChatMessage(event); - if (event.isCancelled()) + if (event.isCancelled()) { ci.cancel(); + } } @Inject( diff --git a/src/main/java/baritone/launch/mixins/MixinEntityRenderer.java b/src/launch/java/baritone/launch/mixins/MixinEntityRenderer.java similarity index 87% rename from src/main/java/baritone/launch/mixins/MixinEntityRenderer.java rename to src/launch/java/baritone/launch/mixins/MixinEntityRenderer.java index 55adfc83..0fc1b246 100644 --- a/src/main/java/baritone/launch/mixins/MixinEntityRenderer.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityRenderer.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/java/baritone/launch/mixins/MixinKeyBinding.java b/src/launch/java/baritone/launch/mixins/MixinKeyBinding.java old mode 100755 new mode 100644 similarity index 79% rename from src/main/java/baritone/launch/mixins/MixinKeyBinding.java rename to src/launch/java/baritone/launch/mixins/MixinKeyBinding.java index 085ddc74..c776d228 --- a/src/main/java/baritone/launch/mixins/MixinKeyBinding.java +++ b/src/launch/java/baritone/launch/mixins/MixinKeyBinding.java @@ -1,43 +1,44 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.launch.mixins; - -import baritone.Baritone; -import net.minecraft.client.settings.KeyBinding; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; - -/** - * @author Brady - * @since 7/31/2018 11:44 PM - */ -@Mixin(KeyBinding.class) -public abstract class MixinKeyBinding { - - @Inject( - method = "isKeyDown", - at = @At("HEAD"), - cancellable = true - ) - private void isKeyDown(CallbackInfoReturnable cir) { - if (Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this)) - cir.setReturnValue(true); - } -} +/* + * 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 . + */ + +package baritone.launch.mixins; + +import baritone.Baritone; +import net.minecraft.client.settings.KeyBinding; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +/** + * @author Brady + * @since 7/31/2018 11:44 PM + */ +@Mixin(KeyBinding.class) +public class MixinKeyBinding { + + @Inject( + method = "isKeyDown", + at = @At("HEAD"), + cancellable = true + ) + private void isKeyDown(CallbackInfoReturnable cir) { + if (Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this)) { + cir.setReturnValue(true); + } + } +} diff --git a/src/main/java/baritone/launch/mixins/MixinMinecraft.java b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java old mode 100755 new mode 100644 similarity index 87% rename from src/main/java/baritone/launch/mixins/MixinMinecraft.java rename to src/launch/java/baritone/launch/mixins/MixinMinecraft.java index 49c587ba..d5d41f44 --- a/src/main/java/baritone/launch/mixins/MixinMinecraft.java +++ b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java @@ -1,176 +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 General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.launch.mixins; - -import baritone.Baritone; -import baritone.api.event.events.BlockInteractEvent; -import baritone.api.event.events.TickEvent; -import baritone.api.event.events.WorldEvent; -import baritone.api.event.events.type.EventState; -import baritone.behavior.impl.PathingBehavior; -import baritone.utils.ExampleBaritoneControl; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityPlayerSP; -import net.minecraft.client.gui.GuiScreen; -import net.minecraft.client.multiplayer.WorldClient; -import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumActionResult; -import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import org.spongepowered.asm.lib.Opcodes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Inject; -import org.spongepowered.asm.mixin.injection.Redirect; -import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import org.spongepowered.asm.mixin.injection.callback.LocalCapture; - -/** - * @author Brady - * @since 7/31/2018 10:51 PM - */ -@Mixin(Minecraft.class) -public class MixinMinecraft { - - @Shadow - private int leftClickCounter; - @Shadow - public EntityPlayerSP player; - @Shadow - public WorldClient world; - - @Inject( - method = "init", - at = @At("RETURN") - ) - private void init(CallbackInfo ci) { - Baritone.INSTANCE.init(); - ExampleBaritoneControl.INSTANCE.initAndRegister(); - } - - @Inject( - method = "runTick", - at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "net/minecraft/client/Minecraft.currentScreen:Lnet/minecraft/client/gui/GuiScreen;", - ordinal = 5, - shift = At.Shift.BY, - by = -3 - ) - ) - private void runTick(CallbackInfo ci) { - Minecraft mc = (Minecraft) (Object) this; - Baritone.INSTANCE.getGameEventHandler().onTick(new TickEvent( - EventState.PRE, - (mc.player != null && mc.world != null) - ? TickEvent.Type.IN - : TickEvent.Type.OUT - )); - } - - @Redirect( - method = "runTickKeyboard", - at = @At( - value = "INVOKE", - target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z", - remap = false - ) - ) - private boolean Keyboard$isKeyDown(int keyCode) { - return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode); - } - - @Inject( - method = "processKeyBinds", - at = @At("HEAD") - ) - private void runTickKeyboard(CallbackInfo ci) { - Baritone.INSTANCE.getGameEventHandler().onProcessKeyBinds(); - } - - @Inject( - method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V", - at = @At("HEAD") - ) - private void preLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) { - // If we're unloading the world but one doesn't exist, ignore it - if (this.world == null && world == null) { - return; - } - - Baritone.INSTANCE.getGameEventHandler().onWorldEvent( - new WorldEvent( - world, - EventState.PRE - ) - ); - } - - @Inject( - method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V", - at = @At("RETURN") - ) - private void postLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) { - // still fire event for both null, as that means we've just finished exiting a world - - Baritone.INSTANCE.getGameEventHandler().onWorldEvent( - new WorldEvent( - world, - EventState.POST - ) - ); - } - - @Redirect( - method = "runTick", - at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "net/minecraft/client/gui/GuiScreen.allowUserInput:Z" - ) - ) - private boolean isAllowUserInput(GuiScreen screen) { - return (PathingBehavior.INSTANCE.getCurrent() != null && player != null) || screen.allowUserInput; - } - - @Inject( - method = "clickMouse", - at = @At( - value = "INVOKE", - target = "net/minecraft/client/multiplayer/PlayerControllerMP.clickBlock(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)Z" - ), - locals = LocalCapture.CAPTURE_FAILHARD - ) - private void onBlockBreak(CallbackInfo ci, BlockPos pos) { - Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(pos, BlockInteractEvent.Type.BREAK)); - } - - @Inject( - method = "rightClickMouse", - at = @At( - value = "INVOKE", - target = "net/minecraft/client/entity/EntityPlayerSP.swingArm(Lnet/minecraft/util/EnumHand;)V" - ), - locals = LocalCapture.CAPTURE_FAILHARD - ) - private void onBlockUse(CallbackInfo ci, EnumHand var1[], int var2, int var3, EnumHand enumhand, ItemStack itemstack, BlockPos blockpos, int i, EnumActionResult enumactionresult) { - Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(blockpos, BlockInteractEvent.Type.USE)); - } -} +/* + * 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 . + */ + +package baritone.launch.mixins; + +import baritone.Baritone; +import baritone.api.event.events.BlockInteractEvent; +import baritone.api.event.events.TickEvent; +import baritone.api.event.events.WorldEvent; +import baritone.api.event.events.type.EventState; +import baritone.behavior.PathingBehavior; +import baritone.utils.ExampleBaritoneControl; +import net.minecraft.client.Minecraft; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.multiplayer.WorldClient; +import net.minecraft.item.ItemStack; +import net.minecraft.util.EnumActionResult; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import org.spongepowered.asm.lib.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.Redirect; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.LocalCapture; + +/** + * @author Brady + * @since 7/31/2018 10:51 PM + */ +@Mixin(Minecraft.class) +public class MixinMinecraft { + + @Shadow + private int leftClickCounter; + @Shadow + public EntityPlayerSP player; + @Shadow + public WorldClient world; + + @Inject( + method = "init", + at = @At("RETURN") + ) + private void init(CallbackInfo ci) { + Baritone.INSTANCE.init(); + ExampleBaritoneControl.INSTANCE.initAndRegister(); + } + + @Inject( + method = "runTick", + at = @At( + value = "FIELD", + opcode = Opcodes.GETFIELD, + target = "net/minecraft/client/Minecraft.currentScreen:Lnet/minecraft/client/gui/GuiScreen;", + ordinal = 5, + shift = At.Shift.BY, + by = -3 + ) + ) + private void runTick(CallbackInfo ci) { + Minecraft mc = (Minecraft) (Object) this; + Baritone.INSTANCE.getGameEventHandler().onTick(new TickEvent( + EventState.PRE, + (mc.player != null && mc.world != null) + ? TickEvent.Type.IN + : TickEvent.Type.OUT + )); + } + + @Inject( + method = "processKeyBinds", + at = @At("HEAD") + ) + private void runTickKeyboard(CallbackInfo ci) { + Baritone.INSTANCE.getGameEventHandler().onProcessKeyBinds(); + } + + @Inject( + method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V", + at = @At("HEAD") + ) + private void preLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) { + // If we're unloading the world but one doesn't exist, ignore it + if (this.world == null && world == null) { + return; + } + + Baritone.INSTANCE.getGameEventHandler().onWorldEvent( + new WorldEvent( + world, + EventState.PRE + ) + ); + } + + @Inject( + method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V", + at = @At("RETURN") + ) + private void postLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) { + // still fire event for both null, as that means we've just finished exiting a world + + Baritone.INSTANCE.getGameEventHandler().onWorldEvent( + new WorldEvent( + world, + EventState.POST + ) + ); + } + + @Redirect( + method = "runTick", + at = @At( + value = "FIELD", + opcode = Opcodes.GETFIELD, + target = "net/minecraft/client/gui/GuiScreen.allowUserInput:Z" + ) + ) + private boolean isAllowUserInput(GuiScreen screen) { + return (PathingBehavior.INSTANCE.getCurrent() != null && player != null) || screen.allowUserInput; + } + + @Inject( + method = "clickMouse", + at = @At( + value = "INVOKE", + target = "net/minecraft/client/multiplayer/PlayerControllerMP.clickBlock(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)Z" + ), + locals = LocalCapture.CAPTURE_FAILHARD + ) + private void onBlockBreak(CallbackInfo ci, BlockPos pos) { + Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(pos, BlockInteractEvent.Type.BREAK)); + } + + @Inject( + method = "rightClickMouse", + at = @At( + value = "INVOKE", + target = "net/minecraft/client/entity/EntityPlayerSP.swingArm(Lnet/minecraft/util/EnumHand;)V" + ), + locals = LocalCapture.CAPTURE_FAILHARD + ) + private void onBlockUse(CallbackInfo ci, EnumHand var1[], int var2, int var3, EnumHand enumhand, ItemStack itemstack, BlockPos blockpos, int i, EnumActionResult enumactionresult) { + Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(blockpos, BlockInteractEvent.Type.USE)); + } +} diff --git a/src/main/java/baritone/launch/mixins/MixinNetHandlerPlayClient.java b/src/launch/java/baritone/launch/mixins/MixinNetHandlerPlayClient.java similarity index 92% rename from src/main/java/baritone/launch/mixins/MixinNetHandlerPlayClient.java rename to src/launch/java/baritone/launch/mixins/MixinNetHandlerPlayClient.java index bd4cbb97..498b5aff 100644 --- a/src/main/java/baritone/launch/mixins/MixinNetHandlerPlayClient.java +++ b/src/launch/java/baritone/launch/mixins/MixinNetHandlerPlayClient.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/java/baritone/launch/mixins/MixinNetworkManager.java b/src/launch/java/baritone/launch/mixins/MixinNetworkManager.java similarity index 64% rename from src/main/java/baritone/launch/mixins/MixinNetworkManager.java rename to src/launch/java/baritone/launch/mixins/MixinNetworkManager.java index 472d4f04..f79e007f 100644 --- a/src/main/java/baritone/launch/mixins/MixinNetworkManager.java +++ b/src/launch/java/baritone/launch/mixins/MixinNetworkManager.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -24,8 +24,10 @@ import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.util.concurrent.Future; import io.netty.util.concurrent.GenericFutureListener; +import net.minecraft.network.EnumPacketDirection; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; @@ -37,26 +39,33 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; * @since 8/6/2018 9:30 PM */ @Mixin(NetworkManager.class) -public abstract class MixinNetworkManager { +public class MixinNetworkManager { - @Shadow private Channel channel; + @Shadow + private Channel channel; - @Shadow protected abstract void channelRead0(ChannelHandlerContext p_channelRead0_1_, Packet p_channelRead0_2_) throws Exception; + @Shadow + @Final + private EnumPacketDirection direction; @Inject( method = "dispatchPacket", at = @At("HEAD") ) - private void preDispatchPacket(Packet inPacket, final GenericFutureListener>[] futureListeners, CallbackInfo ci) { - Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.PRE, inPacket)); + private void preDispatchPacket(Packet inPacket, final GenericFutureListener>[] futureListeners, CallbackInfo ci) { + if (this.direction == EnumPacketDirection.CLIENTBOUND) { + Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.PRE, inPacket)); + } } @Inject( method = "dispatchPacket", at = @At("RETURN") ) - private void postDispatchPacket(Packet inPacket, final GenericFutureListener>[] futureListeners, CallbackInfo ci) { - Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.POST, inPacket)); + private void postDispatchPacket(Packet inPacket, final GenericFutureListener>[] futureListeners, CallbackInfo ci) { + if (this.direction == EnumPacketDirection.CLIENTBOUND) { + Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.POST, inPacket)); + } } @Inject( @@ -67,7 +76,8 @@ public abstract class MixinNetworkManager { ) ) private void preProcessPacket(ChannelHandlerContext context, Packet packet, CallbackInfo ci) { - Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent(EventState.PRE, packet)); + if (this.direction == EnumPacketDirection.CLIENTBOUND) { + Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent(EventState.PRE, packet));} } @Inject( @@ -75,7 +85,8 @@ public abstract class MixinNetworkManager { at = @At("RETURN") ) private void postProcessPacket(ChannelHandlerContext context, Packet packet, CallbackInfo ci) { - if (this.channel.isOpen()) + if (this.channel.isOpen() && this.direction == EnumPacketDirection.CLIENTBOUND) { Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent(EventState.POST, packet)); + } } } diff --git a/src/main/java/baritone/launch/mixins/MixinWorldClient.java b/src/launch/java/baritone/launch/mixins/MixinWorldClient.java similarity index 90% rename from src/main/java/baritone/launch/mixins/MixinWorldClient.java rename to src/launch/java/baritone/launch/mixins/MixinWorldClient.java index 005dbe16..322239b7 100644 --- a/src/main/java/baritone/launch/mixins/MixinWorldClient.java +++ b/src/launch/java/baritone/launch/mixins/MixinWorldClient.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/resources/mixins.baritone.json b/src/launch/resources/mixins.baritone.json old mode 100755 new mode 100644 similarity index 65% rename from src/main/resources/mixins.baritone.json rename to src/launch/resources/mixins.baritone.json index c0b5d3bb..9ea70330 --- a/src/main/resources/mixins.baritone.json +++ b/src/launch/resources/mixins.baritone.json @@ -1,28 +1,24 @@ -{ - "required": true, - "package": "baritone.launch.mixins", - "refmap": "mixins.baritone.refmap.json", - "compatibilityLevel": "JAVA_8", - "verbose": false, - "injectors": { - "maxShiftBy": 2 - }, - "client": [ - "MixinBlockPos", - "MixinEntity", - "MixinEntityPlayerSP", - "MixinEntityRenderer", - "MixinGameSettings", - "MixinGuiContainer", - "MixinGuiScreen", - "MixinInventoryPlayer", - "MixinKeyBinding", - "MixinMinecraft", - "MixinNetHandlerPlayClient", - "MixinNetworkManager", - "MixinWorldClient", - - "accessor.IAnvilChunkLoader", - "accessor.IChunkProviderServer" - ] +{ + "required": true, + "package": "baritone.launch.mixins", + "refmap": "mixins.baritone.refmap.json", + "compatibilityLevel": "JAVA_8", + "verbose": false, + "injectors": { + "maxShiftBy": 2 + }, + "client": [ + "MixinAnvilChunkLoader", + "MixinBlockPos", + "MixinChunkProviderServer", + "MixinEntity", + "MixinEntityLivingBase", + "MixinEntityPlayerSP", + "MixinEntityRenderer", + "MixinKeyBinding", + "MixinMinecraft", + "MixinNetHandlerPlayClient", + "MixinNetworkManager", + "MixinWorldClient" + ] } \ No newline at end of file diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 5baacec8..14c35319 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -2,24 +2,27 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone; -import baritone.api.event.GameEventHandler; -import baritone.behavior.Behavior; -import baritone.behavior.impl.*; +import baritone.api.BaritoneAPI; +import baritone.api.Settings; +import baritone.api.event.listener.IGameEventListener; +import baritone.behavior.*; +import baritone.cache.WorldProvider; +import baritone.event.GameEventHandler; import baritone.utils.InputOverrideHandler; import net.minecraft.client.Minecraft; @@ -28,6 +31,10 @@ import java.io.IOException; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Executor; +import java.util.concurrent.SynchronousQueue; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; import java.util.function.Consumer; /** @@ -51,6 +58,8 @@ public enum Baritone { private Settings settings; private List behaviors; private File dir; + private ThreadPoolExecutor threadPool; + /** * List of consumers to be called after Baritone has initialized @@ -70,9 +79,16 @@ public enum Baritone { if (initialized) { return; } + this.threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>()); this.gameEventHandler = new GameEventHandler(); this.inputOverrideHandler = new InputOverrideHandler(); - this.settings = new Settings(); + + // Acquire the "singleton" instance of the settings directly from the API + // We might want to change this... + this.settings = BaritoneAPI.getSettings(); + + BaritoneAPI.registerProviders(WorldProvider.INSTANCE); + this.behaviors = new ArrayList<>(); { registerBehavior(PathingBehavior.INSTANCE); @@ -81,6 +97,16 @@ public enum Baritone { registerBehavior(LocationTrackingBehavior.INSTANCE); registerBehavior(FollowBehavior.INSTANCE); registerBehavior(MineBehavior.INSTANCE); + + // TODO: Clean this up + // Maybe combine this call in someway with the registerBehavior calls? + BaritoneAPI.registerDefaultBehaviors( + FollowBehavior.INSTANCE, + LookBehavior.INSTANCE, + MemoryBehavior.INSTANCE, + MineBehavior.INSTANCE, + PathingBehavior.INSTANCE + ); } this.dir = new File(Minecraft.getMinecraft().gameDir, "baritone"); if (!Files.exists(dir.toPath())) { @@ -95,32 +121,40 @@ public enum Baritone { this.onInitConsumers.forEach(consumer -> consumer.accept(this)); } - public final boolean isInitialized() { + public boolean isInitialized() { return this.initialized; } - public final GameEventHandler getGameEventHandler() { + public IGameEventListener getGameEventHandler() { return this.gameEventHandler; } - public final InputOverrideHandler getInputOverrideHandler() { + public InputOverrideHandler getInputOverrideHandler() { return this.inputOverrideHandler; } - public final List getBehaviors() { + public List getBehaviors() { return this.behaviors; } + public Executor getExecutor() { + return threadPool; + } + public void registerBehavior(Behavior behavior) { this.behaviors.add(behavior); - this.gameEventHandler.registerEventListener(behavior); + this.registerEventListener(behavior); } - public final boolean isActive() { + public void registerEventListener(IGameEventListener listener) { + this.gameEventHandler.registerEventListener(listener); + } + + public boolean isActive() { return this.active; } - public final Settings getSettings() { + public Settings getSettings() { return this.settings; } @@ -128,11 +162,11 @@ public enum Baritone { return Baritone.INSTANCE.settings; // yolo } - public final File getDir() { + public File getDir() { return this.dir; } - public final void registerInitListener(Consumer runnable) { + public void registerInitListener(Consumer runnable) { this.onInitConsumers.add(runnable); } } diff --git a/src/main/java/baritone/api/event/events/ItemSlotEvent.java b/src/main/java/baritone/api/event/events/ItemSlotEvent.java deleted file mode 100644 index 82e69177..00000000 --- a/src/main/java/baritone/api/event/events/ItemSlotEvent.java +++ /dev/null @@ -1,56 +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 General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.api.event.events; - -import baritone.api.event.listener.IGameEventListener; - -/** - * Called in some cases where a player's inventory has it's current slot queried. - *

- * @see IGameEventListener#onQueryItemSlotForBlocks() - * - * @author Brady - * @since 8/20/2018 - */ -public final class ItemSlotEvent { - - /** - * The current slot index - */ - private int slot; - - public ItemSlotEvent(int slot) { - this.slot = slot; - } - - /** - * Sets the new slot index that will be used - * - * @param slot The slot index - */ - public final void setSlot(int slot) { - this.slot = slot; - } - - /** - * @return The current slot index - */ - public final int getSlot() { - return this.slot; - } -} diff --git a/src/main/java/baritone/api/event/events/RelativeMoveEvent.java b/src/main/java/baritone/api/event/events/RelativeMoveEvent.java deleted file mode 100644 index 14798fd5..00000000 --- a/src/main/java/baritone/api/event/events/RelativeMoveEvent.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.api.event.events; - -import baritone.api.event.events.type.EventState; - -/** - * @author Brady - * @since 8/21/2018 - */ -public final class RelativeMoveEvent { - - /** - * The state of the event - */ - private final EventState state; - - public RelativeMoveEvent(EventState state) { - this.state = state; - } - - /** - * @return The state of the event - */ - public final EventState getState() { - return this.state; - } -} diff --git a/src/main/java/baritone/behavior/Behavior.java b/src/main/java/baritone/behavior/Behavior.java index ad5e3a88..b856e423 100644 --- a/src/main/java/baritone/behavior/Behavior.java +++ b/src/main/java/baritone/behavior/Behavior.java @@ -2,32 +2,30 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.behavior; -import baritone.api.event.listener.AbstractGameEventListener; -import baritone.utils.Helper; -import baritone.utils.interfaces.Toggleable; +import baritone.api.behavior.IBehavior; /** - * A generic bot behavior. + * A type of game event listener that can be toggled. * * @author Brady * @since 8/1/2018 6:29 PM */ -public class Behavior implements AbstractGameEventListener, Toggleable, Helper { +public class Behavior implements IBehavior { /** * Whether or not this behavior is enabled @@ -41,7 +39,7 @@ public class Behavior implements AbstractGameEventListener, Toggleable, Helper { */ @Override public final boolean toggle() { - return this.setEnabled(!this.enabled); + return this.setEnabled(!this.isEnabled()); } /** @@ -51,34 +49,17 @@ public class Behavior implements AbstractGameEventListener, Toggleable, Helper { */ @Override public final boolean setEnabled(boolean enabled) { - boolean newState = getNewState(this.enabled, enabled); - if (newState == this.enabled) + if (enabled == this.enabled) { return this.enabled; - - if (this.enabled = newState) { - onStart(); - } else { - onCancel(); } - + if (this.enabled = enabled) { + this.onEnable(); + } else { + this.onDisable(); + } return this.enabled; } - /** - * Function to determine what the new enabled state of this - * {@link Behavior} should be given the old state, and the - * proposed state. Intended to be overridden by behaviors - * that should always be active, given that the bot itself is - * active. - * - * @param oldState The old state - * @param proposedState The proposed state - * @return The new state - */ - public boolean getNewState(boolean oldState, boolean proposedState) { - return proposedState; - } - /** * @return Whether or not this {@link Behavior} is active. */ @@ -86,14 +67,4 @@ public class Behavior implements AbstractGameEventListener, Toggleable, Helper { public final boolean isEnabled() { return this.enabled; } - - /** - * Called when the state changes from disabled to enabled - */ - public void onStart() {} - - /** - * Called when the state changes from enabled to disabled - */ - public void onCancel() {} } diff --git a/src/main/java/baritone/behavior/FollowBehavior.java b/src/main/java/baritone/behavior/FollowBehavior.java new file mode 100644 index 00000000..83ca5135 --- /dev/null +++ b/src/main/java/baritone/behavior/FollowBehavior.java @@ -0,0 +1,79 @@ +/* + * 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 . + */ + +package baritone.behavior; + +import baritone.Baritone; +import baritone.api.behavior.IFollowBehavior; +import baritone.api.event.events.TickEvent; +import baritone.api.pathing.goals.GoalNear; +import baritone.api.pathing.goals.GoalXZ; +import baritone.utils.Helper; +import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; + +/** + * Follow an entity + * + * @author leijurv + */ +public final class FollowBehavior extends Behavior implements IFollowBehavior, Helper { + + public static final FollowBehavior INSTANCE = new FollowBehavior(); + + private Entity following; + + private FollowBehavior() {} + + @Override + public void onTick(TickEvent event) { + if (event.getType() == TickEvent.Type.OUT) { + following = null; + return; + } + if (following == null) { + return; + } + // lol this is trashy but it works + BlockPos pos; + if (Baritone.settings().followOffsetDistance.get() == 0) { + pos = following.getPosition(); + } else { + GoalXZ g = GoalXZ.fromDirection(following.getPositionVector(), Baritone.settings().followOffsetDirection.get(), Baritone.settings().followOffsetDistance.get()); + pos = new BlockPos(g.getX(), following.posY, g.getZ()); + } + PathingBehavior.INSTANCE.setGoal(new GoalNear(pos, Baritone.settings().followRadius.get())); + PathingBehavior.INSTANCE.revalidateGoal(); + PathingBehavior.INSTANCE.path(); + } + + @Override + public void follow(Entity entity) { + this.following = entity; + } + + @Override + public Entity following() { + return this.following; + } + + @Override + public void cancel() { + PathingBehavior.INSTANCE.cancel(); + follow(null); + } +} diff --git a/src/main/java/baritone/behavior/impl/LocationTrackingBehavior.java b/src/main/java/baritone/behavior/LocationTrackingBehavior.java similarity index 64% rename from src/main/java/baritone/behavior/impl/LocationTrackingBehavior.java rename to src/main/java/baritone/behavior/LocationTrackingBehavior.java index ba075dd3..dee74e79 100644 --- a/src/main/java/baritone/behavior/impl/LocationTrackingBehavior.java +++ b/src/main/java/baritone/behavior/LocationTrackingBehavior.java @@ -2,26 +2,26 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.behavior.impl; +package baritone.behavior; -import baritone.behavior.Behavior; -import baritone.chunk.Waypoint; -import baritone.chunk.WorldProvider; import baritone.api.event.events.BlockInteractEvent; +import baritone.cache.Waypoint; +import baritone.cache.WorldProvider; import baritone.utils.BlockStateInterface; +import baritone.utils.Helper; import net.minecraft.block.BlockBed; /** @@ -33,7 +33,7 @@ import net.minecraft.block.BlockBed; * @author Brady * @since 8/22/2018 */ -public final class LocationTrackingBehavior extends Behavior { +public final class LocationTrackingBehavior extends Behavior implements Helper { public static final LocationTrackingBehavior INSTANCE = new LocationTrackingBehavior(); @@ -42,12 +42,12 @@ public final class LocationTrackingBehavior extends Behavior { @Override public void onBlockInteract(BlockInteractEvent event) { if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(event.getPos()) instanceof BlockBed) { - WorldProvider.INSTANCE.getCurrentWorld().waypoints.addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, event.getPos())); + WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, event.getPos())); } } @Override public void onPlayerDeath() { - WorldProvider.INSTANCE.getCurrentWorld().waypoints.addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, playerFeet())); + WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, playerFeet())); } } diff --git a/src/main/java/baritone/behavior/impl/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java similarity index 71% rename from src/main/java/baritone/behavior/impl/LookBehavior.java rename to src/main/java/baritone/behavior/LookBehavior.java index 080d75d5..a42a1e50 100644 --- a/src/main/java/baritone/behavior/impl/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -2,34 +2,33 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.behavior.impl; +package baritone.behavior; import baritone.Baritone; -import baritone.Settings; -import baritone.behavior.Behavior; +import baritone.api.Settings; +import baritone.api.behavior.ILookBehavior; import baritone.api.event.events.PlayerUpdateEvent; -import baritone.api.event.events.RelativeMoveEvent; -import baritone.utils.Rotation; +import baritone.api.event.events.RotationMoveEvent; +import baritone.api.utils.Rotation; +import baritone.utils.Helper; -public class LookBehavior extends Behavior { +public final class LookBehavior extends Behavior implements ILookBehavior, Helper { public static final LookBehavior INSTANCE = new LookBehavior(); - private LookBehavior() {} - /** * Target's values are as follows: *

@@ -50,6 +49,9 @@ public class LookBehavior extends Behavior { */ private float lastYaw; + private LookBehavior() {} + + @Override public void updateTarget(Rotation target, boolean force) { this.target = target; this.force = force || !Baritone.settings().freeLook.get(); @@ -57,8 +59,9 @@ public class LookBehavior extends Behavior { @Override public void onPlayerUpdate(PlayerUpdateEvent event) { - if (this.target == null) + if (this.target == null) { return; + } // Whether or not we're going to silently set our angles boolean silent = Baritone.settings().antiCheatCompatibility.get(); @@ -66,9 +69,9 @@ public class LookBehavior extends Behavior { switch (event.getState()) { case PRE: { if (this.force) { - player().rotationYaw = this.target.getFirst(); + player().rotationYaw = this.target.getYaw(); float oldPitch = player().rotationPitch; - float desiredPitch = this.target.getSecond(); + float desiredPitch = this.target.getPitch(); player().rotationPitch = desiredPitch; if (desiredPitch == oldPitch) { nudgeToLevel(); @@ -76,7 +79,7 @@ public class LookBehavior extends Behavior { this.target = null; } else if (silent) { this.lastYaw = player().rotationYaw; - player().rotationYaw = this.target.getFirst(); + player().rotationYaw = this.target.getYaw(); } break; } @@ -87,23 +90,29 @@ public class LookBehavior extends Behavior { } break; } + default: + break; } } @Override - public void onPlayerRelativeMove(RelativeMoveEvent event) { + public void onPlayerRotationMove(RotationMoveEvent event) { if (this.target != null && !this.force) { switch (event.getState()) { case PRE: this.lastYaw = player().rotationYaw; - player().rotationYaw = this.target.getFirst(); + player().rotationYaw = this.target.getYaw(); break; case POST: player().rotationYaw = this.lastYaw; // If we have antiCheatCompatibility on, we're going to use the target value later in onPlayerUpdate() - if (!Baritone.settings().antiCheatCompatibility.get()) + // Also the type has to be MOTION_UPDATE because that is called after JUMP + if (!Baritone.settings().antiCheatCompatibility.get() && event.getType() == RotationMoveEvent.Type.MOTION_UPDATE) { this.target = null; + } + break; + default: break; } } diff --git a/src/main/java/baritone/behavior/impl/LookBehaviorUtils.java b/src/main/java/baritone/behavior/LookBehaviorUtils.java similarity index 83% rename from src/main/java/baritone/behavior/impl/LookBehaviorUtils.java rename to src/main/java/baritone/behavior/LookBehaviorUtils.java index 91b046e0..8cbe01ab 100644 --- a/src/main/java/baritone/behavior/impl/LookBehaviorUtils.java +++ b/src/main/java/baritone/behavior/LookBehaviorUtils.java @@ -2,22 +2,26 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.behavior.impl; +package baritone.behavior; -import baritone.utils.*; +import baritone.api.utils.Rotation; +import baritone.utils.BlockStateInterface; +import baritone.utils.Helper; +import baritone.utils.RayTraceUtils; +import baritone.utils.Utils; import net.minecraft.block.BlockFire; import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.*; @@ -47,10 +51,10 @@ public final class LookBehaviorUtils implements Helper { * @return vector of the rotation */ public static Vec3d calcVec3dFromRotation(Rotation rotation) { - float f = MathHelper.cos(-rotation.getFirst() * (float) DEG_TO_RAD - (float) Math.PI); - float f1 = MathHelper.sin(-rotation.getFirst() * (float) DEG_TO_RAD - (float) Math.PI); - float f2 = -MathHelper.cos(-rotation.getSecond() * (float) DEG_TO_RAD); - float f3 = MathHelper.sin(-rotation.getSecond() * (float) DEG_TO_RAD); + float f = MathHelper.cos(-rotation.getYaw() * (float) DEG_TO_RAD - (float) Math.PI); + float f1 = MathHelper.sin(-rotation.getYaw() * (float) DEG_TO_RAD - (float) Math.PI); + float f2 = -MathHelper.cos(-rotation.getPitch() * (float) DEG_TO_RAD); + float f3 = MathHelper.sin(-rotation.getPitch() * (float) DEG_TO_RAD); return new Vec3d((double) (f1 * f2), (double) f3, (double) (f * f2)); } @@ -67,9 +71,10 @@ public final class LookBehaviorUtils implements Helper { return Optional.of(new Rotation(mc.player.rotationYaw, mc.player.rotationPitch + 0.0001f)); } Optional possibleRotation = reachableCenter(pos); - System.out.println("center: " + possibleRotation); - if (possibleRotation.isPresent()) + //System.out.println("center: " + possibleRotation); + if (possibleRotation.isPresent()) { return possibleRotation; + } IBlockState state = BlockStateInterface.get(pos); AxisAlignedBB aabb = state.getBoundingBox(mc.world, pos); @@ -78,8 +83,9 @@ public final class LookBehaviorUtils implements Helper { double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y); double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z); possibleRotation = reachableOffset(pos, new Vec3d(pos).add(xDiff, yDiff, zDiff)); - if (possibleRotation.isPresent()) + if (possibleRotation.isPresent()) { return possibleRotation; + } } return Optional.empty(); } diff --git a/src/main/java/baritone/behavior/impl/MemoryBehavior.java b/src/main/java/baritone/behavior/MemoryBehavior.java similarity index 53% rename from src/main/java/baritone/behavior/impl/MemoryBehavior.java rename to src/main/java/baritone/behavior/MemoryBehavior.java index 8f43a8e8..b0980322 100644 --- a/src/main/java/baritone/behavior/impl/MemoryBehavior.java +++ b/src/main/java/baritone/behavior/MemoryBehavior.java @@ -1,9 +1,28 @@ -package baritone.behavior.impl; +/* + * 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 . + */ -import baritone.behavior.Behavior; +package baritone.behavior; + +import baritone.api.behavior.IMemoryBehavior; +import baritone.api.behavior.memory.IRememberedInventory; import baritone.api.event.events.PacketEvent; import baritone.api.event.events.PlayerUpdateEvent; import baritone.api.event.events.type.EventState; +import baritone.utils.Helper; import net.minecraft.item.ItemStack; import net.minecraft.network.Packet; import net.minecraft.network.play.client.CPacketCloseWindow; @@ -20,12 +39,10 @@ import java.util.*; * @author Brady * @since 8/6/2018 9:47 PM */ -public class MemoryBehavior extends Behavior { +public final class MemoryBehavior extends Behavior implements IMemoryBehavior, Helper { public static MemoryBehavior INSTANCE = new MemoryBehavior(); - private MemoryBehavior() {} - /** * Possible future inventories that we will be able to remember */ @@ -36,37 +53,37 @@ public class MemoryBehavior extends Behavior { */ private final Map rememberedInventories = new HashMap<>(); + private MemoryBehavior() {} + @Override public void onPlayerUpdate(PlayerUpdateEvent event) { - if (event.getState() == EventState.PRE) + if (event.getState() == EventState.PRE) { updateInventory(); + } } @Override public void onSendPacket(PacketEvent event) { Packet p = event.getPacket(); - switch (event.getState()) { - case PRE: { - if (p instanceof CPacketPlayerTryUseItemOnBlock) { - CPacketPlayerTryUseItemOnBlock packet = event.cast(); + if (event.getState() == EventState.PRE) { + if (p instanceof CPacketPlayerTryUseItemOnBlock) { + CPacketPlayerTryUseItemOnBlock packet = event.cast(); - TileEntity tileEntity = world().getTileEntity(packet.getPos()); + TileEntity tileEntity = world().getTileEntity(packet.getPos()); - // Ensure the TileEntity is a container of some sort - if (tileEntity instanceof TileEntityLockable) { + // Ensure the TileEntity is a container of some sort + if (tileEntity instanceof TileEntityLockable) { - TileEntityLockable lockable = (TileEntityLockable) tileEntity; - int size = lockable.getSizeInventory(); + TileEntityLockable lockable = (TileEntityLockable) tileEntity; + int size = lockable.getSizeInventory(); - this.futureInventories.add(new FutureInventory(System.nanoTime() / 1000000L, size, lockable.getGuiID(), tileEntity.getPos())); - } + this.futureInventories.add(new FutureInventory(System.nanoTime() / 1000000L, size, lockable.getGuiID(), tileEntity.getPos())); } + } - if (p instanceof CPacketCloseWindow) { - updateInventory(); - } - break; + if (p instanceof CPacketCloseWindow) { + updateInventory(); } } } @@ -75,31 +92,28 @@ public class MemoryBehavior extends Behavior { public void onReceivePacket(PacketEvent event) { Packet p = event.getPacket(); - switch (event.getState()) { - case PRE: { - if (p instanceof SPacketOpenWindow) { - SPacketOpenWindow packet = event.cast(); + if (event.getState() == EventState.PRE) { + if (p instanceof SPacketOpenWindow) { + SPacketOpenWindow packet = event.cast(); - // Remove any entries that were created over a second ago, this should make up for INSANE latency - this.futureInventories.removeIf(i -> System.nanoTime() / 1000000L - i.time > 1000); + // Remove any entries that were created over a second ago, this should make up for INSANE latency + this.futureInventories.removeIf(i -> System.nanoTime() / 1000000L - i.time > 1000); - this.futureInventories.stream() - .filter(i -> i.type.equals(packet.getGuiId()) && i.slots == packet.getSlotCount()) - .findFirst().ifPresent(matched -> { - // Remove the future inventory - this.futureInventories.remove(matched); + this.futureInventories.stream() + .filter(i -> i.type.equals(packet.getGuiId()) && i.slots == packet.getSlotCount()) + .findFirst().ifPresent(matched -> { + // Remove the future inventory + this.futureInventories.remove(matched); - // Setup the remembered inventory - RememberedInventory inventory = this.rememberedInventories.computeIfAbsent(matched.pos, pos -> new RememberedInventory()); - inventory.windowId = packet.getWindowId(); - inventory.size = packet.getSlotCount(); - }); - } + // Setup the remembered inventory + RememberedInventory inventory = this.rememberedInventories.computeIfAbsent(matched.pos, pos -> new RememberedInventory()); + inventory.windowId = packet.getWindowId(); + inventory.size = packet.getSlotCount(); + }); + } - if (p instanceof SPacketCloseWindow) { - updateInventory(); - } - break; + if (p instanceof SPacketCloseWindow) { + updateInventory(); } } } @@ -115,6 +129,7 @@ public class MemoryBehavior extends Behavior { }); } + @Override public final RememberedInventory getInventoryByPos(BlockPos pos) { return this.rememberedInventories.get(pos); } @@ -157,7 +172,7 @@ public class MemoryBehavior extends Behavior { *

* Associated with a {@link BlockPos} in {@link MemoryBehavior#rememberedInventories}. */ - public static class RememberedInventory { + public static class RememberedInventory implements IRememberedInventory { /** * The list of items in the inventory @@ -178,11 +193,14 @@ public class MemoryBehavior extends Behavior { this.items = new ArrayList<>(); } - /** - * @return The list of items in the inventory - */ - public final List getItems() { + @Override + public final List getContents() { return this.items; } + + @Override + public final int getSize() { + return this.size; + } } } diff --git a/src/main/java/baritone/behavior/MineBehavior.java b/src/main/java/baritone/behavior/MineBehavior.java new file mode 100644 index 00000000..0f1a6b34 --- /dev/null +++ b/src/main/java/baritone/behavior/MineBehavior.java @@ -0,0 +1,195 @@ +/* + * 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 . + */ + +package baritone.behavior; + +import baritone.Baritone; +import baritone.api.behavior.IMineBehavior; +import baritone.api.event.events.PathEvent; +import baritone.api.event.events.TickEvent; +import baritone.api.pathing.goals.Goal; +import baritone.cache.CachedChunk; +import baritone.cache.ChunkPacker; +import baritone.cache.WorldProvider; +import baritone.cache.WorldScanner; +import baritone.api.pathing.goals.GoalBlock; +import baritone.api.pathing.goals.GoalComposite; +import baritone.api.pathing.goals.GoalTwoBlocks; +import baritone.utils.BlockStateInterface; +import baritone.utils.Helper; +import net.minecraft.block.Block; +import net.minecraft.init.Blocks; +import net.minecraft.item.Item; +import net.minecraft.item.ItemStack; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.EmptyChunk; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Mine blocks of a certain type + * + * @author leijurv + */ +public final class MineBehavior extends Behavior implements IMineBehavior, Helper { + + public static final MineBehavior INSTANCE = new MineBehavior(); + + private List mining; + private List locationsCache; + private int quantity; + + private MineBehavior() {} + + @Override + public void onTick(TickEvent event) { + if (event.getType() == TickEvent.Type.OUT) { + cancel(); + return; + } + if (mining == null) { + return; + } + if (quantity > 0) { + Item item = mining.get(0).getItemDropped(mining.get(0).getDefaultState(), new Random(), 0); + int curr = player().inventory.mainInventory.stream().filter(stack -> item.equals(stack.getItem())).mapToInt(ItemStack::getCount).sum(); + System.out.println("Currently have " + curr + " " + item); + if (curr >= quantity) { + logDirect("Have " + curr + " " + item.getItemStackDisplayName(new ItemStack(item, 1))); + cancel(); + return; + } + } + int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get(); + if (mineGoalUpdateInterval != 0) { + if (event.getCount() % mineGoalUpdateInterval == 0) { + Baritone.INSTANCE.getExecutor().execute(this::updateGoal); + } + } + PathingBehavior.INSTANCE.revalidateGoal(); + } + + @Override + public void onPathEvent(PathEvent event) { + updateGoal(); + } + + private void updateGoal() { + if (mining == null) { + return; + } + if (!locationsCache.isEmpty()) { + locationsCache = prune(new ArrayList<>(locationsCache), mining, 64); + PathingBehavior.INSTANCE.setGoal(coalesce(locationsCache)); + PathingBehavior.INSTANCE.path(); + } + List locs = scanFor(mining, 64); + if (locs.isEmpty()) { + logDebug("No locations for " + mining + " known, cancelling"); + cancel(); + return; + } + locationsCache = locs; + PathingBehavior.INSTANCE.setGoal(coalesce(locs)); + PathingBehavior.INSTANCE.path(); + } + + public GoalComposite coalesce(List locs) { + return new GoalComposite(locs.stream().map(loc -> { + if (!Baritone.settings().forceInternalMining.get()) { + return new GoalTwoBlocks(loc); + } + + boolean upwardGoal = locs.contains(loc.up()) || (Baritone.settings().internalMiningAirException.get() && BlockStateInterface.getBlock(loc.up()) == Blocks.AIR); + boolean downwardGoal = locs.contains(loc.down()) || (Baritone.settings().internalMiningAirException.get() && BlockStateInterface.getBlock(loc.up()) == Blocks.AIR); + if (upwardGoal) { + if (downwardGoal) { + return new GoalTwoBlocks(loc); + } else { + return new GoalBlock(loc); + } + } else { + if (downwardGoal) { + return new GoalBlock(loc.down()); + } else { + return new GoalTwoBlocks(loc); + } + } + }).toArray(Goal[]::new)); + } + + public List scanFor(List mining, int max) { + List locs = new ArrayList<>(); + List uninteresting = new ArrayList<>(); + //long b = System.currentTimeMillis(); + for (Block m : mining) { + if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(m)) { + locs.addAll(WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), 1, 1)); + } else { + uninteresting.add(m); + } + } + //System.out.println("Scan of cached chunks took " + (System.currentTimeMillis() - b) + "ms"); + if (locs.isEmpty()) { + uninteresting = mining; + } + if (!uninteresting.isEmpty()) { + //long before = System.currentTimeMillis(); + locs.addAll(WorldScanner.INSTANCE.scanLoadedChunks(uninteresting, max, 10, 26)); + //System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms"); + } + return prune(locs, mining, max); + } + + public List prune(List locs, List mining, int max) { + BlockPos playerFeet = MineBehavior.INSTANCE.playerFeet(); + locs.sort(Comparator.comparingDouble(playerFeet::distanceSq)); + + // remove any that are within loaded chunks that aren't actually what we want + locs.removeAll(locs.stream() + .filter(pos -> !(MineBehavior.INSTANCE.world().getChunk(pos) instanceof EmptyChunk)) + .filter(pos -> !mining.contains(BlockStateInterface.get(pos).getBlock())) + .collect(Collectors.toList())); + if (locs.size() > max) { + return locs.subList(0, max); + } + return locs; + } + + @Override + public void mine(int quantity, String... blocks) { + this.mining = blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlock).collect(Collectors.toList()); + this.quantity = quantity; + this.locationsCache = new ArrayList<>(); + updateGoal(); + } + + @Override + public void mine(int quantity, Block... blocks) { + this.mining = blocks == null || blocks.length == 0 ? null : Arrays.asList(blocks); + this.quantity = quantity; + this.locationsCache = new ArrayList<>(); + updateGoal(); + } + + @Override + public void cancel() { + mine(0, (String[]) null); + PathingBehavior.INSTANCE.cancel(); + } +} diff --git a/src/main/java/baritone/behavior/impl/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java similarity index 72% rename from src/main/java/baritone/behavior/impl/PathingBehavior.java rename to src/main/java/baritone/behavior/PathingBehavior.java index fa651a87..377af7f3 100644 --- a/src/main/java/baritone/behavior/impl/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -2,51 +2,55 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.behavior.impl; +package baritone.behavior; import baritone.Baritone; +import baritone.api.behavior.IPathingBehavior; import baritone.api.event.events.PathEvent; import baritone.api.event.events.PlayerUpdateEvent; import baritone.api.event.events.RenderEvent; import baritone.api.event.events.TickEvent; -import baritone.behavior.Behavior; +import baritone.api.pathing.goals.Goal; import baritone.pathing.calc.AStarPathFinder; import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.calc.IPathFinder; -import baritone.pathing.goals.*; +import baritone.api.pathing.goals.GoalXZ; import baritone.pathing.movement.MovementHelper; import baritone.pathing.path.IPath; import baritone.pathing.path.PathExecutor; +import baritone.utils.BlockBreakHelper; import baritone.utils.BlockStateInterface; +import baritone.utils.Helper; import baritone.utils.PathRenderer; +import baritone.api.utils.interfaces.IGoalRenderPos; +import baritone.utils.pathing.BetterBlockPos; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.EmptyChunk; -import java.awt.*; +import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.Optional; +import java.util.stream.Collectors; -public class PathingBehavior extends Behavior { +public final class PathingBehavior extends Behavior implements IPathingBehavior, Helper { public static final PathingBehavior INSTANCE = new PathingBehavior(); - private PathingBehavior() { - } - private PathExecutor current; private PathExecutor next; @@ -59,8 +63,10 @@ public class PathingBehavior extends Behavior { private boolean lastAutoJump; + private PathingBehavior() {} + private void dispatchPathEvent(PathEvent event) { - new Thread(() -> Baritone.INSTANCE.getGameEventHandler().onPathEvent(event)).start(); + Baritone.INSTANCE.getExecutor().execute(() -> Baritone.INSTANCE.getGameEventHandler().onPathEvent(event)); } @Override @@ -69,6 +75,7 @@ public class PathingBehavior extends Behavior { this.cancel(); return; } + mc.playerController.setPlayerCapabilities(mc.player); if (current == null) { return; } @@ -77,14 +84,14 @@ public class PathingBehavior extends Behavior { if (current.failed() || current.finished()) { current = null; if (goal == null || goal.isInGoal(playerFeet())) { - displayChatMessageRaw("All done. At " + goal); + logDebug("All done. At " + goal); dispatchPathEvent(PathEvent.AT_GOAL); next = null; return; } if (next != null && !next.getPath().positions().contains(playerFeet())) { // if the current path failed, we may not actually be on the next one, so make sure - displayChatMessageRaw("Discarding next path as it does not contain current position"); + logDebug("Discarding next path as it does not contain current position"); // for example if we had a nicely planned ahead path that starts where current ends // that's all fine and good // but if we fail in the middle of current @@ -94,7 +101,7 @@ public class PathingBehavior extends Behavior { next = null; } if (next != null) { - displayChatMessageRaw("Continuing on to planned next path"); + logDebug("Continuing on to planned next path"); dispatchPathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT); current = next; next = null; @@ -118,7 +125,7 @@ public class PathingBehavior extends Behavior { if (next != null) { if (next.getPath().positions().contains(playerFeet())) { // jump directly onto the next path - displayChatMessageRaw("Splicing into planned next path early..."); + logDebug("Splicing into planned next path early..."); dispatchPathEvent(PathEvent.SPLICING_ONTO_NEXT_EARLY); current = next; next = null; @@ -141,7 +148,7 @@ public class PathingBehavior extends Behavior { } if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) { // and this path has 5 seconds or less left - displayChatMessageRaw("Path almost over. Planning ahead..."); + logDebug("Path almost over. Planning ahead..."); dispatchPathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED); findPathInNewThread(current.getPath().getDest(), false, Optional.of(current.getPath())); } @@ -160,10 +167,13 @@ public class PathingBehavior extends Behavior { case POST: mc.gameSettings.autoJump = lastAutoJump; break; + default: + break; } } } + @Override public Optional ticksRemainingInSegment() { if (current == null) { return Optional.empty(); @@ -171,10 +181,12 @@ public class PathingBehavior extends Behavior { return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition())); } + @Override public void setGoal(Goal goal) { this.goal = goal; } + @Override public Goal getGoal() { return goal; } @@ -187,15 +199,30 @@ public class PathingBehavior extends Behavior { return next; } + // TODO: Expose this method in the API? + // In order to do so, we'd need to move over IPath which has a whole lot of references to other + // things that may not need to be exposed necessarily, so we'll need to figure that out. public Optional getPath() { return Optional.ofNullable(current).map(PathExecutor::getPath); } + @Override + public boolean isPathing() { + return this.current != null; + } + + @Override public void cancel() { + dispatchPathEvent(PathEvent.CANCELED); current = null; next = null; Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(AbstractNodeCostSearch::cancel); + BlockBreakHelper.stopBreakingBlock(); + } + + public void forceCancel() { // NOT exposed on public api + isPathCalcInProgress = false; } /** @@ -203,6 +230,7 @@ public class PathingBehavior extends Behavior { * * @return true if this call started path calculation, false if it was already calculating or executing a path */ + @Override public boolean path() { if (goal == null) { return false; @@ -225,8 +253,11 @@ public class PathingBehavior extends Behavior { } } - public BlockPos pathStart() { - BlockPos feet = playerFeet(); + /** + * @return The starting {@link BlockPos} for a new path + */ + private BlockPos pathStart() { + BetterBlockPos feet = playerFeet(); if (BlockStateInterface.get(feet.down()).getBlock().equals(Blocks.AIR) && MovementHelper.canWalkOn(feet.down().down())) { return feet.down(); } @@ -246,9 +277,9 @@ public class PathingBehavior extends Behavior { } isPathCalcInProgress = true; } - new Thread(() -> { + Baritone.INSTANCE.getExecutor().execute(() -> { if (talkAboutIt) { - displayChatMessageRaw("Starting to search for path from " + start + " to " + goal); + logDebug("Starting to search for path from " + start + " to " + goal); } Optional path = findPath(start, previous); @@ -280,16 +311,16 @@ public class PathingBehavior extends Behavior { if (talkAboutIt && current != null && current.getPath() != null) { if (goal == null || goal.isInGoal(current.getPath().getDest())) { - displayChatMessageRaw("Finished finding a path from " + start + " to " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered"); + logDebug("Finished finding a path from " + start + " to " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered"); } else { - displayChatMessageRaw("Found path segment from " + start + " towards " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered"); + logDebug("Found path segment from " + start + " towards " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered"); } } synchronized (pathCalcLock) { isPathCalcInProgress = false; } - }).start(); + }); } /** @@ -301,26 +332,18 @@ public class PathingBehavior extends Behavior { private Optional findPath(BlockPos start, Optional previous) { Goal goal = this.goal; if (goal == null) { - displayChatMessageRaw("no goal"); + logDebug("no goal"); return Optional.empty(); } if (Baritone.settings().simplifyUnloadedYCoord.get()) { BlockPos pos = null; - if (goal instanceof GoalBlock) { - pos = ((GoalBlock) goal).getGoalPos(); - } - if (goal instanceof GoalTwoBlocks) { - pos = ((GoalTwoBlocks) goal).getGoalPos(); - } - if (goal instanceof GoalNear) { - pos = ((GoalNear) goal).getGoalPos(); - } - if (goal instanceof GoalGetToBlock) { - pos = ((GoalGetToBlock) goal).getGoalPos(); + if (goal instanceof IGoalRenderPos) { + pos = ((IGoalRenderPos) goal).getGoalPos(); } + // TODO simplify each individual goal in a GoalComposite if (pos != null && world().getChunk(pos) instanceof EmptyChunk) { - displayChatMessageRaw("Simplifying " + goal.getClass() + " to GoalXZ due to distance"); + logDebug("Simplifying " + goal.getClass() + " to GoalXZ due to distance"); goal = new GoalXZ(pos.getX(), pos.getZ()); } } @@ -330,29 +353,46 @@ public class PathingBehavior extends Behavior { } else { timeout = Baritone.settings().planAheadTimeoutMS.get(); } + Optional> favoredPositions = previous.map(IPath::positions).map(Collection::stream).map(x -> x.map(y -> y.hashCode)).map(x -> x.collect(Collectors.toList())).map(HashSet::new); // <-- okay this is EPIC try { - IPathFinder pf = new AStarPathFinder(start, goal, previous.map(IPath::positions)); + IPathFinder pf = new AStarPathFinder(start, goal, favoredPositions); return pf.calculate(timeout); } catch (Exception e) { - displayChatMessageRaw("Pathing exception: " + e); + logDebug("Pathing exception: " + e); e.printStackTrace(); return Optional.empty(); } } + public void revalidateGoal() { + if (!Baritone.settings().cancelOnGoalInvalidation.get()) { + return; + } + if (current == null || goal == null) { + return; + } + Goal intended = current.getPath().getGoal(); + BlockPos end = current.getPath().getDest(); + if (intended.isInGoal(end) && !goal.isInGoal(end)) { + // this path used to end in the goal + // but the goal has changed, so there's no reason to continue... + cancel(); + } + } + @Override public void onRenderPass(RenderEvent event) { // System.out.println("Render passing"); // System.out.println(event.getPartialTicks()); float partialTicks = event.getPartialTicks(); if (goal != null && Baritone.settings().renderGoal.value) { - PathRenderer.drawLitDankGoalBox(player(), goal, partialTicks, Color.GREEN); + PathRenderer.drawLitDankGoalBox(player(), goal, partialTicks, Baritone.settings().colorGoalBox.get()); } if (!Baritone.settings().renderPath.get()) { return; } - long start = System.nanoTime(); + //long start = System.nanoTime(); PathExecutor current = this.current; // this should prevent most race conditions? @@ -363,34 +403,39 @@ public class PathingBehavior extends Behavior { // Render the current path, if there is one if (current != null && current.getPath() != null) { int renderBegin = Math.max(current.getPosition() - 3, 0); - PathRenderer.drawPath(current.getPath(), renderBegin, player(), partialTicks, Color.RED, Baritone.settings().fadePath.get(), 10, 20); + PathRenderer.drawPath(current.getPath(), renderBegin, player(), partialTicks, Baritone.settings().colorCurrentPath.get(), Baritone.settings().fadePath.get(), 10, 20); } if (next != null && next.getPath() != null) { - PathRenderer.drawPath(next.getPath(), 0, player(), partialTicks, Color.MAGENTA, Baritone.settings().fadePath.get(), 10, 20); + PathRenderer.drawPath(next.getPath(), 0, player(), partialTicks, Baritone.settings().colorNextPath.get(), Baritone.settings().fadePath.get(), 10, 20); } - long split = System.nanoTime(); + //long split = System.nanoTime(); if (current != null) { - PathRenderer.drawManySelectionBoxes(player(), current.toBreak(), partialTicks, Color.RED); - PathRenderer.drawManySelectionBoxes(player(), current.toPlace(), partialTicks, Color.GREEN); - PathRenderer.drawManySelectionBoxes(player(), current.toWalkInto(), partialTicks, Color.MAGENTA); + PathRenderer.drawManySelectionBoxes(player(), current.toBreak(), partialTicks, Baritone.settings().colorBlocksToBreak.get()); + PathRenderer.drawManySelectionBoxes(player(), current.toPlace(), partialTicks, Baritone.settings().colorBlocksToPlace.get()); + PathRenderer.drawManySelectionBoxes(player(), current.toWalkInto(), partialTicks, Baritone.settings().colorBlocksToWalkInto.get()); } // If there is a path calculation currently running, render the path calculation process AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(currentlyRunning -> { currentlyRunning.bestPathSoFar().ifPresent(p -> { - PathRenderer.drawPath(p, 0, player(), partialTicks, Color.BLUE, Baritone.settings().fadePath.get(), 10, 20); + PathRenderer.drawPath(p, 0, player(), partialTicks, Baritone.settings().colorBestPathSoFar.get(), Baritone.settings().fadePath.get(), 10, 20); currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> { - PathRenderer.drawPath(mr, 0, player(), partialTicks, Color.CYAN, Baritone.settings().fadePath.get(), 10, 20); - PathRenderer.drawManySelectionBoxes(player(), Collections.singletonList(mr.getDest()), partialTicks, Color.CYAN); + PathRenderer.drawPath(mr, 0, player(), partialTicks, Baritone.settings().colorMostRecentConsidered.get(), Baritone.settings().fadePath.get(), 10, 20); + PathRenderer.drawManySelectionBoxes(player(), Collections.singletonList(mr.getDest()), partialTicks, Baritone.settings().colorMostRecentConsidered.get()); }); }); }); - long end = System.nanoTime(); + //long end = System.nanoTime(); //System.out.println((end - split) + " " + (split - start)); - // if (end - start > 0) + // if (end - start > 0) { // System.out.println("Frame took " + (split - start) + " " + (end - split)); + //} + } + @Override + public void onDisable() { + Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); } } diff --git a/src/main/java/baritone/behavior/impl/FollowBehavior.java b/src/main/java/baritone/behavior/impl/FollowBehavior.java deleted file mode 100644 index 55ec5539..00000000 --- a/src/main/java/baritone/behavior/impl/FollowBehavior.java +++ /dev/null @@ -1,60 +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 General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.behavior.impl; - -import baritone.api.event.events.TickEvent; -import baritone.behavior.Behavior; -import baritone.pathing.goals.GoalNear; -import net.minecraft.entity.Entity; -import net.minecraft.util.math.BlockPos; - -/** - * Follow an entity - * - * @author leijurv - */ -public class FollowBehavior extends Behavior { - public static final FollowBehavior INSTANCE = new FollowBehavior(); - - private FollowBehavior() { - } - - Entity following; - - @Override - public void onTick(TickEvent event) { - if (event.getType() == TickEvent.Type.OUT) { - return; - } - if (following == null) { - return; - } - // lol this is trashy but it works - PathingBehavior.INSTANCE.setGoal(new GoalNear(new BlockPos(following), 3)); - PathingBehavior.INSTANCE.path(); - } - - public void follow(Entity follow) { - this.following = follow; - } - - public void cancel() { - PathingBehavior.INSTANCE.cancel(); - follow(null); - } -} diff --git a/src/main/java/baritone/behavior/impl/MineBehavior.java b/src/main/java/baritone/behavior/impl/MineBehavior.java deleted file mode 100644 index 32f92877..00000000 --- a/src/main/java/baritone/behavior/impl/MineBehavior.java +++ /dev/null @@ -1,86 +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 General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.behavior.impl; - -import baritone.api.event.events.TickEvent; -import baritone.behavior.Behavior; -import baritone.chunk.ChunkPacker; -import baritone.chunk.WorldProvider; -import baritone.pathing.goals.Goal; -import baritone.pathing.goals.GoalComposite; -import baritone.pathing.goals.GoalTwoBlocks; -import baritone.utils.BlockStateInterface; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.chunk.EmptyChunk; - -import java.util.ArrayList; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Mine blocks of a certain type - * - * @author leijurv - */ -public class MineBehavior extends Behavior { - public static final MineBehavior INSTANCE = new MineBehavior(); - - private MineBehavior() { - } - - String mining; - - @Override - public void onTick(TickEvent event) { - if (event.getType() == TickEvent.Type.OUT) { - return; - } - if (mining == null) { - return; - } - List locs = new ArrayList<>(WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(mining, 1, 1)); - BlockPos playerFeet = playerFeet(); - locs.sort(Comparator.comparingDouble(playerFeet::distanceSq)); - - // remove any that are within loaded chunks that aren't actually what we want - locs.removeAll(locs.stream() - .filter(pos -> !(world().getChunk(pos) instanceof EmptyChunk)) - .filter(pos -> !ChunkPacker.blockToString(BlockStateInterface.get(pos).getBlock()).equalsIgnoreCase(mining)) - .collect(Collectors.toList())); - if (locs.size() > 30) { - locs = locs.subList(0, 30); - } - if (locs.isEmpty()) { - displayChatMessageRaw("No locations for " + mining + " known, cancelling"); - cancel(); - return; - } - PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalTwoBlocks::new).toArray(Goal[]::new))); - PathingBehavior.INSTANCE.path(); - } - - public void mine(String mining) { - this.mining = mining; - } - - public void cancel() { - PathingBehavior.INSTANCE.cancel(); - mine(null); - } -} diff --git a/src/main/java/baritone/chunk/CachedChunk.java b/src/main/java/baritone/cache/CachedChunk.java similarity index 87% rename from src/main/java/baritone/chunk/CachedChunk.java rename to src/main/java/baritone/cache/CachedChunk.java index 418a015e..b8d88a49 100644 --- a/src/main/java/baritone/chunk/CachedChunk.java +++ b/src/main/java/baritone/cache/CachedChunk.java @@ -2,22 +2,23 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.chunk; +package baritone.cache; -import baritone.utils.pathing.IBlockTypeAccess; +import baritone.api.cache.IBlockTypeAccess; +import baritone.utils.Helper; import baritone.utils.pathing.PathingBlockType; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; @@ -30,7 +31,7 @@ import java.util.*; * @author Brady * @since 8/3/2018 1:04 AM */ -public final class CachedChunk implements IBlockTypeAccess { +public final class CachedChunk implements IBlockTypeAccess, Helper { public static final Set BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(new HashSet() {{ add(Blocks.DIAMOND_ORE); @@ -63,6 +64,8 @@ public final class CachedChunk implements IBlockTypeAccess { add(Blocks.DRAGON_EGG); add(Blocks.JUKEBOX); add(Blocks.END_GATEWAY); + add(Blocks.WEB); + add(Blocks.NETHER_WART); }}); /** @@ -97,13 +100,13 @@ public final class CachedChunk implements IBlockTypeAccess { /** * The block names of each surface level block for generating an overview */ - private final String[] overview; + private final IBlockState[] overview; private final int[] heightMap; private final Map> specialBlockLocations; - CachedChunk(int x, int z, BitSet data, String[] overview, Map> specialBlockLocations) { + CachedChunk(int x, int z, BitSet data, IBlockState[] overview, Map> specialBlockLocations) { validateSize(data); this.x = x; @@ -120,14 +123,16 @@ public final class CachedChunk implements IBlockTypeAccess { int internalPos = z << 4 | x; if (heightMap[internalPos] == y) { // we have this exact block, it's a surface block - IBlockState state = ChunkPacker.stringToBlock(overview[internalPos]).getDefaultState(); /*System.out.println("Saying that " + x + "," + y + "," + z + " is " + state); if (!Minecraft.getMinecraft().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock().equals(state.getBlock())) { throw new IllegalStateException("failed " + Minecraft.getMinecraft().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock() + " " + state.getBlock() + " " + (x + this.x * 16) + " " + y + " " + (z + this.z * 16)); }*/ - return state; + return overview[internalPos]; } PathingBlockType type = getType(x, y, z); + if (type == PathingBlockType.SOLID && y == 127 && mc.player.dimension == -1) { + return Blocks.BEDROCK.getDefaultState(); + } return ChunkPacker.pathingTypeToBlock(type); } @@ -152,7 +157,7 @@ public final class CachedChunk implements IBlockTypeAccess { } } - public final String[] getOverview() { + public final IBlockState[] getOverview() { return overview; } @@ -199,7 +204,8 @@ public final class CachedChunk implements IBlockTypeAccess { * @throws IllegalArgumentException if the bitset size exceeds the maximum size */ private static void validateSize(BitSet data) { - if (data.size() > SIZE) + if (data.size() > SIZE) { throw new IllegalArgumentException("BitSet of invalid length provided"); + } } } diff --git a/src/main/java/baritone/chunk/CachedRegion.java b/src/main/java/baritone/cache/CachedRegion.java similarity index 92% rename from src/main/java/baritone/chunk/CachedRegion.java rename to src/main/java/baritone/cache/CachedRegion.java index e15164e4..e9402bd5 100644 --- a/src/main/java/baritone/chunk/CachedRegion.java +++ b/src/main/java/baritone/cache/CachedRegion.java @@ -2,22 +2,22 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.chunk; +package baritone.cache; -import baritone.utils.pathing.IBlockTypeAccess; +import baritone.api.cache.ICachedRegion; import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; @@ -33,7 +33,8 @@ import java.util.zip.GZIPOutputStream; * @author Brady * @since 8/3/2018 9:35 PM */ -public final class CachedRegion implements IBlockTypeAccess { +public final class CachedRegion implements ICachedRegion { + private static final byte CHUNK_NOT_PRESENT = 0; private static final byte CHUNK_PRESENT = 1; @@ -77,6 +78,7 @@ public final class CachedRegion implements IBlockTypeAccess { return null; } + @Override public final boolean isCached(int x, int z) { return chunks[x >> 4][z >> 4] != null; } @@ -100,7 +102,7 @@ public final class CachedRegion implements IBlockTypeAccess { return res; } - final synchronized void updateCachedChunk(int chunkX, int chunkZ, CachedChunk chunk) { + public final synchronized void updateCachedChunk(int chunkX, int chunkZ, CachedChunk chunk) { this.chunks[chunkX][chunkZ] = chunk; hasUnsavedChanges = true; } @@ -112,13 +114,15 @@ public final class CachedRegion implements IBlockTypeAccess { } try { Path path = Paths.get(directory); - if (!Files.exists(path)) + if (!Files.exists(path)) { Files.createDirectories(path); + } System.out.println("Saving region " + x + "," + z + " to disk " + path); Path regionFile = getRegionFile(path, this.x, this.z); - if (!Files.exists(regionFile)) + if (!Files.exists(regionFile)) { Files.createFile(regionFile); + } try ( FileOutputStream fileOut = new FileOutputStream(regionFile.toFile()); GZIPOutputStream gzipOut = new GZIPOutputStream(fileOut, 16384); @@ -143,7 +147,7 @@ public final class CachedRegion implements IBlockTypeAccess { for (int x = 0; x < 32; x++) { if (chunks[x][z] != null) { for (int i = 0; i < 256; i++) { - out.writeUTF(chunks[x][z].getOverview()[i]); + out.writeUTF(ChunkPacker.blockToString(chunks[x][z].getOverview()[i].getBlock())); } } } @@ -175,12 +179,14 @@ public final class CachedRegion implements IBlockTypeAccess { public synchronized void load(String directory) { try { Path path = Paths.get(directory); - if (!Files.exists(path)) + if (!Files.exists(path)) { Files.createDirectories(path); + } Path regionFile = getRegionFile(path, this.x, this.z); - if (!Files.exists(regionFile)) + if (!Files.exists(regionFile)) { return; + } System.out.println("Loading region " + x + "," + z + " from disk " + path); long start = System.nanoTime() / 1000000L; @@ -211,7 +217,7 @@ public final class CachedRegion implements IBlockTypeAccess { int regionZ = this.z; int chunkX = x + 32 * regionX; int chunkZ = z + 32 * regionZ; - tmpCached[x][z] = new CachedChunk(chunkX, chunkZ, BitSet.valueOf(bytes), new String[256], location[x][z]); + tmpCached[x][z] = new CachedChunk(chunkX, chunkZ, BitSet.valueOf(bytes), new IBlockState[256], location[x][z]); break; case CHUNK_NOT_PRESENT: tmpCached[x][z] = null; @@ -225,7 +231,7 @@ public final class CachedRegion implements IBlockTypeAccess { for (int x = 0; x < 32; x++) { if (tmpCached[x][z] != null) { for (int i = 0; i < 256; i++) { - tmpCached[x][z].getOverview()[i] = in.readUTF(); + tmpCached[x][z].getOverview()[i] = ChunkPacker.stringToBlock(in.readUTF()).getDefaultState(); } } } @@ -276,6 +282,7 @@ public final class CachedRegion implements IBlockTypeAccess { /** * @return The region x coordinate */ + @Override public final int getX() { return this.x; } @@ -283,6 +290,7 @@ public final class CachedRegion implements IBlockTypeAccess { /** * @return The region z coordinate */ + @Override public final int getZ() { return this.z; } diff --git a/src/main/java/baritone/chunk/CachedWorld.java b/src/main/java/baritone/cache/CachedWorld.java similarity index 76% rename from src/main/java/baritone/chunk/CachedWorld.java rename to src/main/java/baritone/cache/CachedWorld.java index 56d8ef38..3901303d 100644 --- a/src/main/java/baritone/chunk/CachedWorld.java +++ b/src/main/java/baritone/cache/CachedWorld.java @@ -2,41 +2,42 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.chunk; +package baritone.cache; import baritone.Baritone; -import baritone.utils.pathing.IBlockTypeAccess; +import baritone.api.cache.ICachedWorld; +import baritone.utils.Helper; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; -import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.Chunk; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.LinkedList; +import java.util.List; import java.util.concurrent.LinkedBlockingQueue; -import java.util.function.Consumer; /** * @author Brady * @since 8/4/2018 12:02 AM */ -public final class CachedWorld implements IBlockTypeAccess { +public final class CachedWorld implements ICachedWorld, Helper { /** * The maximum number of regions in any direction from (0,0) @@ -66,8 +67,8 @@ public final class CachedWorld implements IBlockTypeAccess { System.out.println("Cached world directory: " + directory); // Insert an invalid region element cachedRegions.put(0, null); - new PackerThread().start(); - new Thread(() -> { + Baritone.INSTANCE.getExecutor().execute(new PackerThread()); + Baritone.INSTANCE.getExecutor().execute(() -> { try { Thread.sleep(30000); while (true) { @@ -80,9 +81,10 @@ public final class CachedWorld implements IBlockTypeAccess { } catch (InterruptedException e) { e.printStackTrace(); } - }).start(); + }); } + @Override public final void queueForPacking(Chunk chunk) { try { toPack.put(chunk); @@ -92,27 +94,16 @@ public final class CachedWorld implements IBlockTypeAccess { } @Override - public final IBlockState getBlock(int x, int y, int z) { - // no point in doing getOrCreate region, if we don't have it we don't have it - CachedRegion region = getRegion(x >> 9, z >> 9); - if (region == null) { - return null; - } - return region.getBlock(x & 511, y, z & 511); - } - - public final boolean isCached(BlockPos pos) { - int x = pos.getX(); - int z = pos.getZ(); - CachedRegion region = getRegion(x >> 9, z >> 9); + public final boolean isCached(int blockX, int blockZ) { + CachedRegion region = getRegion(blockX >> 9, blockZ >> 9); if (region == null) { return false; } - return region.isCached(x & 511, z & 511); + return region.isCached(blockX & 511, blockZ & 511); } - - public final LinkedList getLocationsOf(String block, int minimum, int maxRegionDistanceSq) { + @Override + public final LinkedList getLocationsOf(String block, int maximum, int maxRegionDistanceSq) { LinkedList res = new LinkedList<>(); int playerRegionX = playerFeet().getX() >> 9; int playerRegionZ = playerFeet().getZ() >> 9; @@ -128,12 +119,13 @@ public final class CachedWorld implements IBlockTypeAccess { int regionX = xoff + playerRegionX; int regionZ = zoff + playerRegionZ; CachedRegion region = getOrCreateRegion(regionX, regionZ); - if (region != null) - for (BlockPos pos : region.getLocationsOf(block)) - res.add(pos); + if (region != null) { + // TODO: 100% verify if this or addAll is faster. + region.getLocationsOf(block).forEach(res::add); + } } } - if (res.size() >= minimum) { + if (res.size() >= maximum) { return res; } searchRadius++; @@ -146,38 +138,40 @@ public final class CachedWorld implements IBlockTypeAccess { region.updateCachedChunk(chunk.x & 31, chunk.z & 31, chunk); } + @Override public final void save() { if (!Baritone.settings().chunkCaching.get()) { System.out.println("Not saving to disk; chunk caching is disabled."); return; } long start = System.nanoTime() / 1000000L; - this.cachedRegions.values().parallelStream().forEach(region -> { - if (region != null) + allRegions().parallelStream().forEach(region -> { + if (region != null) { region.save(this.directory); + } }); long now = System.nanoTime() / 1000000L; System.out.println("World save took " + (now - start) + "ms"); } + private synchronized List allRegions() { + return new ArrayList<>(this.cachedRegions.values()); + } + + @Override public final void reloadAllFromDisk() { long start = System.nanoTime() / 1000000L; - this.cachedRegions.values().forEach(region -> { - if (region != null) + allRegions().forEach(region -> { + if (region != null) { region.load(this.directory); + } }); long now = System.nanoTime() / 1000000L; System.out.println("World load took " + (now - start) + "ms"); } - /** - * Returns the region at the specified region coordinates - * - * @param regionX The region X coordinate - * @param regionZ The region Z coordinate - * @return The region located at the specified coordinates - */ - public final CachedRegion getRegion(int regionX, int regionZ) { + @Override + public final synchronized CachedRegion getRegion(int regionX, int regionZ) { return cachedRegions.get(getRegionID(regionX, regionZ)); } @@ -197,13 +191,6 @@ public final class CachedWorld implements IBlockTypeAccess { }); } - public void forEachRegion(Consumer consumer) { - this.cachedRegions.forEach((id, r) -> { - if (r != null) - consumer.accept(r); - }); - } - /** * Returns the region ID based on the region coordinates. 0 will be * returned if the specified region coordinates are out of bounds. @@ -213,8 +200,9 @@ public final class CachedWorld implements IBlockTypeAccess { * @return The region ID */ private long getRegionID(int regionX, int regionZ) { - if (!isRegionInWorld(regionX, regionZ)) + if (!isRegionInWorld(regionX, regionZ)) { return 0; + } return (long) regionX & 0xFFFFFFFFL | ((long) regionZ & 0xFFFFFFFFL) << 32; } @@ -230,9 +218,10 @@ public final class CachedWorld implements IBlockTypeAccess { return regionX <= REGION_MAX && regionX >= -REGION_MAX && regionZ <= REGION_MAX && regionZ >= -REGION_MAX; } - private class PackerThread extends Thread { + private class PackerThread implements Runnable { public void run() { while (true) { + // TODO: Add CachedWorld unloading to remove the redundancy of having this LinkedBlockingQueue queue = toPack; if (queue == null) { break; diff --git a/src/main/java/baritone/cache/ChunkPacker.java b/src/main/java/baritone/cache/ChunkPacker.java new file mode 100644 index 00000000..4164be3c --- /dev/null +++ b/src/main/java/baritone/cache/ChunkPacker.java @@ -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 . + */ + +package baritone.cache; + +import baritone.pathing.movement.MovementHelper; +import baritone.utils.Helper; +import baritone.utils.pathing.PathingBlockType; +import net.minecraft.block.Block; +import net.minecraft.block.BlockDoublePlant; +import net.minecraft.block.BlockFlower; +import net.minecraft.block.BlockTallGrass; +import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.util.ResourceLocation; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.BlockStateContainer; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; + +import java.util.*; + +/** + * @author Brady + * @since 8/3/2018 1:09 AM + */ +public final class ChunkPacker implements Helper { + + private ChunkPacker() {} + + public static CachedChunk pack(Chunk chunk) { + //long start = System.nanoTime() / 1000000L; + + Map> specialBlocks = new HashMap<>(); + BitSet bitSet = new BitSet(CachedChunk.SIZE); + try { + ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); + for (int y0 = 0; y0 < 16; y0++) { + ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; + if (extendedblockstorage == null) { + // any 16x16x16 area that's all air will have null storage + // for example, in an ocean biome, with air from y=64 to y=256 + // the first 4 extended blocks storages will be full + // and the remaining 12 will be null + + // since the index into the bitset is calculated from the x y and z + // and doesn't function as an append, we can entirely skip the scanning + // since a bitset is initialized to all zero, and air is saved as zeros + continue; + } + BlockStateContainer bsc = extendedblockstorage.getData(); + int yReal = y0 << 4; + // the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x; + // for better cache locality, iterate in that order + for (int y1 = 0; y1 < 16; y1++) { + int y = y1 | yReal; + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + int index = CachedChunk.getPositionIndex(x, y, z); + IBlockState state = bsc.get(x, y1, z); + boolean[] bits = getPathingBlockType(state).getBits(); + bitSet.set(index, bits[0]); + bitSet.set(index + 1, bits[1]); + Block block = state.getBlock(); + if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(block)) { + String name = blockToString(block); + specialBlocks.computeIfAbsent(name, b -> new ArrayList<>()).add(new BlockPos(x, y, z)); + } + } + } + } + } + } catch (Exception e) { + e.printStackTrace(); + } + //long end = System.nanoTime() / 1000000L; + //System.out.println("Chunk packing took " + (end - start) + "ms for " + chunk.x + "," + chunk.z); + IBlockState[] blocks = new IBlockState[256]; + + for (int z = 0; z < 16; z++) { + // @formatter:off + https://www.ibm.com/developerworks/library/j-perry-writing-good-java-code/index.html + // @formatter:on + for (int x = 0; x < 16; x++) { + for (int y = 255; y >= 0; y--) { + int index = CachedChunk.getPositionIndex(x, y, z); + if (bitSet.get(index) || bitSet.get(index + 1)) { + blocks[z << 4 | x] = chunk.getBlockState(x, y, z); + continue https; + } + } + blocks[z << 4 | x] = Blocks.AIR.getDefaultState(); + } + } + return new CachedChunk(chunk.x, chunk.z, bitSet, blocks, specialBlocks); + } + + public static String blockToString(Block block) { + ResourceLocation loc = Block.REGISTRY.getNameForObject(block); + String name = loc.getPath(); // normally, only write the part after the minecraft: + if (!loc.getNamespace().equals("minecraft")) { + // Baritone is running on top of forge with mods installed, perhaps? + name = loc.toString(); // include the namespace with the colon + } + return name; + } + + public static Block stringToBlock(String name) { + return Block.getBlockFromName(name.contains(":") ? name : "minecraft:" + name); + } + + private static PathingBlockType getPathingBlockType(IBlockState state) { + Block block = state.getBlock(); + if (block.equals(Blocks.WATER)) { + // only water source blocks are plausibly usable, flowing water should be avoid + return PathingBlockType.WATER; + } + + if (MovementHelper.avoidWalkingInto(block) || block == Blocks.FLOWING_WATER || MovementHelper.isBottomSlab(state)) { + return PathingBlockType.AVOID; + } + // We used to do an AABB check here + // however, this failed in the nether when you were near a nether fortress + // because fences check their adjacent blocks in the world for their fence connection status to determine AABB shape + // this caused a nullpointerexception when we saved chunks on unload, because they were unable to check their neighbors + if (block == Blocks.AIR || block instanceof BlockTallGrass || block instanceof BlockDoublePlant || block instanceof BlockFlower) { + return PathingBlockType.AIR; + } + + return PathingBlockType.SOLID; + } + + public static IBlockState pathingTypeToBlock(PathingBlockType type) { + switch (type) { + case AIR: + return Blocks.AIR.getDefaultState(); + case WATER: + return Blocks.WATER.getDefaultState(); + case AVOID: + return Blocks.LAVA.getDefaultState(); + case SOLID: + // Dimension solid types + switch (mc.player.dimension) { + case -1: + return Blocks.NETHERRACK.getDefaultState(); + case 0: + default: // The fallback solid type + return Blocks.STONE.getDefaultState(); + case 1: + return Blocks.END_STONE.getDefaultState(); + } + default: + return null; + } + } +} diff --git a/src/main/java/baritone/chunk/Waypoint.java b/src/main/java/baritone/cache/Waypoint.java similarity index 50% rename from src/main/java/baritone/chunk/Waypoint.java rename to src/main/java/baritone/cache/Waypoint.java index 8b290d56..00f4410a 100644 --- a/src/main/java/baritone/chunk/Waypoint.java +++ b/src/main/java/baritone/cache/Waypoint.java @@ -2,91 +2,97 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.chunk; +package baritone.cache; -import com.google.common.collect.ImmutableList; +import baritone.api.cache.IWaypoint; import net.minecraft.util.math.BlockPos; -import org.apache.commons.lang3.ArrayUtils; -import java.util.*; +import java.util.Date; /** - * A single waypoint + * Basic implementation of {@link IWaypoint} * * @author leijurv */ -public class Waypoint { +public class Waypoint implements IWaypoint { - public final String name; - public final Tag tag; + private final String name; + private final Tag tag; private final long creationTimestamp; - public final BlockPos location; + private final BlockPos location; public Waypoint(String name, Tag tag, BlockPos location) { this(name, tag, location, System.currentTimeMillis()); } - Waypoint(String name, Tag tag, BlockPos location, long creationTimestamp) { // read from disk + /** + * Constructor called when a Waypoint is read from disk, adds the creationTimestamp + * as a parameter so that it is reserved after a waypoint is wrote to the disk. + * + * @param name The waypoint name + * @param tag The waypoint tag + * @param location The waypoint location + * @param creationTimestamp When the waypoint was created + */ + Waypoint(String name, Tag tag, BlockPos location, long creationTimestamp) { this.name = name; this.tag = tag; this.location = location; this.creationTimestamp = creationTimestamp; } - @Override - public boolean equals(Object o) { - if (o == null) { - return false; - } - if (!(o instanceof Waypoint)) { - return false; - } - Waypoint w = (Waypoint) o; - return name.equals(w.name) && tag == w.tag && location.equals(w.location); - } - @Override public int hashCode() { return name.hashCode() + tag.hashCode() + location.hashCode(); //lol } - public long creationTimestamp() { - return creationTimestamp; + @Override + public String getName() { + return this.name; } + @Override + public Tag getTag() { + return this.tag; + } + + @Override + public long getCreationTimestamp() { + return this.creationTimestamp; + } + + @Override + public BlockPos getLocation() { + return this.location; + } + + @Override public String toString() { return name + " " + location.toString() + " " + new Date(creationTimestamp).toString(); } - public enum Tag { - HOME("home", "base"), - DEATH("death"), - BED("bed", "spawn"), - USER(); - - private static final List TAG_LIST = ImmutableList.builder().add(Tag.values()).build(); - - private final String[] names; - - Tag(String... names) { - this.names = names; + @Override + public boolean equals(Object o) { + if (o == null) { + return false; } - - public static Tag fromString(String name) { - return TAG_LIST.stream().filter(tag -> ArrayUtils.contains(tag.names, name.toLowerCase())).findFirst().orElse(null); + if (!(o instanceof IWaypoint)) { + return false; } + IWaypoint w = (IWaypoint) o; + return name.equals(w.getName()) && tag == w.getTag() && location.equals(w.getLocation()); } } diff --git a/src/main/java/baritone/chunk/Waypoints.java b/src/main/java/baritone/cache/Waypoints.java similarity index 59% rename from src/main/java/baritone/chunk/Waypoints.java rename to src/main/java/baritone/cache/Waypoints.java index d75ff733..2122ddaf 100644 --- a/src/main/java/baritone/chunk/Waypoints.java +++ b/src/main/java/baritone/cache/Waypoints.java @@ -2,34 +2,37 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.chunk; +package baritone.cache; +import baritone.api.cache.IWaypoint; +import baritone.api.cache.IWaypointCollection; import net.minecraft.util.math.BlockPos; import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.util.*; +import java.util.stream.Collectors; /** * Waypoints for a world * * @author leijurv */ -public class Waypoints { +public class Waypoints implements IWaypointCollection { /** * Magic value to detect invalid waypoint files @@ -37,7 +40,7 @@ public class Waypoints { private static final long WAYPOINT_MAGIC_VALUE = 121977993584L; // good value private final Path directory; - private final Map> waypoints; + private final Map> waypoints; Waypoints(Path directory) { this.directory = directory; @@ -58,11 +61,12 @@ public class Waypoints { } private synchronized void load(Waypoint.Tag tag) { - waypoints.put(tag, new HashSet<>()); + this.waypoints.put(tag, new HashSet<>()); - Path fileName = directory.resolve(tag.name().toLowerCase() + ".mp4"); - if (!Files.exists(fileName)) + Path fileName = this.directory.resolve(tag.name().toLowerCase() + ".mp4"); + if (!Files.exists(fileName)) { return; + } try ( FileInputStream fileIn = new FileInputStream(fileName.toFile()); @@ -81,44 +85,60 @@ public class Waypoints { int x = in.readInt(); int y = in.readInt(); int z = in.readInt(); - waypoints.get(tag).add(new Waypoint(name, tag, new BlockPos(x, y, z), creationTimestamp)); + this.waypoints.get(tag).add(new Waypoint(name, tag, new BlockPos(x, y, z), creationTimestamp)); } } catch (IOException ignored) {} } private synchronized void save(Waypoint.Tag tag) { - Path fileName = directory.resolve(tag.name().toLowerCase() + ".mp4"); + Path fileName = this.directory.resolve(tag.name().toLowerCase() + ".mp4"); try ( FileOutputStream fileOut = new FileOutputStream(fileName.toFile()); BufferedOutputStream bufOut = new BufferedOutputStream(fileOut); DataOutputStream out = new DataOutputStream(bufOut) ) { out.writeLong(WAYPOINT_MAGIC_VALUE); - out.writeLong(waypoints.get(tag).size()); - for (Waypoint waypoint : waypoints.get(tag)) { - out.writeUTF(waypoint.name); - out.writeLong(waypoint.creationTimestamp()); - out.writeInt(waypoint.location.getX()); - out.writeInt(waypoint.location.getY()); - out.writeInt(waypoint.location.getZ()); + out.writeLong(this.waypoints.get(tag).size()); + for (IWaypoint waypoint : this.waypoints.get(tag)) { + out.writeUTF(waypoint.getName()); + out.writeLong(waypoint.getCreationTimestamp()); + out.writeInt(waypoint.getLocation().getX()); + out.writeInt(waypoint.getLocation().getY()); + out.writeInt(waypoint.getLocation().getZ()); } } catch (IOException ex) { ex.printStackTrace(); } } - public Set getByTag(Waypoint.Tag tag) { - return Collections.unmodifiableSet(waypoints.get(tag)); - } - - public Waypoint getMostRecentByTag(Waypoint.Tag tag) { - // Find a waypoint of the given tag which has the greatest timestamp value, indicating the most recent - return this.waypoints.get(tag).stream().min(Comparator.comparingLong(w -> -w.creationTimestamp())).orElse(null); - } - - public void addWaypoint(Waypoint waypoint) { + @Override + public void addWaypoint(IWaypoint waypoint) { // no need to check for duplicate, because it's a Set not a List - waypoints.get(waypoint.tag).add(waypoint); - save(waypoint.tag); + if (waypoints.get(waypoint.getTag()).add(waypoint)) { + save(waypoint.getTag()); + } + } + + @Override + public void removeWaypoint(IWaypoint waypoint) { + if (waypoints.get(waypoint.getTag()).remove(waypoint)) { + save(waypoint.getTag()); + } + } + + @Override + public IWaypoint getMostRecentByTag(IWaypoint.Tag tag) { + // Find a waypoint of the given tag which has the greatest timestamp value, indicating the most recent + return this.waypoints.get(tag).stream().min(Comparator.comparingLong(w -> -w.getCreationTimestamp())).orElse(null); + } + + @Override + public Set getByTag(IWaypoint.Tag tag) { + return Collections.unmodifiableSet(this.waypoints.get(tag)); + } + + @Override + public Set getAllWaypoints() { + return this.waypoints.values().stream().flatMap(Collection::stream).collect(Collectors.toSet()); } } diff --git a/src/main/java/baritone/chunk/WorldData.java b/src/main/java/baritone/cache/WorldData.java similarity index 54% rename from src/main/java/baritone/chunk/WorldData.java rename to src/main/java/baritone/cache/WorldData.java index 3cd7b737..19461d22 100644 --- a/src/main/java/baritone/chunk/WorldData.java +++ b/src/main/java/baritone/cache/WorldData.java @@ -2,20 +2,25 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.chunk; +package baritone.cache; + +import baritone.Baritone; +import baritone.api.cache.ICachedWorld; +import baritone.api.cache.IWaypointCollection; +import baritone.api.cache.IWorldData; import java.nio.file.Path; @@ -24,9 +29,10 @@ import java.nio.file.Path; * * @author leijurv */ -public class WorldData { +public class WorldData implements IWorldData { + public final CachedWorld cache; - public final Waypoints waypoints; + private final Waypoints waypoints; //public final MapData map; public final Path directory; @@ -37,11 +43,19 @@ public class WorldData { } void onClose() { - new Thread() { - public void run() { - System.out.println("Started saving the world in a new thread"); - cache.save(); - } - }.start(); + Baritone.INSTANCE.getExecutor().execute(() -> { + System.out.println("Started saving the world in a new thread"); + cache.save(); + }); + } + + @Override + public ICachedWorld getCachedWorld() { + return this.cache; + } + + @Override + public IWaypointCollection getWaypoints() { + return this.waypoints; } } diff --git a/src/main/java/baritone/chunk/WorldProvider.java b/src/main/java/baritone/cache/WorldProvider.java similarity index 87% rename from src/main/java/baritone/chunk/WorldProvider.java rename to src/main/java/baritone/cache/WorldProvider.java index 709ddff8..2aef54c6 100644 --- a/src/main/java/baritone/chunk/WorldProvider.java +++ b/src/main/java/baritone/cache/WorldProvider.java @@ -2,25 +2,26 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.chunk; +package baritone.cache; import baritone.Baritone; -import baritone.launch.mixins.accessor.IAnvilChunkLoader; -import baritone.launch.mixins.accessor.IChunkProviderServer; +import baritone.api.cache.IWorldProvider; import baritone.utils.Helper; +import baritone.utils.accessor.IAnvilChunkLoader; +import baritone.utils.accessor.IChunkProviderServer; import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.server.integrated.IntegratedServer; import net.minecraft.world.WorldServer; @@ -38,7 +39,7 @@ import java.util.function.Consumer; * @author Brady * @since 8/4/2018 11:06 AM */ -public enum WorldProvider implements Helper { +public enum WorldProvider implements IWorldProvider, Helper { INSTANCE; @@ -46,6 +47,7 @@ public enum WorldProvider implements Helper { private WorldData currentWorld; + @Override public final WorldData getCurrentWorld() { return this.currentWorld; } @@ -69,7 +71,7 @@ public enum WorldProvider implements Helper { directory = new File(directory, "baritone"); readme = directory; - + } else { //remote directory = new File(Baritone.INSTANCE.getDir(), mc.getCurrentServerData().serverIP); @@ -102,7 +104,8 @@ public enum WorldProvider implements Helper { } public final void ifWorldLoaded(Consumer currentWorldConsumer) { - if (this.currentWorld != null) + if (this.currentWorld != null) { currentWorldConsumer.accept(this.currentWorld); + } } } diff --git a/src/main/java/baritone/cache/WorldScanner.java b/src/main/java/baritone/cache/WorldScanner.java new file mode 100644 index 00000000..d6b466ef --- /dev/null +++ b/src/main/java/baritone/cache/WorldScanner.java @@ -0,0 +1,117 @@ +/* + * 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 . + */ + +package baritone.cache; + +import baritone.utils.Helper; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.multiplayer.ChunkProviderClient; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.BlockStateContainer; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; + +import java.util.LinkedList; +import java.util.List; + +public enum WorldScanner implements Helper { + INSTANCE; + + /** + * Scans the world, up to your render distance, for the specified blocks. + * + * @param blocks The blocks to scan for + * @param max The maximum number of blocks to scan before cutoff + * @param yLevelThreshold If a block is found within this Y level, the current result will be + * returned, if the value is negative, then this condition doesn't apply. + * @param maxSearchRadius The maximum chunk search radius + * @return The matching block positions + */ + public List scanLoadedChunks(List blocks, int max, int yLevelThreshold, int maxSearchRadius) { + if (blocks.contains(null)) { + throw new IllegalStateException("Invalid block name should have been caught earlier: " + blocks.toString()); + } + LinkedList res = new LinkedList<>(); + if (blocks.isEmpty()) { + return res; + } + ChunkProviderClient chunkProvider = world().getChunkProvider(); + + int maxSearchRadiusSq = maxSearchRadius * maxSearchRadius; + int playerChunkX = playerFeet().getX() >> 4; + int playerChunkZ = playerFeet().getZ() >> 4; + int playerY = playerFeet().getY(); + + int searchRadiusSq = 0; + boolean foundWithinY = false; + while (true) { + boolean allUnloaded = true; + boolean foundChunks = false; + for (int xoff = -searchRadiusSq; xoff <= searchRadiusSq; xoff++) { + for (int zoff = -searchRadiusSq; zoff <= searchRadiusSq; zoff++) { + int distance = xoff * xoff + zoff * zoff; + if (distance != searchRadiusSq) { + continue; + } + foundChunks = true; + int chunkX = xoff + playerChunkX; + int chunkZ = zoff + playerChunkZ; + Chunk chunk = chunkProvider.getLoadedChunk(chunkX, chunkZ); + if (chunk == null) { + continue; + } + allUnloaded = false; + ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); + chunkX = chunkX << 4; + chunkZ = chunkZ << 4; + for (int y0 = 0; y0 < 16; y0++) { + ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; + if (extendedblockstorage == null) { + continue; + } + int yReal = y0 << 4; + BlockStateContainer bsc = extendedblockstorage.getData(); + // the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x; + // for better cache locality, iterate in that order + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + IBlockState state = bsc.get(x, y, z); + if (blocks.contains(state.getBlock())) { + int yy = yReal | y; + res.add(new BlockPos(chunkX | x, yy, chunkZ | z)); + if (Math.abs(yy - playerY) < yLevelThreshold) { + foundWithinY = true; + } + } + } + } + } + } + } + } + if ((allUnloaded && foundChunks) + || (res.size() >= max + && (searchRadiusSq > maxSearchRadiusSq || (searchRadiusSq > 1 && foundWithinY))) + ) { + return res; + } + searchRadiusSq++; + } + } +} diff --git a/src/main/java/baritone/chunk/ChunkPacker.java b/src/main/java/baritone/chunk/ChunkPacker.java deleted file mode 100644 index fef3c0a5..00000000 --- a/src/main/java/baritone/chunk/ChunkPacker.java +++ /dev/null @@ -1,152 +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 General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.chunk; - -import baritone.pathing.movement.MovementHelper; -import baritone.utils.Helper; -import baritone.utils.pathing.PathingBlockType; -import net.minecraft.block.Block; -import net.minecraft.block.BlockDoublePlant; -import net.minecraft.block.BlockFlower; -import net.minecraft.block.BlockTallGrass; -import net.minecraft.block.state.IBlockState; -import net.minecraft.init.Blocks; -import net.minecraft.util.ResourceLocation; -import net.minecraft.util.math.BlockPos; -import net.minecraft.world.chunk.Chunk; - -import java.util.*; - -/** - * @author Brady - * @since 8/3/2018 1:09 AM - */ -public final class ChunkPacker implements Helper { - - private ChunkPacker() {} - - public static CachedChunk pack(Chunk chunk) { - long start = System.nanoTime() / 1000000L; - - Map> specialBlocks = new HashMap<>(); - BitSet bitSet = new BitSet(CachedChunk.SIZE); - try { - for (int y = 0; y < 256; y++) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - int index = CachedChunk.getPositionIndex(x, y, z); - Block block = chunk.getBlockState(x, y, z).getBlock(); - boolean[] bits = getPathingBlockType(block).getBits(); - bitSet.set(index, bits[0]); - bitSet.set(index + 1, bits[1]); - if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(block)) { - String name = blockToString(block); - specialBlocks.computeIfAbsent(name, b -> new ArrayList<>()).add(new BlockPos(x, y, z)); - } - } - } - } - } catch (Exception e) { - e.printStackTrace(); - } - //System.out.println("Packed special blocks: " + specialBlocks); - long end = System.nanoTime() / 1000000L; - //System.out.println("Chunk packing took " + (end - start) + "ms for " + chunk.x + "," + chunk.z); - String[] blockNames = new String[256]; - for (int z = 0; z < 16; z++) { - outerLoop: - for (int x = 0; x < 16; x++) { - for (int y = 255; y >= 0; y--) { - int index = CachedChunk.getPositionIndex(x, y, z); - if (bitSet.get(index) || bitSet.get(index + 1)) { - String name = blockToString(chunk.getBlockState(x, y, z).getBlock()); - blockNames[z << 4 | x] = name; - continue outerLoop; - } - } - blockNames[z << 4 | x] = "air"; - } - } - CachedChunk cached = new CachedChunk(chunk.x, chunk.z, bitSet, blockNames, specialBlocks); - return cached; - } - - public static String blockToString(Block block) { - ResourceLocation loc = Block.REGISTRY.getNameForObject(block); - String name = loc.getPath(); // normally, only write the part after the minecraft: - if (!loc.getNamespace().equals("minecraft")) { - // Baritone is running on top of forge with mods installed, perhaps? - name = loc.toString(); // include the namespace with the colon - } - return name; - } - - public static Block stringToBlock(String name) { - if (!name.contains(":")) { - name = "minecraft:" + name; - } - return Block.getBlockFromName(name); - } - - private static PathingBlockType getPathingBlockType(Block block) { - if (block.equals(Blocks.WATER)) { - // only water source blocks are plausibly usable, flowing water should be avoid - return PathingBlockType.WATER; - } - - if (MovementHelper.avoidWalkingInto(block) || block.equals(Blocks.FLOWING_WATER)) { - return PathingBlockType.AVOID; - } - // We used to do an AABB check here - // however, this failed in the nether when you were near a nether fortress - // because fences check their adjacent blocks in the world for their fence connection status to determine AABB shape - // this caused a nullpointerexception when we saved chunks on unload, because they were unable to check their neighbors - if (block == Blocks.AIR || block instanceof BlockTallGrass || block instanceof BlockDoublePlant || block instanceof BlockFlower) { - return PathingBlockType.AIR; - } - - return PathingBlockType.SOLID; - } - - static IBlockState pathingTypeToBlock(PathingBlockType type) { - if (type != null) { - switch (type) { - case AIR: - return Blocks.AIR.getDefaultState(); - case WATER: - return Blocks.WATER.getDefaultState(); - case AVOID: - return Blocks.LAVA.getDefaultState(); - case SOLID: - // Dimension solid types - switch (mc.player.dimension) { - case -1: - return Blocks.NETHERRACK.getDefaultState(); - case 0: - return Blocks.STONE.getDefaultState(); - case 1: - return Blocks.END_STONE.getDefaultState(); - } - - // The fallback solid type - return Blocks.STONE.getDefaultState(); - } - } - return null; - } -} diff --git a/src/main/java/baritone/api/event/GameEventHandler.java b/src/main/java/baritone/event/GameEventHandler.java similarity index 56% rename from src/main/java/baritone/api/event/GameEventHandler.java rename to src/main/java/baritone/event/GameEventHandler.java index 45e86885..61756e33 100644 --- a/src/main/java/baritone/api/event/GameEventHandler.java +++ b/src/main/java/baritone/event/GameEventHandler.java @@ -2,54 +2,35 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.api.event; +package baritone.event; import baritone.Baritone; import baritone.api.event.events.*; import baritone.api.event.events.type.EventState; import baritone.api.event.listener.IGameEventListener; -import baritone.chunk.WorldProvider; +import baritone.api.utils.interfaces.Toggleable; +import baritone.cache.WorldProvider; import baritone.utils.BlockStateInterface; import baritone.utils.Helper; import baritone.utils.InputOverrideHandler; -import baritone.utils.interfaces.Toggleable; import net.minecraft.client.settings.KeyBinding; import net.minecraft.world.chunk.Chunk; import org.lwjgl.input.Keyboard; import java.util.ArrayList; -import java.util.List; -import java.util.function.Consumer; /** * @author Brady @@ -57,16 +38,24 @@ import java.util.function.Consumer; */ public final class GameEventHandler implements IGameEventListener, Helper { - private final List listeners = new ArrayList<>(); + private final ArrayList listeners = new ArrayList<>(); @Override public final void onTick(TickEvent event) { - dispatch(listener -> listener.onTick(event)); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onTick(event); + } + }); } @Override public final void onPlayerUpdate(PlayerUpdateEvent event) { - dispatch(listener -> listener.onPlayerUpdate(event)); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onPlayerUpdate(event); + } + }); } @Override @@ -80,17 +69,26 @@ public final class GameEventHandler implements IGameEventListener, Helper { if (inputHandler.isInputForcedDown(keyBinding) && !keyBinding.isKeyDown()) { int keyCode = keyBinding.getKeyCode(); - if (keyCode < Keyboard.KEYBOARD_SIZE) + if (keyCode < Keyboard.KEYBOARD_SIZE) { KeyBinding.onTick(keyCode < 0 ? keyCode + 100 : keyCode); + } } } - dispatch(IGameEventListener::onProcessKeyBinds); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onProcessKeyBinds(); + } + }); } @Override public final void onSendChatMessage(ChatEvent event) { - dispatch(listener -> listener.onSendChatMessage(event)); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onSendChatMessage(event); + } + }); } @Override @@ -111,23 +109,25 @@ public final class GameEventHandler implements IGameEventListener, Helper { if (isPostPopulate || isPreUnload) { WorldProvider.INSTANCE.ifWorldLoaded(world -> { Chunk chunk = mc.world.getChunk(event.getX(), event.getZ()); - world.cache.queueForPacking(chunk); + world.getCachedWorld().queueForPacking(chunk); }); } - dispatch(listener -> listener.onChunkEvent(event)); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onChunkEvent(event); + } + }); } @Override public final void onRenderPass(RenderEvent event) { - /* - WorldProvider.INSTANCE.ifWorldLoaded(world -> world.forEachRegion(region -> region.forEachChunk(chunk -> { - drawChunkLine(region.getX() * 512 + chunk.getX() * 16, region.getZ() * 512 + chunk.getZ() * 16, event.getPartialTicks()); - }))); - */ - - dispatch(listener -> listener.onRenderPass(event)); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onRenderPass(event); + } + }); } @Override @@ -136,62 +136,78 @@ public final class GameEventHandler implements IGameEventListener, Helper { BlockStateInterface.clearCachedChunk(); - switch (event.getState()) { - case PRE: - break; - case POST: - cache.closeWorld(); - if (event.getWorld() != null) - cache.initWorld(event.getWorld()); - break; + if (event.getState() == EventState.POST) { + cache.closeWorld(); + if (event.getWorld() != null) { + cache.initWorld(event.getWorld()); + } } - dispatch(listener -> listener.onWorldEvent(event)); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onWorldEvent(event); + } + }); } @Override public final void onSendPacket(PacketEvent event) { - dispatch(listener -> listener.onSendPacket(event)); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onSendPacket(event); + } + }); } @Override public final void onReceivePacket(PacketEvent event) { - dispatch(listener -> listener.onReceivePacket(event)); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onReceivePacket(event); + } + }); } @Override - public final void onQueryItemSlotForBlocks(ItemSlotEvent event) { - dispatch(listener -> listener.onQueryItemSlotForBlocks(event)); - } - - @Override - public void onPlayerRelativeMove(RelativeMoveEvent event) { - dispatch(listener -> listener.onPlayerRelativeMove(event)); + public void onPlayerRotationMove(RotationMoveEvent event) { + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onPlayerRotationMove(event); + } + }); } @Override public void onBlockInteract(BlockInteractEvent event) { - dispatch(listener -> listener.onBlockInteract(event)); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onBlockInteract(event); + } + }); } @Override public void onPlayerDeath() { - dispatch(IGameEventListener::onPlayerDeath); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onPlayerDeath(); + } + }); } @Override public void onPathEvent(PathEvent event) { - dispatch(listener -> listener.onPathEvent(event)); + listeners.forEach(l -> { + if (canDispatch(l)) { + l.onPathEvent(event); + } + }); } public final void registerEventListener(IGameEventListener listener) { this.listeners.add(listener); } - private void dispatch(Consumer dispatchFunction) { - this.listeners.stream().filter(this::canDispatch).forEach(dispatchFunction); - } - private boolean canDispatch(IGameEventListener listener) { return !(listener instanceof Toggleable) || ((Toggleable) listener).isEnabled(); } diff --git a/src/main/java/baritone/launch/mixins/MixinGameSettings.java b/src/main/java/baritone/launch/mixins/MixinGameSettings.java deleted file mode 100755 index b68cce51..00000000 --- a/src/main/java/baritone/launch/mixins/MixinGameSettings.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.launch.mixins; - -import baritone.Baritone; -import net.minecraft.client.settings.GameSettings; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -/** - * @author Brady - * @since 8/1/2018 12:28 AM - */ -@Mixin(GameSettings.class) -public class MixinGameSettings { - - @Redirect( - method = "isKeyDown", - at = @At( - value = "INVOKE", - target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z", - remap = false - ) - ) - private static boolean isKeyDown(int keyCode) { - return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode); - } -} diff --git a/src/main/java/baritone/launch/mixins/MixinGuiContainer.java b/src/main/java/baritone/launch/mixins/MixinGuiContainer.java deleted file mode 100755 index dd9bf715..00000000 --- a/src/main/java/baritone/launch/mixins/MixinGuiContainer.java +++ /dev/null @@ -1,47 +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 General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.launch.mixins; - -import baritone.Baritone; -import net.minecraft.client.gui.inventory.GuiContainer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -/** - * @author Brady - * @since 7/31/2018 10:47 PM - */ -@Mixin(GuiContainer.class) -public class MixinGuiContainer { - - @Redirect( - method = { - "mouseClicked", - "mouseReleased" - }, - at = @At( - value = "INVOKE", - target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z", - remap = false - ) - ) - private boolean isKeyDown(int keyCode) { - return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode); - } -} diff --git a/src/main/java/baritone/launch/mixins/MixinGuiScreen.java b/src/main/java/baritone/launch/mixins/MixinGuiScreen.java deleted file mode 100755 index 47877058..00000000 --- a/src/main/java/baritone/launch/mixins/MixinGuiScreen.java +++ /dev/null @@ -1,48 +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 General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.launch.mixins; - -import baritone.Baritone; -import net.minecraft.client.gui.GuiScreen; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -/** - * @author Brady - * @since 7/31/2018 10:38 PM - */ -@Mixin(GuiScreen.class) -public class MixinGuiScreen { - - @Redirect( - method = { - "isCtrlKeyDown", - "isShiftKeyDown", - "isAltKeyDown" - }, - at = @At( - value = "INVOKE", - target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z", - remap = false - ) - ) - private static boolean isKeyDown(int keyCode) { - return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode); - } -} diff --git a/src/main/java/baritone/launch/mixins/MixinInventoryPlayer.java b/src/main/java/baritone/launch/mixins/MixinInventoryPlayer.java deleted file mode 100644 index dfaa4b19..00000000 --- a/src/main/java/baritone/launch/mixins/MixinInventoryPlayer.java +++ /dev/null @@ -1,62 +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 General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.launch.mixins; - -import baritone.Baritone; -import baritone.api.event.events.ItemSlotEvent; -import net.minecraft.entity.player.InventoryPlayer; -import org.spongepowered.asm.lib.Opcodes; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.injection.At; -import org.spongepowered.asm.mixin.injection.Redirect; - -/** - * @author Brady - * @since 8/20/2018 - */ -@Mixin(InventoryPlayer.class) -public class MixinInventoryPlayer { - - @Redirect( - method = "getDestroySpeed", - at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I" - ) - ) - private int getDestroySpeed$getCurrentItem(InventoryPlayer inventory) { - ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem); - Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event); - return event.getSlot(); - } - - @Redirect( - method = "canHarvestBlock", - at = @At( - value = "FIELD", - opcode = Opcodes.GETFIELD, - target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I" - ) - ) - private int canHarvestBlock$getCurrentItem(InventoryPlayer inventory) { - ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem); - Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event); - return event.getSlot(); - } -} diff --git a/src/main/java/baritone/pathing/calc/AStarPathFinder.java b/src/main/java/baritone/pathing/calc/AStarPathFinder.java index fa8b5076..933bb7d4 100644 --- a/src/main/java/baritone/pathing/calc/AStarPathFinder.java +++ b/src/main/java/baritone/pathing/calc/AStarPathFinder.java @@ -2,61 +2,53 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.calc; import baritone.Baritone; -import baritone.chunk.CachedWorld; -import baritone.chunk.WorldProvider; +import baritone.api.pathing.goals.Goal; +import baritone.api.pathing.movement.ActionCosts; import baritone.pathing.calc.openset.BinaryHeapOpenSet; -import baritone.pathing.goals.Goal; -import baritone.pathing.movement.ActionCosts; import baritone.pathing.movement.CalculationContext; -import baritone.pathing.movement.Movement; -import baritone.pathing.movement.MovementHelper; -import baritone.pathing.movement.movements.*; +import baritone.pathing.movement.Moves; import baritone.pathing.path.IPath; +import baritone.utils.BlockStateInterface; import baritone.utils.Helper; -import baritone.utils.pathing.BetterBlockPos; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ChunkProviderClient; -import net.minecraft.util.EnumFacing; +import baritone.utils.pathing.MoveResult; import net.minecraft.util.math.BlockPos; -import java.util.Collection; import java.util.HashSet; import java.util.Optional; -import java.util.Random; /** * The actual A* pathfinding * * @author leijurv */ -public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { +public final class AStarPathFinder extends AbstractNodeCostSearch implements Helper { - private final Optional> favoredPositions; + private final Optional> favoredPositions; - public AStarPathFinder(BlockPos start, Goal goal, Optional> favoredPositions) { + public AStarPathFinder(BlockPos start, Goal goal, Optional> favoredPositions) { super(start, goal); - this.favoredPositions = favoredPositions.map(HashSet::new); // <-- okay this is epic + this.favoredPositions = favoredPositions; } @Override protected Optional calculate0(long timeout) { - startNode = getNodeAtPosition(start); + startNode = getNodeAtPosition(start.x, start.y, start.z); startNode.cost = 0; startNode.combinedCost = startNode.estimatedCostToGoal; BinaryHeapOpenSet openSet = new BinaryHeapOpenSet(); @@ -65,17 +57,16 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i]) double[] bestHeuristicSoFar = new double[COEFFICIENTS.length]; for (int i = 0; i < bestHeuristicSoFar.length; i++) { - bestHeuristicSoFar[i] = Double.MAX_VALUE; + bestHeuristicSoFar[i] = startNode.estimatedCostToGoal; + bestSoFar[i] = startNode; } CalculationContext calcContext = new CalculationContext(); - HashSet favored = favoredPositions.orElse(null); - currentlyRunning = this; - CachedWorld cachedWorld = Optional.ofNullable(WorldProvider.INSTANCE.getCurrentWorld()).map(w -> w.cache).orElse(null); - ChunkProviderClient chunkProvider = Minecraft.getMinecraft().world.getChunkProvider(); + HashSet favored = favoredPositions.orElse(null); + BlockStateInterface.clearCachedChunk(); long startTime = System.nanoTime() / 1000000L; boolean slowPath = Baritone.settings().slowPath.get(); if (slowPath) { - displayChatMessageRaw("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.get() + "ms instead of " + timeout + "ms"); + logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.get() + "ms instead of " + timeout + "ms"); } long timeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.get() : timeout); //long lastPrintout = 0; @@ -86,6 +77,7 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior double favorCoeff = Baritone.settings().backtrackCostFavoringCoefficient.get(); boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get(); + loopBegin(); while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.nanoTime() / 1000000L - timeoutTime < 0 && !cancelRequested) { if (slowPath) { try { @@ -96,50 +88,45 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { PathNode currentNode = openSet.removeLowest(); currentNode.isOpen = false; mostRecentConsidered = currentNode; - BetterBlockPos currentNodePos = currentNode.pos; numNodes++; - if (goal.isInGoal(currentNodePos)) { - currentlyRunning = null; - displayChatMessageRaw("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, " + numMovementsConsidered + " movements considered"); - return Optional.of(new Path(startNode, currentNode, numNodes)); + if (goal.isInGoal(currentNode.x, currentNode.y, currentNode.z)) { + logDebug("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, " + numMovementsConsidered + " movements considered"); + return Optional.of(new Path(startNode, currentNode, numNodes, goal)); } - Movement[] possibleMovements = getConnectedPositions(currentNodePos, calcContext);//movement that we could take that start at currentNodePos, in random order - shuffle(possibleMovements); - for (Movement movementToGetToNeighbor : possibleMovements) { - if (movementToGetToNeighbor == null) { - continue; - } - BetterBlockPos dest = (BetterBlockPos) movementToGetToNeighbor.getDest(); - int chunkX = currentNodePos.x >> 4; - int chunkZ = currentNodePos.z >> 4; - if (dest.x >> 4 != chunkX || dest.z >> 4 != chunkZ) { + for (Moves moves : Moves.values()) { + int newX = currentNode.x + moves.xOffset; + int newZ = currentNode.z + moves.zOffset; + if (newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) { // only need to check if the destination is a loaded chunk if it's in a different chunk than the start of the movement - if (chunkProvider.getLoadedChunk(chunkX, chunkZ) == null) { - // see issue #106 - if (cachedWorld == null || !cachedWorld.isCached(dest)) { + if (!BlockStateInterface.isLoaded(newX, newZ)) { + if (!moves.dynamicXZ) { // only increment the counter if the movement would have gone out of bounds guaranteed numEmptyChunk++; - continue; } + continue; } } - // TODO cache cost - double actionCost = movementToGetToNeighbor.getCost(calcContext); + MoveResult res = moves.apply(calcContext, currentNode.x, currentNode.y, currentNode.z); numMovementsConsidered++; + double actionCost = res.cost; if (actionCost >= ActionCosts.COST_INF) { continue; } - if (actionCost <= 0) { - throw new IllegalStateException(movementToGetToNeighbor.getClass() + " " + movementToGetToNeighbor + " calculated implausible cost " + actionCost); + // check destination after verifying it's not COST_INF -- some movements return a static IMPOSSIBLE object with COST_INF and destination being 0,0,0 to avoid allocating a new result for every failed calculation + if (!moves.dynamicXZ && (res.destX != newX || res.destZ != newZ)) { + throw new IllegalStateException(moves + " " + res.destX + " " + newX + " " + res.destZ + " " + newZ); } - if (favoring && favored.contains(dest)) { + if (actionCost <= 0) { + throw new IllegalStateException(moves + " calculated implausible cost " + actionCost); + } + if (favoring && favored.contains(posHash(res.destX, res.destY, res.destZ))) { // see issue #18 actionCost *= favorCoeff; } - PathNode neighbor = getNodeAtPosition(dest); + PathNode neighbor = getNodeAtPosition(res.destX, res.destY, res.destZ); double tentativeCost = currentNode.cost + actionCost; if (tentativeCost < neighbor.cost) { if (tentativeCost < 0) { - throw new IllegalStateException(movementToGetToNeighbor.getClass() + " " + movementToGetToNeighbor + " overflowed into negative " + actionCost + " " + neighbor.cost + " " + tentativeCost); + throw new IllegalStateException(moves + " overflowed into negative " + actionCost + " " + neighbor.cost + " " + tentativeCost); } double improvementBy = neighbor.cost - tentativeCost; // there are floating point errors caused by random combinations of traverse and diagonal over a flat area @@ -150,14 +137,13 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { continue; } neighbor.previous = currentNode; - neighbor.previousMovement = movementToGetToNeighbor; neighbor.cost = tentativeCost; neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal; if (neighbor.isOpen) { openSet.update(neighbor); } else { - openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there neighbor.isOpen = true; + openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there } for (int i = 0; i < bestSoFar.length; i++) { double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i]; @@ -173,11 +159,11 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { } } if (cancelRequested) { - currentlyRunning = null; return Optional.empty(); } System.out.println(numMovementsConsidered + " movements considered"); System.out.println("Open set size: " + openSet.size()); + System.out.println("PathNode map size: " + mapSize()); System.out.println((int) (numNodes * 1.0 / ((System.nanoTime() / 1000000L - startTime) / 1000F)) + " nodes per second"); double bestDist = 0; for (int i = 0; i < bestSoFar.length; i++) { @@ -189,63 +175,18 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { bestDist = dist; } if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared - displayChatMessageRaw("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i] + ", " + numMovementsConsidered + " movements considered"); + logDebug("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i] + ", " + numMovementsConsidered + " movements considered"); if (COEFFICIENTS[i] >= 3) { System.out.println("Warning: cost coefficient is greater than three! Probably means that"); System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)"); System.out.println("But I'm going to do it anyway, because yolo"); } System.out.println("Path goes for " + Math.sqrt(dist) + " blocks"); - currentlyRunning = null; - return Optional.of(new Path(startNode, bestSoFar[i], numNodes)); + return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal)); } } - displayChatMessageRaw("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + bestDist + " blocks"); - displayChatMessageRaw("No path found =("); - currentlyRunning = null; + logDebug("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks"); + logDebug("No path found =("); return Optional.empty(); } - - - public static Movement[] getConnectedPositions(BetterBlockPos pos, CalculationContext calcContext) { - int x = pos.getX(); - int y = pos.getY(); - int z = pos.getZ(); - BetterBlockPos east = new BetterBlockPos(x + 1, y, z); - BetterBlockPos west = new BetterBlockPos(x - 1, y, z); - BetterBlockPos south = new BetterBlockPos(x, y, z + 1); - BetterBlockPos north = new BetterBlockPos(x, y, z - 1); - return new Movement[]{ - new MovementTraverse(pos, east), - new MovementTraverse(pos, west), - new MovementTraverse(pos, north), - new MovementTraverse(pos, south), - new MovementAscend(pos, new BetterBlockPos(x + 1, y + 1, z)), - new MovementAscend(pos, new BetterBlockPos(x - 1, y + 1, z)), - new MovementAscend(pos, new BetterBlockPos(x, y + 1, z + 1)), - new MovementAscend(pos, new BetterBlockPos(x, y + 1, z - 1)), - MovementHelper.generateMovementFallOrDescend(pos, east, calcContext), - MovementHelper.generateMovementFallOrDescend(pos, west, calcContext), - MovementHelper.generateMovementFallOrDescend(pos, north, calcContext), - MovementHelper.generateMovementFallOrDescend(pos, south, calcContext), - new MovementDownward(pos, new BetterBlockPos(x, y - 1, z)), - new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.WEST), - new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.EAST), - new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.WEST), - new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.EAST), - new MovementPillar(pos, new BetterBlockPos(x, y + 1, z)) - }; - } - - private final Random random = new Random(); - - private void shuffle(T[] list) { - int len = list.length; - for (int i = 0; i < len; i++) { - int j = random.nextInt(len); - T t = list[j]; - list[j] = list[i]; - list[i] = t; - } - } } diff --git a/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java b/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java index 5804cb1a..21f6d848 100644 --- a/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java +++ b/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java @@ -2,23 +2,22 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.calc; -import baritone.behavior.impl.PathingBehavior; -import baritone.pathing.goals.Goal; +import baritone.api.pathing.goals.Goal; import baritone.pathing.path.IPath; import baritone.utils.pathing.BetterBlockPos; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; @@ -36,13 +35,16 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { /** * The currently running search task */ - protected static AbstractNodeCostSearch currentlyRunning = null; + private static AbstractNodeCostSearch currentlyRunning = null; protected final BetterBlockPos start; protected final Goal goal; - private final Long2ObjectOpenHashMap map; // see issue #107 + /** + * @see Issue #107 + */ + private final Long2ObjectOpenHashMap map; protected PathNode startNode; @@ -83,19 +85,24 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { this.cancelRequested = false; try { Optional path = calculate0(timeout); + path.ifPresent(IPath::postprocess); isFinished = true; return path; - } catch (Exception e) { + } finally { + // this is run regardless of what exception may or may not be raised by calculate0 currentlyRunning = null; isFinished = true; - if (e instanceof RuntimeException) { - throw (RuntimeException) e; - } else { - throw new RuntimeException(e); - } } } + /** + * Don't set currentlyRunning to this until everything is all ready to go, and we're about to enter the main loop. + * For example, bestSoFar is null so bestPathSoFar (which gets bestSoFar[0]) could NPE if we set currentlyRunning before calculate0 + */ + protected void loopBegin() { + currentlyRunning = this; + } + protected abstract Optional calculate0(long timeout); /** @@ -107,9 +114,9 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { * @return The distance, squared */ protected double getDistFromStartSq(PathNode n) { - int xDiff = n.pos.getX() - start.getX(); - int yDiff = n.pos.getY() - start.getY(); - int zDiff = n.pos.getZ() - start.getZ(); + int xDiff = n.x - start.x; + int yDiff = n.y - start.y; + int zDiff = n.z - start.z; return xDiff * xDiff + yDiff * yDiff + zDiff * zDiff; } @@ -118,28 +125,66 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { * for the node mapped to the specified pos. If no node is found, * a new node is created. * - * @param pos The pos to lookup * @return The associated node + * @see Issue #107 */ - protected PathNode getNodeAtPosition(BetterBlockPos pos) { - // see issue #107 - long hashCode = pos.hashCode; + protected PathNode getNodeAtPosition(int x, int y, int z) { + long hashCode = posHash(x, y, z); PathNode node = map.get(hashCode); if (node == null) { - node = new PathNode(pos, goal); + node = new PathNode(x, y, z, goal); map.put(hashCode, node); } return node; } + public static long posHash(int x, int y, int z) { + /* + * This is the hashcode implementation of Vec3i, the superclass of BlockPos + * + * public int hashCode() { + * return (this.getY() + this.getZ() * 31) * 31 + this.getX(); + * } + * + * That is terrible and has tons of collisions and makes the HashMap terribly inefficient. + * + * That's why we grab out the X, Y, Z and calculate our own hashcode + */ + long hash = 3241; + hash = 3457689L * hash + x; + hash = 8734625L * hash + y; + hash = 2873465L * hash + z; + return hash; + } + public static void forceCancel() { - PathingBehavior.INSTANCE.cancel(); currentlyRunning = null; } + public PathNode mostRecentNodeConsidered() { + return mostRecentConsidered; + } + + public PathNode bestNodeSoFar() { + return bestSoFar[0]; + } + + public PathNode startNode() { + return startNode; + } + @Override public Optional pathToMostRecentNodeConsidered() { - return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0)); + try { + return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal)); + } catch (IllegalStateException ex) { + System.out.println("Unable to construct path to render"); + return Optional.empty(); + } + } + + protected int mapSize() { + return map.size(); } @Override @@ -152,7 +197,12 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { continue; } if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared - return Optional.of(new Path(startNode, bestSoFar[i], 0)); + try { + return Optional.of(new Path(startNode, bestSoFar[i], 0, goal)); + } catch (IllegalStateException ex) { + System.out.println("Unable to construct path to render"); + return Optional.empty(); + } } } // instead of returning bestSoFar[0], be less misleading diff --git a/src/main/java/baritone/pathing/calc/IPathFinder.java b/src/main/java/baritone/pathing/calc/IPathFinder.java index dceee65d..6ed2b3a7 100644 --- a/src/main/java/baritone/pathing/calc/IPathFinder.java +++ b/src/main/java/baritone/pathing/calc/IPathFinder.java @@ -2,22 +2,22 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.calc; -import baritone.pathing.goals.Goal; +import baritone.api.pathing.goals.Goal; import baritone.pathing.path.IPath; import net.minecraft.util.math.BlockPos; diff --git a/src/main/java/baritone/pathing/calc/Path.java b/src/main/java/baritone/pathing/calc/Path.java index 96c8950e..7f8cf085 100644 --- a/src/main/java/baritone/pathing/calc/Path.java +++ b/src/main/java/baritone/pathing/calc/Path.java @@ -2,22 +2,24 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.calc; +import baritone.api.pathing.goals.Goal; import baritone.pathing.movement.Movement; +import baritone.pathing.movement.Moves; import baritone.pathing.path.IPath; import baritone.utils.pathing.BetterBlockPos; import net.minecraft.util.math.BlockPos; @@ -37,31 +39,40 @@ class Path implements IPath { /** * The start position of this path */ - final BetterBlockPos start; + private final BetterBlockPos start; /** * The end position of this path */ - final BetterBlockPos end; + private final BetterBlockPos end; /** * The blocks on the path. Guaranteed that path.get(0) equals start and * path.get(path.size()-1) equals end */ - final List path; + private final List path; - final List movements; + private final List movements; + + private final Goal goal; private final int numNodes; - Path(PathNode start, PathNode end, int numNodes) { - this.start = start.pos; - this.end = end.pos; + private volatile boolean verified; + + Path(PathNode start, PathNode end, int numNodes, Goal goal) { + this.start = new BetterBlockPos(start.x, start.y, start.z); + this.end = new BetterBlockPos(end.x, end.y, end.z); this.numNodes = numNodes; this.path = new ArrayList<>(); this.movements = new ArrayList<>(); + this.goal = goal; assemblePath(start, end); - sanityCheck(); + } + + @Override + public Goal getGoal() { + return goal; } /** @@ -78,11 +89,11 @@ class Path implements IPath { LinkedList tempPath = new LinkedList<>(); // Repeatedly inserting to the beginning of an arraylist is O(n^2) LinkedList tempMovements = new LinkedList<>(); // Instead, do it into a linked list, then convert at the end while (!current.equals(start)) { - tempPath.addFirst(current.pos); - tempMovements.addFirst(current.previousMovement); + tempPath.addFirst(new BetterBlockPos(current.x, current.y, current.z)); + tempMovements.addFirst(runBackwards(current.previous, current)); current = current.previous; } - tempPath.addFirst(start.pos); + tempPath.addFirst(this.start); // Can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is // inserting into a LinkedList keeps track of length, then when we addall (which calls .toArray) it's able // to performantly do that conversion since it knows the length. @@ -90,6 +101,19 @@ class Path implements IPath { movements.addAll(tempMovements); } + private static Movement runBackwards(PathNode src0, PathNode dest0) { // TODO this is horrifying + BetterBlockPos src = new BetterBlockPos(src0.x, src0.y, src0.z); + BetterBlockPos dest = new BetterBlockPos(dest0.x, dest0.y, dest0.z); + for (Moves moves : Moves.values()) { + Movement move = moves.apply0(src); + if (move.getDest().equals(dest)) { + return move; + } + } + // leave this as IllegalStateException; it's caught in AbstractNodeCostSearch + throw new IllegalStateException("Movement became impossible during calculation " + src + " " + dest + " " + dest.subtract(src)); + } + /** * Performs a series of checks to ensure that the assembly of the path went as expected. */ @@ -116,8 +140,22 @@ class Path implements IPath { } } + @Override + public void postprocess() { + if (verified) { + throw new IllegalStateException(); + } + verified = true; + // more post processing here + movements.forEach(Movement::checkLoadedChunk); + sanityCheck(); + } + @Override public List movements() { + if (!verified) { + throw new IllegalStateException(); + } return Collections.unmodifiableList(movements); } diff --git a/src/main/java/baritone/pathing/calc/PathNode.java b/src/main/java/baritone/pathing/calc/PathNode.java index 314c996b..8e42d564 100644 --- a/src/main/java/baritone/pathing/calc/PathNode.java +++ b/src/main/java/baritone/pathing/calc/PathNode.java @@ -2,41 +2,37 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.calc; -import baritone.pathing.goals.Goal; -import baritone.pathing.movement.Movement; -import baritone.utils.pathing.BetterBlockPos; +import baritone.api.pathing.goals.Goal; +import baritone.api.pathing.movement.ActionCosts; /** * A node in the path, containing the cost and steps to get to it. * * @author leijurv */ -public class PathNode { +public final class PathNode { /** * The position of this node */ - final BetterBlockPos pos; - - /** - * The goal it's going towards - */ - final Goal goal; + final int x; + final int y; + final int z; /** * Cached, should always be equal to goal.heuristic(pos) @@ -61,12 +57,6 @@ public class PathNode { */ PathNode previous; - /** - * In the graph search, what previous movement (edge) was taken to get to here - * Mutable and changed by PathFinder - */ - Movement previousMovement; - /** * Is this a member of the open set in A*? (only used during pathfinding) * Instead of doing a costly member check in the open set, cache membership in each node individually too. @@ -78,14 +68,14 @@ public class PathNode { */ public int heapPosition; - public PathNode(BetterBlockPos pos, Goal goal) { - this.pos = pos; + public PathNode(int x, int y, int z, Goal goal) { this.previous = null; - this.cost = Short.MAX_VALUE; - this.goal = goal; - this.estimatedCostToGoal = goal.heuristic(pos); - this.previousMovement = null; + this.cost = ActionCosts.COST_INF; + this.estimatedCostToGoal = goal.heuristic(x, y, z); this.isOpen = false; + this.x = x; + this.y = y; + this.z = z; } /** @@ -95,7 +85,7 @@ public class PathNode { */ @Override public int hashCode() { - return pos.hashCode() * 7 + 3; + return (int) AbstractNodeCostSearch.posHash(x, y, z); } @Override @@ -103,11 +93,13 @@ public class PathNode { // GOTTA GO FAST // ALL THESE CHECKS ARE FOR PEOPLE WHO WANT SLOW CODE // SKRT SKRT - //if (obj == null || !(obj instanceof PathNode)) + //if (obj == null || !(obj instanceof PathNode)) { // return false; + //} - //final PathNode other = (PathNode) obj; + final PathNode other = (PathNode) obj; //return Objects.equals(this.pos, other.pos) && Objects.equals(this.goal, other.goal); - return this.pos.equals(((PathNode) obj).pos); + + return x == other.x && y == other.y && z == other.z; } } diff --git a/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java b/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java index 47d370c6..6758a30a 100644 --- a/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java +++ b/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/java/baritone/pathing/calc/openset/IOpenSet.java b/src/main/java/baritone/pathing/calc/openset/IOpenSet.java index e43664c8..4d362139 100644 --- a/src/main/java/baritone/pathing/calc/openset/IOpenSet.java +++ b/src/main/java/baritone/pathing/calc/openset/IOpenSet.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/main/java/baritone/pathing/calc/openset/LinkedListOpenSet.java b/src/main/java/baritone/pathing/calc/openset/LinkedListOpenSet.java index 8ff5a674..6de8290d 100644 --- a/src/main/java/baritone/pathing/calc/openset/LinkedListOpenSet.java +++ b/src/main/java/baritone/pathing/calc/openset/LinkedListOpenSet.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -83,7 +83,7 @@ class LinkedListOpenSet implements IOpenSet { } public static class Node { //wrapper with next - Node nextOpen; - PathNode val; + private Node nextOpen; + private PathNode val; } } diff --git a/src/main/java/baritone/pathing/goals/GoalGetToBlock.java b/src/main/java/baritone/pathing/goals/GoalGetToBlock.java deleted file mode 100644 index 9c847918..00000000 --- a/src/main/java/baritone/pathing/goals/GoalGetToBlock.java +++ /dev/null @@ -1,48 +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 General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.pathing.goals; - -import net.minecraft.util.EnumFacing; -import net.minecraft.util.math.BlockPos; - -/** - * Don't get into the block, but get directly adjacent to it. Useful for chests. - * - * @author avecowa - */ -public class GoalGetToBlock extends GoalComposite { - - private final BlockPos pos; - - public GoalGetToBlock(BlockPos pos) { - super(adjacentBlocks(pos)); - this.pos = pos; - } - - private static BlockPos[] adjacentBlocks(BlockPos pos) { - BlockPos[] sides = new BlockPos[6]; - for (int i = 0; i < 6; i++) { - sides[i] = pos.offset(EnumFacing.values()[i]); - } - return sides; - } - - public BlockPos getGoalPos() { - return pos; - } -} diff --git a/src/main/java/baritone/pathing/movement/ActionCosts.java b/src/main/java/baritone/pathing/movement/ActionCosts.java deleted file mode 100644 index 9baff727..00000000 --- a/src/main/java/baritone/pathing/movement/ActionCosts.java +++ /dev/null @@ -1,47 +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 General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -package baritone.pathing.movement; - -public interface ActionCosts extends ActionCostsButOnlyTheOnesThatMakeMickeyDieInside { - - /** - * These costs are measured roughly in ticks btw - */ - double WALK_ONE_BLOCK_COST = 20 / 4.317; // 4.633 - double WALK_ONE_IN_WATER_COST = 20 / 2.2; - double WALK_ONE_OVER_SOUL_SAND_COST = WALK_ONE_BLOCK_COST * 0.5; // 0.4 in BlockSoulSand but effectively about half - double SPRINT_ONE_OVER_SOUL_SAND_COST = WALK_ONE_OVER_SOUL_SAND_COST / 0.75; - double LADDER_UP_ONE_COST = 20 / 2.35; - double LADDER_DOWN_ONE_COST = 20 / 3.0; - double SNEAK_ONE_BLOCK_COST = 20 / 1.3; - double SPRINT_ONE_BLOCK_COST = 20 / 5.612; // 3.564 - /** - * To walk off an edge you need to walk 0.5 to the edge then 0.3 to start falling off - */ - double WALK_OFF_BLOCK_COST = WALK_ONE_BLOCK_COST * 0.8; - /** - * To walk the rest of the way to be centered on the new block - */ - double CENTER_AFTER_FALL_COST = WALK_ONE_BLOCK_COST - WALK_OFF_BLOCK_COST; - - /** - * don't make this Double.MAX_VALUE because it's added to other things, maybe other COST_INFs, - * and that would make it overflow to negative - */ - double COST_INF = 1000000; -} diff --git a/src/main/java/baritone/pathing/movement/CalculationContext.java b/src/main/java/baritone/pathing/movement/CalculationContext.java index 2aca1f82..3149cfe9 100644 --- a/src/main/java/baritone/pathing/movement/CalculationContext.java +++ b/src/main/java/baritone/pathing/movement/CalculationContext.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -46,7 +46,6 @@ public class CalculationContext implements Helper { } public CalculationContext(ToolSet toolSet) { - player().setSprinting(true); this.toolSet = toolSet; this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(false); this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) && !world().provider.isNether(); diff --git a/src/main/java/baritone/pathing/movement/Movement.java b/src/main/java/baritone/pathing/movement/Movement.java index 715bfd68..21341fa4 100644 --- a/src/main/java/baritone/pathing/movement/Movement.java +++ b/src/main/java/baritone/pathing/movement/Movement.java @@ -2,38 +2,35 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.movement; import baritone.Baritone; -import baritone.behavior.impl.LookBehavior; -import baritone.behavior.impl.LookBehaviorUtils; +import baritone.api.utils.Rotation; +import baritone.behavior.LookBehavior; +import baritone.behavior.LookBehaviorUtils; import baritone.pathing.movement.MovementState.MovementStatus; -import baritone.pathing.movement.movements.MovementDownward; -import baritone.pathing.movement.movements.MovementPillar; -import baritone.pathing.movement.movements.MovementTraverse; import baritone.utils.*; -import net.minecraft.block.Block; -import net.minecraft.block.BlockLadder; -import net.minecraft.block.BlockVine; +import baritone.utils.pathing.BetterBlockPos; +import net.minecraft.block.BlockLiquid; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; +import net.minecraft.world.chunk.EmptyChunk; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -45,54 +42,48 @@ public abstract class Movement implements Helper, MovementHelper { private MovementState currentState = new MovementState().setStatus(MovementStatus.PREPPING); - protected final BlockPos src; + protected final BetterBlockPos src; - protected final BlockPos dest; + protected final BetterBlockPos dest; /** * The positions that need to be broken before this movement can ensue */ - protected final BlockPos[] positionsToBreak; + protected final BetterBlockPos[] positionsToBreak; /** * The position where we need to place a block before this movement can ensue */ - protected final BlockPos positionToPlace; + protected final BetterBlockPos positionToPlace; private boolean didBreakLastTick; private Double cost; - protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak, BlockPos toPlace) { + public List toBreakCached = null; + public List toPlaceCached = null; + public List toWalkIntoCached = null; + + private Boolean calculatedWhileLoaded; + + protected Movement(BetterBlockPos src, BetterBlockPos dest, BetterBlockPos[] toBreak, BetterBlockPos toPlace) { this.src = src; this.dest = dest; this.positionsToBreak = toBreak; this.positionToPlace = toPlace; } - protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak) { + protected Movement(BetterBlockPos src, BetterBlockPos dest, BetterBlockPos[] toBreak) { this(src, dest, toBreak, null); } public double getCost(CalculationContext context) { if (cost == null) { - if (context == null) - context = new CalculationContext(); - cost = calculateCost0(context); + cost = calculateCost(context != null ? context : new CalculationContext()); } return cost; } - private double calculateCost0(CalculationContext context) { - if (!(this instanceof MovementPillar) && !(this instanceof MovementTraverse) && !(this instanceof MovementDownward)) { - Block fromDown = BlockStateInterface.get(src.down()).getBlock(); - if (fromDown instanceof BlockLadder || fromDown instanceof BlockVine) { - return COST_INF; - } - } - return calculateCost(context); - } - protected abstract double calculateCost(CalculationContext context); public double recalculateCost() { @@ -100,8 +91,12 @@ public abstract class Movement implements Helper, MovementHelper { return getCost(null); } + protected void override(double cost) { + this.cost = cost; + } + public double calculateCostWithoutCaching() { - return calculateCost0(new CalculationContext()); + return calculateCost(new CalculationContext()); } /** @@ -111,6 +106,7 @@ public abstract class Movement implements Helper, MovementHelper { * @return Status */ public MovementStatus update() { + player().capabilities.allowFlying = false; MovementState latestState = updateState(currentState); if (BlockStateInterface.isLiquid(playerFeet())) { latestState.setInput(Input.JUMP, true); @@ -128,29 +124,32 @@ public abstract class Movement implements Helper, MovementHelper { this.didBreakLastTick = false; latestState.getInputStates().forEach((input, forced) -> { - RayTraceResult trace = mc.objectMouseOver; - boolean isBlockTrace = trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK; - boolean isLeftClick = forced && input == Input.CLICK_LEFT; + if (Baritone.settings().leftClickWorkaround.get()) { + RayTraceResult trace = mc.objectMouseOver; + boolean isBlockTrace = trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK; + boolean isLeftClick = forced && input == Input.CLICK_LEFT; - // If we're forcing left click, we're in a gui screen, and we're looking - // at a block, break the block without a direct game input manipulation. - if (mc.currentScreen != null && isLeftClick && isBlockTrace) { - BlockBreakHelper.tryBreakBlock(trace.getBlockPos(), trace.sideHit); - this.didBreakLastTick = true; - return; + // If we're forcing left click, we're in a gui screen, and we're looking + // at a block, break the block without a direct game input manipulation. + if (mc.currentScreen != null && isLeftClick && isBlockTrace) { + BlockBreakHelper.tryBreakBlock(trace.getBlockPos(), trace.sideHit); + this.didBreakLastTick = true; + return; + } } - Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced); }); latestState.getInputStates().replaceAll((input, forced) -> false); - if (!this.didBreakLastTick) + if (!this.didBreakLastTick) { BlockBreakHelper.stopBreakingBlock(); + } currentState = latestState; - if (isFinished()) + if (isFinished()) { onFinish(latestState); + } return currentState.getStatus(); } @@ -160,12 +159,12 @@ public abstract class Movement implements Helper, MovementHelper { return true; } boolean somethingInTheWay = false; - for (BlockPos blockPos : positionsToBreak) { - if (!MovementHelper.canWalkThrough(blockPos)) { + for (BetterBlockPos blockPos : positionsToBreak) { + if (!MovementHelper.canWalkThrough(blockPos) && !(BlockStateInterface.getBlock(blockPos) instanceof BlockLiquid)) { // can't break liquid, so don't try somethingInTheWay = true; Optional reachable = LookBehaviorUtils.reachable(blockPos); if (reachable.isPresent()) { - player().inventory.currentItem = new ToolSet().getBestSlot(BlockStateInterface.get(blockPos)); + MovementHelper.switchToBestToolFor(BlockStateInterface.get(blockPos)); state.setTarget(new MovementState.MovementTarget(reachable.get(), true)).setInput(Input.CLICK_LEFT, true); return false; } @@ -194,11 +193,11 @@ public abstract class Movement implements Helper, MovementHelper { && currentState.getStatus() != MovementStatus.WAITING); } - public BlockPos getSrc() { + public BetterBlockPos getSrc() { return src; } - public BlockPos getDest() { + public BetterBlockPos getDest() { return dest; } @@ -220,60 +219,6 @@ public abstract class Movement implements Helper, MovementHelper { currentState = new MovementState().setStatus(MovementStatus.PREPPING); } - public double getTotalHardnessOfBlocksToBreak(CalculationContext ctx) { - if (positionsToBreak.length == 0) { - return 0; - } - if (positionsToBreak.length == 1) { - return MovementHelper.getMiningDurationTicks(ctx, positionsToBreak[0], true); - } - int firstColumnX = positionsToBreak[0].getX(); - int firstColumnZ = positionsToBreak[0].getZ(); - int firstColumnMaxY = positionsToBreak[0].getY(); - int firstColumnMaximalIndex = 0; - boolean hasSecondColumn = false; - int secondColumnX = -1; - int secondColumnZ = -1; - int secondColumnMaxY = -1; - int secondColumnMaximalIndex = -1; - for (int i = 0; i < positionsToBreak.length; i++) { - BlockPos pos = positionsToBreak[i]; - if (pos.getX() == firstColumnX && pos.getZ() == firstColumnZ) { - if (pos.getY() > firstColumnMaxY) { - firstColumnMaxY = pos.getY(); - firstColumnMaximalIndex = i; - } - } else { - if (!hasSecondColumn || (pos.getX() == secondColumnX && pos.getZ() == secondColumnZ)) { - if (hasSecondColumn) { - if (pos.getY() > secondColumnMaxY) { - secondColumnMaxY = pos.getY(); - secondColumnMaximalIndex = i; - } - } else { - hasSecondColumn = true; - secondColumnX = pos.getX(); - secondColumnZ = pos.getZ(); - secondColumnMaxY = pos.getY(); - secondColumnMaximalIndex = i; - } - } else { - throw new IllegalStateException("I literally have no idea " + Arrays.asList(positionsToBreak)); - } - } - } - - double sum = 0; - for (int i = 0; i < positionsToBreak.length; i++) { - sum += MovementHelper.getMiningDurationTicks(ctx, positionsToBreak[i], firstColumnMaximalIndex == i || secondColumnMaximalIndex == i); - if (sum >= COST_INF) { - break; - } - } - return sum; - } - - /** * Calculate latest movement state. * Gets called once a tick. @@ -286,6 +231,11 @@ public abstract class Movement implements Helper, MovementHelper { } else if (state.getStatus() == MovementStatus.PREPPING) { state.setStatus(MovementStatus.WAITING); } + + if (state.getStatus() == MovementStatus.WAITING) { + state.setStatus(MovementStatus.RUNNING); + } + return state; } @@ -293,16 +243,20 @@ public abstract class Movement implements Helper, MovementHelper { return getDest().subtract(getSrc()); } - public List toBreakCached = null; - public List toPlaceCached = null; - public List toWalkIntoCached = null; + public void checkLoadedChunk() { + calculatedWhileLoaded = !(world().getChunk(getDest()) instanceof EmptyChunk); + } + + public boolean calculatedWhileLoaded() { + return calculatedWhileLoaded; + } public List toBreak() { if (toBreakCached != null) { return toBreakCached; } List result = new ArrayList<>(); - for (BlockPos positionToBreak : positionsToBreak) { + for (BetterBlockPos positionToBreak : positionsToBreak) { if (!MovementHelper.canWalkThrough(positionToBreak)) { result.add(positionToBreak); } diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 909c21a7..d614e544 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -2,27 +2,28 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.movement; import baritone.Baritone; -import baritone.behavior.impl.LookBehaviorUtils; +import baritone.api.pathing.movement.ActionCosts; +import baritone.api.utils.Rotation; +import baritone.behavior.LookBehaviorUtils; import baritone.pathing.movement.MovementState.MovementTarget; -import baritone.pathing.movement.movements.MovementDescend; -import baritone.pathing.movement.movements.MovementFall; import baritone.utils.*; +import baritone.utils.pathing.BetterBlockPos; import net.minecraft.block.*; import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.state.IBlockState; @@ -46,18 +47,20 @@ import java.util.Optional; */ public interface MovementHelper extends ActionCosts, Helper { - static boolean avoidBreaking(BlockPos pos, IBlockState state) { + static boolean avoidBreaking(BetterBlockPos pos, IBlockState state) { + return avoidBreaking(pos.x, pos.y, pos.z, state); + } + + static boolean avoidBreaking(int x, int y, int z, IBlockState state) { Block b = state.getBlock(); - Block below = BlockStateInterface.get(new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ())).getBlock(); - return Blocks.ICE.equals(b) // ice becomes water, and water can mess up the path + return b == Blocks.ICE // ice becomes water, and water can mess up the path || b instanceof BlockSilverfish // obvious reasons - || BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY() + 1, pos.getZ()))//don't break anything touching liquid on any side - || BlockStateInterface.isLiquid(new BlockPos(pos.getX() + 1, pos.getY(), pos.getZ())) - || BlockStateInterface.isLiquid(new BlockPos(pos.getX() - 1, pos.getY(), pos.getZ())) - || BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() + 1)) - || BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() - 1)) - || (!(b instanceof BlockLilyPad && BlockStateInterface.isWater(below)) && below instanceof BlockLiquid);//if it's a lilypad above water, it's ok to break, otherwise don't break if its liquid - // TODO revisit this. why is it not okay to break non-lilypads that are right above water? + // call BlockStateInterface.get directly with x,y,z. no need to make 5 new BlockPos for no reason + || BlockStateInterface.get(x, y + 1, z).getBlock() instanceof BlockLiquid//don't break anything touching liquid on any side + || BlockStateInterface.get(x + 1, y, z).getBlock() instanceof BlockLiquid + || BlockStateInterface.get(x - 1, y, z).getBlock() instanceof BlockLiquid + || BlockStateInterface.get(x, y, z + 1).getBlock() instanceof BlockLiquid + || BlockStateInterface.get(x, y, z - 1).getBlock() instanceof BlockLiquid; } /** @@ -66,32 +69,49 @@ public interface MovementHelper extends ActionCosts, Helper { * @param pos * @return */ - static boolean canWalkThrough(BlockPos pos) { - return canWalkThrough(pos, BlockStateInterface.get(pos)); + static boolean canWalkThrough(BetterBlockPos pos) { + return canWalkThrough(pos.x, pos.y, pos.z, BlockStateInterface.get(pos)); } - static boolean canWalkThrough(BlockPos pos, IBlockState state) { + static boolean canWalkThrough(BetterBlockPos pos, IBlockState state) { + return canWalkThrough(pos.x, pos.y, pos.z, state); + } + + static boolean canWalkThrough(int x, int y, int z) { + return canWalkThrough(x, y, z, BlockStateInterface.get(x, y, z)); + } + + static boolean canWalkThrough(int x, int y, int z, IBlockState state) { Block block = state.getBlock(); - if (block instanceof BlockFire - || block instanceof BlockTripWire - || block instanceof BlockWeb - || block instanceof BlockEndPortal) {//you can't actually walk through a lilypad from the side, and you shouldn't walk through fire + if (block == Blocks.AIR) { // early return for most common case + return true; + } + if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL) { return false; } if (block instanceof BlockDoor || block instanceof BlockFenceGate) { - if (block == Blocks.IRON_DOOR) { - return false; - } - return true; // we can just open the door + // Because there's no nice method in vanilla to check if a door is openable or not, we just have to assume + // that anything that isn't an iron door isn't openable, ignoring that some doors introduced in mods can't + // be opened by just interacting. + return block != Blocks.IRON_DOOR; } - if (block instanceof BlockSnow || block instanceof BlockTrapDoor) { - // we've already checked doors - // so the only remaining dynamic isPassables are snow, fence gate, and trapdoor + boolean snow = block instanceof BlockSnow; + boolean trapdoor = block instanceof BlockTrapDoor; + if (snow || trapdoor) { + // we've already checked doors and fence gates + // so the only remaining dynamic isPassables are snow and trapdoor // if they're cached as a top block, we don't know their metadata // default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible) - if (mc.world.getChunk(pos) instanceof EmptyChunk) { + if (mc.world.getChunk(x >> 4, z >> 4) instanceof EmptyChunk) { return true; } + if (snow) { + return state.getValue(BlockSnow.LAYERS) < 5; // see BlockSnow.isPassable + } + if (trapdoor) { + return !state.getValue(BlockTrapDoor.OPEN); // see BlockTrapDoor.isPassable + } + throw new IllegalStateException(); } if (BlockStateInterface.isFlowing(state)) { return false; // Don't walk through flowing liquids @@ -100,15 +120,60 @@ public interface MovementHelper extends ActionCosts, Helper { if (Baritone.settings().assumeWalkOnWater.get()) { return false; } - IBlockState up = BlockStateInterface.get(pos.up()); + IBlockState up = BlockStateInterface.get(x, y + 1, z); if (up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) { return false; } + return block == Blocks.WATER || block == Blocks.FLOWING_WATER; } - return block.isPassable(mc.world, pos); + // every block that overrides isPassable with anything more complicated than a "return true;" or "return false;" + // has already been accounted for above + // therefore it's safe to not construct a blockpos from our x, y, z ints and instead just pass null + return block.isPassable(null, null); + } + + /** + * canWalkThrough but also won't impede movement at all. so not including doors or fence gates (we'd have to right click), + * not including water, and not including ladders or vines or cobwebs (they slow us down) + * + * @return + */ + static boolean fullyPassable(BlockPos pos) { + return fullyPassable(BlockStateInterface.get(pos)); + } + + static boolean fullyPassable(int x, int y, int z) { + return fullyPassable(BlockStateInterface.get(x, y, z)); + } + + static boolean fullyPassable(IBlockState state) { + Block block = state.getBlock(); + if (block == Blocks.AIR) { // early return for most common case + return true; + } + // exceptions - blocks that are isPassable true, but we can't actually jump through + if (block == Blocks.FIRE + || block == Blocks.TRIPWIRE + || block == Blocks.WEB + || block == Blocks.VINE + || block == Blocks.LADDER + || block instanceof BlockDoor + || block instanceof BlockFenceGate + || block instanceof BlockSnow + || block instanceof BlockLiquid + || block instanceof BlockTrapDoor + || block instanceof BlockEndPortal) { + return false; + } + // door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters + return block.isPassable(null, null); } static boolean isReplacable(BlockPos pos, IBlockState state) { + return isReplacable(pos.getX(), pos.getY(), pos.getZ(), state); + } + + static boolean isReplacable(int x, int y, int z, IBlockState state) { // for MovementTraverse and MovementAscend // block double plant defaults to true when the block doesn't match, so don't need to check that case // all other overrides just return true or false @@ -119,40 +184,51 @@ public interface MovementHelper extends ActionCosts, Helper { * return ((Integer)worldIn.getBlockState(pos).getValue(LAYERS)).intValue() == 1; * } */ - if (state.getBlock() instanceof BlockSnow) { + Block block = state.getBlock(); + if (block instanceof BlockSnow) { // as before, default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible) - if (mc.world.getChunk(pos) instanceof EmptyChunk) { + if (mc.world.getChunk(x >> 4, z >> 4) instanceof EmptyChunk) { return true; } + return state.getValue(BlockSnow.LAYERS) == 1; } - return state.getBlock().isReplaceable(mc.world, pos); + if (block instanceof BlockDoublePlant) { + BlockDoublePlant.EnumPlantType kek = state.getValue(BlockDoublePlant.VARIANT); + return kek == BlockDoublePlant.EnumPlantType.FERN || kek == BlockDoublePlant.EnumPlantType.GRASS; + } + return state.getBlock().isReplaceable(null, null); } static boolean isDoorPassable(BlockPos doorPos, BlockPos playerPos) { - if (playerPos.equals(doorPos)) + if (playerPos.equals(doorPos)) { return false; + } IBlockState state = BlockStateInterface.get(doorPos); - if (!(state.getBlock() instanceof BlockDoor)) + if (!(state.getBlock() instanceof BlockDoor)) { return true; + } return isHorizontalBlockPassable(doorPos, state, playerPos, BlockDoor.OPEN); } static boolean isGatePassable(BlockPos gatePos, BlockPos playerPos) { - if (playerPos.equals(gatePos)) + if (playerPos.equals(gatePos)) { return false; + } IBlockState state = BlockStateInterface.get(gatePos); - if (!(state.getBlock() instanceof BlockFenceGate)) + if (!(state.getBlock() instanceof BlockFenceGate)) { return true; + } return isHorizontalBlockPassable(gatePos, state, playerPos, BlockFenceGate.OPEN); } static boolean isHorizontalBlockPassable(BlockPos blockPos, IBlockState blockState, BlockPos playerPos, PropertyBool propertyOpen) { - if (playerPos.equals(blockPos)) + if (playerPos.equals(blockPos)) { return false; + } EnumFacing.Axis facing = blockState.getValue(BlockHorizontal.FACING).getAxis(); boolean open = blockState.getValue(propertyOpen); @@ -170,11 +246,13 @@ public interface MovementHelper extends ActionCosts, Helper { } static boolean avoidWalkingInto(Block block) { - return BlockStateInterface.isLava(block) - || block instanceof BlockCactus - || block instanceof BlockFire - || block instanceof BlockEndPortal - || block instanceof BlockWeb; + return block instanceof BlockLiquid + || block instanceof BlockDynamicLiquid + || block == Blocks.MAGMA + || block == Blocks.CACTUS + || block == Blocks.FIRE + || block == Blocks.END_PORTAL + || block == Blocks.WEB; } /** @@ -184,76 +262,122 @@ public interface MovementHelper extends ActionCosts, Helper { * * @return */ - static boolean canWalkOn(BlockPos pos, IBlockState state) { + static boolean canWalkOn(int x, int y, int z, IBlockState state) { Block block = state.getBlock(); - if (block instanceof BlockLadder || (Baritone.settings().allowVines.get() && block instanceof BlockVine)) { // TODO reconsider this - return true; - } - if (block instanceof BlockGlass || block instanceof BlockStainedGlass) { - return true; - } - if (Blocks.FARMLAND.equals(block) || Blocks.GRASS_PATH.equals(block)) { - return true; - } - if (Blocks.ENDER_CHEST.equals(block) || Blocks.CHEST.equals(block)) { - return true; - } - if (block instanceof BlockAir) { + if (block == Blocks.AIR || block == Blocks.MAGMA) { + // early return for most common case (air) + // plus magma, which is a normal cube but it hurts you return false; } - if (BlockStateInterface.isWater(block)) { - if (BlockStateInterface.isFlowing(state)) { - return false; + if (state.isBlockNormalCube()) { + if (BlockStateInterface.isLava(block) || BlockStateInterface.isWater(block)) { + throw new IllegalStateException(); } - Block up = BlockStateInterface.get(pos.up()).getBlock(); - if (up instanceof BlockLilyPad) { + return true; + } + if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.get())) { // TODO reconsider this + return true; + } + if (block == Blocks.FARMLAND || block == Blocks.GRASS_PATH) { + return true; + } + if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST) { + return true; + } + if (BlockStateInterface.isWater(block)) { + // since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()" + // BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think its a decrease in readability + Block up = BlockStateInterface.get(x, y + 1, z).getBlock(); + if (up == Blocks.WATERLILY) { return true; } + if (BlockStateInterface.isFlowing(state) || block == Blocks.FLOWING_WATER) { + // the only scenario in which we can walk on flowing water is if it's under still water with jesus off + return BlockStateInterface.isWater(up) && !Baritone.settings().assumeWalkOnWater.get(); + } // if assumeWalkOnWater is on, we can only walk on water if there isn't water above it // if assumeWalkOnWater is off, we can only walk on water if there is water above it return BlockStateInterface.isWater(up) ^ Baritone.settings().assumeWalkOnWater.get(); } - if (Blocks.MAGMA.equals(block)) { - return false; + if (block instanceof BlockGlass || block instanceof BlockStainedGlass) { + return true; } - return state.isBlockNormalCube() && !BlockStateInterface.isLava(block); + if (block instanceof BlockSlab) { + if (!Baritone.settings().allowWalkOnBottomSlab.get()) { + if (((BlockSlab) block).isDouble()) { + return true; + } + return state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM; + } + return true; + } + if (block instanceof BlockStairs) { + return true; + } + return false; } - static boolean canWalkOn(BlockPos pos) { - return canWalkOn(pos, BlockStateInterface.get(pos)); + static boolean canWalkOn(BetterBlockPos pos, IBlockState state) { + return canWalkOn(pos.x, pos.y, pos.z, state); } - static boolean canFall(BlockPos pos) { - return BlockStateInterface.get(pos).getBlock() instanceof BlockFalling; + static boolean canWalkOn(BetterBlockPos pos) { + return canWalkOn(pos.x, pos.y, pos.z, BlockStateInterface.get(pos)); + } + + static boolean canWalkOn(int x, int y, int z) { + return canWalkOn(x, y, z, BlockStateInterface.get(x, y, z)); + } + + static boolean canPlaceAgainst(int x, int y, int z) { + return canPlaceAgainst(BlockStateInterface.get(x, y, z)); } static boolean canPlaceAgainst(BlockPos pos) { - IBlockState state = BlockStateInterface.get(pos); + return canPlaceAgainst(BlockStateInterface.get(pos)); + } + + static boolean canPlaceAgainst(IBlockState state) { // TODO isBlockNormalCube isn't the best check for whether or not we can place a block against it. e.g. glass isn't normalCube but we can place against it return state.isBlockNormalCube(); } - static double getMiningDurationTicks(CalculationContext context, BlockPos position, boolean includeFalling) { + static double getMiningDurationTicks(CalculationContext context, BetterBlockPos position, boolean includeFalling) { IBlockState state = BlockStateInterface.get(position); - return getMiningDurationTicks(context, position, state, includeFalling); + return getMiningDurationTicks(context, position.x, position.y, position.z, state, includeFalling); } - static double getMiningDurationTicks(CalculationContext context, BlockPos position, IBlockState state, boolean includeFalling) { + static double getMiningDurationTicks(CalculationContext context, BetterBlockPos position, IBlockState state, boolean includeFalling) { + return getMiningDurationTicks(context, position.x, position.y, position.z, state, includeFalling); + } + + static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling) { + return getMiningDurationTicks(context, x, y, z, BlockStateInterface.get(x, y, z), includeFalling); + } + + static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) { Block block = state.getBlock(); - if (!block.equals(Blocks.AIR) && !canWalkThrough(position, state)) { // TODO is the air check really necessary? Isn't air canWalkThrough? + if (!canWalkThrough(x, y, z, state)) { if (!context.allowBreak()) { return COST_INF; } - if (avoidBreaking(position, state)) { + if (avoidBreaking(x, y, z, state)) { + return COST_INF; + } + if (block instanceof BlockLiquid) { return COST_INF; } double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table - double result = m / context.getToolSet().getStrVsBlock(state, position); + double strVsBlock = context.getToolSet().getStrVsBlock(state); + if (strVsBlock <= 0) { + return COST_INF; + } + + double result = m / strVsBlock; if (includeFalling) { - BlockPos up = position.up(); - IBlockState above = BlockStateInterface.get(up); + IBlockState above = BlockStateInterface.get(x, y + 1, z); if (above.getBlock() instanceof BlockFalling) { - result += getMiningDurationTicks(context, up, above, true); + result += getMiningDurationTicks(context, x, y + 1, z, above, true); } } return result; @@ -261,6 +385,16 @@ public interface MovementHelper extends ActionCosts, Helper { return 0; // we won't actually mine it, so don't check fallings above } + static boolean isBottomSlab(IBlockState state) { + return state.getBlock() instanceof BlockSlab + && !((BlockSlab) state.getBlock()).isDouble() + && state.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM; + } + + static boolean isBottomSlab(BlockPos pos) { + return isBottomSlab(BlockStateInterface.get(pos)); + } + /** * The entity the player is currently looking at * @@ -329,56 +463,8 @@ public interface MovementHelper extends ActionCosts, Helper { state.setTarget(new MovementTarget( new Rotation(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F), Utils.getBlockPosCenter(pos), - new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)).getFirst(), mc.player.rotationPitch), + new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)).getYaw(), mc.player.rotationPitch), false )).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true); } - - static Movement generateMovementFallOrDescend(BlockPos pos, BlockPos dest, CalculationContext calcContext) { - // A - //SA - // A - // B - // C - // D - //if S is where you start, B needs to be air for a movementfall - //A is plausibly breakable by either descend or fall - //C, D, etc determine the length of the fall - - if (!canWalkThrough(dest.down(2))) { - //if B in the diagram aren't air - //have to do a descend, because fall is impossible - - //this doesn't guarantee descend is possible, it just guarantees fall is impossible - return new MovementDescend(pos, dest.down()); // standard move out by 1 and descend by 1 - } - - // we're clear for a fall 2 - // let's see how far we can fall - for (int fallHeight = 3; true; fallHeight++) { - BlockPos onto = dest.down(fallHeight); - if (onto.getY() < 0) { - // when pathing in the end, where you could plausibly fall into the void - // this check prevents it from getting the block at y=-1 and crashing - break; - } - IBlockState ontoBlock = BlockStateInterface.get(onto); - if (BlockStateInterface.isWater(ontoBlock.getBlock())) { - return new MovementFall(pos, onto); - } - if (canWalkThrough(onto, ontoBlock)) { - continue; - } - if (canWalkOn(onto, ontoBlock)) { - if ((calcContext.hasWaterBucket() && fallHeight <= calcContext.maxFallHeightBucket() + 1) || fallHeight <= calcContext.maxFallHeightNoWater() + 1) { - // fallHeight = 4 means onto.up() is 3 blocks down, which is the max - return new MovementFall(pos, onto.up()); - } else { - return null; - } - } - break; - } - return null; - } } diff --git a/src/main/java/baritone/pathing/movement/MovementState.java b/src/main/java/baritone/pathing/movement/MovementState.java index 057d22bb..6d0262e6 100644 --- a/src/main/java/baritone/pathing/movement/MovementState.java +++ b/src/main/java/baritone/pathing/movement/MovementState.java @@ -2,23 +2,23 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.movement; +import baritone.api.utils.Rotation; import baritone.utils.InputOverrideHandler.Input; -import baritone.utils.Rotation; import net.minecraft.util.math.Vec3d; import java.util.HashMap; diff --git a/src/main/java/baritone/pathing/movement/Moves.java b/src/main/java/baritone/pathing/movement/Moves.java new file mode 100644 index 00000000..6f49dfbd --- /dev/null +++ b/src/main/java/baritone/pathing/movement/Moves.java @@ -0,0 +1,333 @@ +/* + * 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 . + */ + +package baritone.pathing.movement; + +import baritone.pathing.movement.movements.*; +import baritone.utils.pathing.BetterBlockPos; +import baritone.utils.pathing.MoveResult; +import net.minecraft.util.EnumFacing; + +/** + * An enum of all possible movements attached to all possible directions they could be taken in + * + * @author leijurv + */ +public enum Moves { + DOWNWARD(0, 0) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementDownward(src, src.down()); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x, y - 1, z, MovementDownward.cost(context, x, y, z)); + } + }, + + PILLAR(0, 0) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementPillar(src, src.up()); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x, y + 1, z, MovementPillar.cost(context, x, y, z)); + } + }, + + TRAVERSE_NORTH(0, -1) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementTraverse(src, src.north()); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x, y, z - 1, MovementTraverse.cost(context, x, y, z, x, z - 1)); + } + }, + + TRAVERSE_SOUTH(0, +1) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementTraverse(src, src.south()); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x, y, z + 1, MovementTraverse.cost(context, x, y, z, x, z + 1)); + } + }, + + TRAVERSE_EAST(+1, 0) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementTraverse(src, src.east()); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x + 1, y, z, MovementTraverse.cost(context, x, y, z, x + 1, z)); + } + }, + + TRAVERSE_WEST(-1, 0) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementTraverse(src, src.west()); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x - 1, y, z, MovementTraverse.cost(context, x, y, z, x - 1, z)); + } + }, + + ASCEND_NORTH(0, -1) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementAscend(src, new BetterBlockPos(src.x, src.y + 1, src.z - 1)); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x, y + 1, z - 1, MovementAscend.cost(context, x, y, z, x, z - 1)); + } + }, + + ASCEND_SOUTH(0, +1) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementAscend(src, new BetterBlockPos(src.x, src.y + 1, src.z + 1)); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x, y + 1, z + 1, MovementAscend.cost(context, x, y, z, x, z + 1)); + } + }, + + ASCEND_EAST(+1, 0) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementAscend(src, new BetterBlockPos(src.x + 1, src.y + 1, src.z)); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x + 1, y + 1, z, MovementAscend.cost(context, x, y, z, x + 1, z)); + } + }, + + ASCEND_WEST(-1, 0) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementAscend(src, new BetterBlockPos(src.x - 1, src.y + 1, src.z)); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x - 1, y + 1, z, MovementAscend.cost(context, x, y, z, x - 1, z)); + } + }, + + DESCEND_EAST(+1, 0) { + @Override + public Movement apply0(BetterBlockPos src) { + MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z); + if (res.destY == src.y - 1) { + return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); + } else { + return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); + } + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return MovementDescend.cost(context, x, y, z, x + 1, z); + } + }, + + DESCEND_WEST(-1, 0) { + @Override + public Movement apply0(BetterBlockPos src) { + MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z); + if (res.destY == src.y - 1) { + return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); + } else { + return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); + } + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return MovementDescend.cost(context, x, y, z, x - 1, z); + } + }, + + DESCEND_NORTH(0, -1) { + @Override + public Movement apply0(BetterBlockPos src) { + MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z); + if (res.destY == src.y - 1) { + return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); + } else { + return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); + } + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return MovementDescend.cost(context, x, y, z, x, z - 1); + } + }, + + DESCEND_SOUTH(0, +1) { + @Override + public Movement apply0(BetterBlockPos src) { + MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z); + if (res.destY == src.y - 1) { + return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); + } else { + return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); + } + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return MovementDescend.cost(context, x, y, z, x, z + 1); + } + }, + + DIAGONAL_NORTHEAST(+1, -1) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementDiagonal(src, EnumFacing.NORTH, EnumFacing.EAST); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x + 1, y, z - 1, MovementDiagonal.cost(context, x, y, z, x + 1, z - 1)); + } + }, + + DIAGONAL_NORTHWEST(-1, -1) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementDiagonal(src, EnumFacing.NORTH, EnumFacing.WEST); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x - 1, y, z - 1, MovementDiagonal.cost(context, x, y, z, x - 1, z - 1)); + } + }, + + DIAGONAL_SOUTHEAST(+1, +1) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementDiagonal(src, EnumFacing.SOUTH, EnumFacing.EAST); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x + 1, y, z + 1, MovementDiagonal.cost(context, x, y, z, x + 1, z + 1)); + } + }, + + DIAGONAL_SOUTHWEST(-1, +1) { + @Override + public Movement apply0(BetterBlockPos src) { + return new MovementDiagonal(src, EnumFacing.SOUTH, EnumFacing.WEST); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return new MoveResult(x - 1, y, z + 1, MovementDiagonal.cost(context, x, y, z, x - 1, z + 1)); + } + }, + + PARKOUR_NORTH(0, -4, true) { + @Override + public Movement apply0(BetterBlockPos src) { + return MovementParkour.cost(new CalculationContext(), src, EnumFacing.NORTH); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return MovementParkour.cost(context, x, y, z, EnumFacing.NORTH); + } + }, + + PARKOUR_SOUTH(0, +4, true) { + @Override + public Movement apply0(BetterBlockPos src) { + return MovementParkour.cost(new CalculationContext(), src, EnumFacing.SOUTH); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return MovementParkour.cost(context, x, y, z, EnumFacing.SOUTH); + } + }, + + PARKOUR_EAST(+4, 0, true) { + @Override + public Movement apply0(BetterBlockPos src) { + return MovementParkour.cost(new CalculationContext(), src, EnumFacing.EAST); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return MovementParkour.cost(context, x, y, z, EnumFacing.EAST); + } + }, + + PARKOUR_WEST(-4, 0, true) { + @Override + public Movement apply0(BetterBlockPos src) { + return MovementParkour.cost(new CalculationContext(), src, EnumFacing.WEST); + } + + @Override + public MoveResult apply(CalculationContext context, int x, int y, int z) { + return MovementParkour.cost(context, x, y, z, EnumFacing.WEST); + } + }; + + public final boolean dynamicXZ; + + public final int xOffset; + public final int zOffset; + + Moves(int x, int z, boolean dynamicXZ) { + this.xOffset = x; + this.zOffset = z; + this.dynamicXZ = dynamicXZ; + } + + Moves(int x, int z) { + this(x, z, false); + } + + public abstract Movement apply0(BetterBlockPos src); + + public abstract MoveResult apply(CalculationContext context, int x, int y, int z); +} diff --git a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java index a50dfba8..6d313c48 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java @@ -2,22 +2,23 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.movement.movements; -import baritone.behavior.impl.LookBehaviorUtils; +import baritone.Baritone; +import baritone.behavior.LookBehaviorUtils; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; @@ -26,7 +27,7 @@ import baritone.pathing.movement.MovementState.MovementStatus; import baritone.utils.BlockStateInterface; import baritone.utils.InputOverrideHandler; import baritone.utils.Utils; -import net.minecraft.block.Block; +import baritone.utils.pathing.BetterBlockPos; import net.minecraft.block.BlockFalling; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -41,8 +42,8 @@ public class MovementAscend extends Movement { private int ticksWithoutPlacement = 0; - public MovementAscend(BlockPos src, BlockPos dest) { - super(src, dest, new BlockPos[]{dest, src.up(2), dest.up()}, dest.down()); + public MovementAscend(BetterBlockPos src, BetterBlockPos dest) { + super(src, dest, new BetterBlockPos[]{dest, src.up(2), dest.up()}, dest.down()); } @Override @@ -53,35 +54,54 @@ public class MovementAscend extends Movement { @Override protected double calculateCost(CalculationContext context) { - IBlockState toPlace = BlockStateInterface.get(positionToPlace); - if (!MovementHelper.canWalkOn(positionToPlace, toPlace)) { + return cost(context, src.x, src.y, src.z, dest.x, dest.z); + } + + public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { + IBlockState srcDown = BlockStateInterface.get(x, y - 1, z); + if (srcDown.getBlock() == Blocks.LADDER || srcDown.getBlock() == Blocks.VINE) { + return COST_INF; + } + // we can jump from soul sand, but not from a bottom slab + boolean jumpingFromBottomSlab = MovementHelper.isBottomSlab(srcDown); + IBlockState toPlace = BlockStateInterface.get(destX, y, destZ); + boolean jumpingToBottomSlab = MovementHelper.isBottomSlab(toPlace); + + if (jumpingFromBottomSlab && !jumpingToBottomSlab) { + return COST_INF;// the only thing we can ascend onto from a bottom slab is another bottom slab + } + boolean hasToPlace = false; + if (!MovementHelper.canWalkOn(destX, y, z, toPlace)) { if (!context.hasThrowaway()) { return COST_INF; } - if (!BlockStateInterface.isAir(toPlace) && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(positionToPlace, toPlace)) { + if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y, destZ, toPlace)) { return COST_INF; } // TODO: add ability to place against .down() as well as the cardinal directions // useful for when you are starting a staircase without anything to place against // Counterpoint to the above TODO ^ you should move then pillar instead of ascend for (int i = 0; i < 4; i++) { - BlockPos against1 = positionToPlace.offset(HORIZONTALS[i]); - if (against1.equals(src)) { + int againstX = destX + HORIZONTALS[i].getXOffset(); + int againstZ = destZ + HORIZONTALS[i].getZOffset(); + if (againstX == x && againstZ == z) { continue; } - if (MovementHelper.canPlaceAgainst(against1)) { - return JUMP_ONE_BLOCK_COST + WALK_ONE_BLOCK_COST + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context); + if (MovementHelper.canPlaceAgainst(againstX, y, againstZ)) { + hasToPlace = true; + break; } } - return COST_INF; + if (!hasToPlace) { // didn't find a valid place =( + return COST_INF; + } } - if (BlockStateInterface.get(src.up(3)).getBlock() instanceof BlockFalling) {//it would fall on us and possibly suffocate us + IBlockState srcUp2 = null; + if (BlockStateInterface.get(x, y + 3, z).getBlock() instanceof BlockFalling) {//it would fall on us and possibly suffocate us // HOWEVER, we assume that we're standing in the start position // that means that src and src.up(1) are both air // maybe they aren't now, but they will be by the time this starts - Block srcUp = BlockStateInterface.get(src.up(1)).getBlock(); - Block srcUp2 = BlockStateInterface.get(src.up(2)).getBlock(); - if (!(srcUp instanceof BlockFalling) || !(srcUp2 instanceof BlockFalling)) { + if (!(BlockStateInterface.getBlock(x, y + 1, z) instanceof BlockFalling) || !((srcUp2 = BlockStateInterface.get(x, y + 2, z)).getBlock() instanceof BlockFalling)) { // if both of those are BlockFalling, that means that by standing on src // (the presupposition of this Movement) // we have necessarily already cleared the entire BlockFalling stack @@ -96,13 +116,41 @@ public class MovementAscend extends Movement { // it's possible srcUp is AIR from the start, and srcUp2 is falling // and in that scenario, when we arrive and break srcUp2, that lets srcUp3 fall on us and suffocate us } - // TODO maybe change behavior if src.down() is soul sand? - double walk = WALK_ONE_BLOCK_COST; - if (toPlace.getBlock().equals(Blocks.SOUL_SAND)) { - walk *= WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST; + double walk; + if (jumpingToBottomSlab) { + if (jumpingFromBottomSlab) { + walk = Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST); // we hit space immediately on entering this action + } else { + walk = WALK_ONE_BLOCK_COST; // we don't hit space we just walk into the slab + } + } else { + if (toPlace.getBlock() == Blocks.SOUL_SAND) { + walk = WALK_ONE_OVER_SOUL_SAND_COST; + } else { + walk = WALK_ONE_BLOCK_COST; + } } - // we hit space immediately on entering this action - return Math.max(JUMP_ONE_BLOCK_COST, walk) + getTotalHardnessOfBlocksToBreak(context); + + // cracks knuckles + + double totalCost = 0; + totalCost += walk; + if (hasToPlace) { + totalCost += context.placeBlockCost(); + } + if (srcUp2 == null) { + srcUp2 = BlockStateInterface.get(x, y + 2, z); + } + totalCost += MovementHelper.getMiningDurationTicks(context, x, y + 2, z, srcUp2, false); // TODO MAKE ABSOLUTELY SURE we don't need includeFalling here, from the falling check above + if (totalCost >= COST_INF) { + return COST_INF; + } + totalCost += MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, false); + if (totalCost >= COST_INF) { + return COST_INF; + } + totalCost += MovementHelper.getMiningDurationTicks(context, destX, y + 2, destZ, true); + return totalCost; } @Override @@ -110,20 +158,16 @@ public class MovementAscend extends Movement { super.updateState(state); // TODO incorporate some behavior from ActionClimb (specifically how it waited until it was at most 1.2 blocks away before starting to jump // for efficiency in ascending minimal height staircases, which is just repeated MovementAscend, so that it doesn't bonk its head on the ceiling repeatedly) - switch (state.getStatus()) { - case WAITING: - state.setStatus(MovementStatus.RUNNING); - case RUNNING: - break; - default: - return state; + if (state.getStatus() != MovementStatus.RUNNING) { + return state; } if (playerFeet().equals(dest)) { return state.setStatus(MovementStatus.SUCCESS); } - if (!MovementHelper.canWalkOn(positionToPlace)) { + IBlockState jumpingOnto = BlockStateInterface.get(positionToPlace); + if (!MovementHelper.canWalkOn(positionToPlace, jumpingOnto)) { for (int i = 0; i < 4; i++) { BlockPos anAgainst = positionToPlace.offset(HORIZONTALS[i]); if (anAgainst.equals(src)) { @@ -146,8 +190,8 @@ public class MovementAscend extends Movement { if (player().isSneaking()) { state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); } - if (ticksWithoutPlacement > 20) { - // After 20 ticks without placement, we might be standing in the way, move back + if (ticksWithoutPlacement > 10) { + // After 10 ticks without placement, we might be standing in the way, move back state.setInput(InputOverrideHandler.Input.MOVE_BACK, true); } } else { @@ -161,6 +205,15 @@ public class MovementAscend extends Movement { return state.setStatus(MovementStatus.UNREACHABLE); } MovementHelper.moveTowards(state, dest); + if (MovementHelper.isBottomSlab(jumpingOnto)) { + if (!MovementHelper.isBottomSlab(src.down())) { + return state; // don't jump while walking from a non double slab into a bottom slab + } + } + + if (Baritone.settings().assumeStep.get()) { + return state; + } if (headBonkClear()) { return state.setInput(InputOverrideHandler.Input.JUMP, true); @@ -182,9 +235,9 @@ public class MovementAscend extends Movement { } private boolean headBonkClear() { - BlockPos startUp = src.up(2); + BetterBlockPos startUp = src.up(2); for (int i = 0; i < 4; i++) { - BlockPos check = startUp.offset(EnumFacing.byHorizontalIndex(i)); + BetterBlockPos check = startUp.offset(EnumFacing.byHorizontalIndex(i)); if (!MovementHelper.canWalkThrough(check)) { // We might bonk our head return false; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index 7a07abb1..b8c6bc43 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -2,21 +2,22 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.movement.movements; +import baritone.Baritone; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; @@ -24,16 +25,22 @@ import baritone.pathing.movement.MovementState; import baritone.pathing.movement.MovementState.MovementStatus; import baritone.utils.BlockStateInterface; import baritone.utils.InputOverrideHandler; +import baritone.utils.pathing.BetterBlockPos; +import baritone.utils.pathing.MoveResult; import net.minecraft.block.Block; -import net.minecraft.block.BlockLadder; -import net.minecraft.block.BlockVine; +import net.minecraft.block.BlockFalling; +import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; +import static baritone.utils.pathing.MoveResult.IMPOSSIBLE; + public class MovementDescend extends Movement { - public MovementDescend(BlockPos start, BlockPos end) { - super(start, end, new BlockPos[]{end.up(2), end.up(), end}, end.down()); + private int numTicks = 0; + + public MovementDescend(BetterBlockPos start, BetterBlockPos end) { + super(start, end, new BetterBlockPos[]{end.up(2), end.up(), end}, end.down()); } @Override @@ -44,42 +51,125 @@ public class MovementDescend extends Movement { @Override protected double calculateCost(CalculationContext context) { - if (!MovementHelper.canWalkOn(positionToPlace)) { - return COST_INF; + MoveResult result = cost(context, src.x, src.y, src.z, dest.x, dest.z); + if (result.destY != dest.y) { + return COST_INF; // doesn't apply to us, this position is a fall not a descend } - Block tmp1 = BlockStateInterface.get(dest).getBlock(); - if (tmp1 instanceof BlockLadder || tmp1 instanceof BlockVine) { - return COST_INF; - } - // we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel) - double walk = WALK_OFF_BLOCK_COST; - if (BlockStateInterface.get(src.down()).getBlock().equals(Blocks.SOUL_SAND)) { - // use this ratio to apply the soul sand speed penalty to our 0.8 block distance - walk *= WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST; - } - return walk + Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST) + getTotalHardnessOfBlocksToBreak(context); + return result.cost; } - int numTicks = 0; + public static MoveResult cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { + Block fromDown = BlockStateInterface.get(x, y - 1, z).getBlock(); + if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) { + return IMPOSSIBLE; + } + + double totalCost = 0; + totalCost += MovementHelper.getMiningDurationTicks(context, destX, y - 1, destZ, false); + if (totalCost >= COST_INF) { + return IMPOSSIBLE; + } + totalCost += MovementHelper.getMiningDurationTicks(context, destX, y, destZ, false); + if (totalCost >= COST_INF) { + return IMPOSSIBLE; + } + totalCost += MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, true); // only the top block in the 3 we need to mine needs to consider the falling blocks above + if (totalCost >= COST_INF) { + return IMPOSSIBLE; + } + + // A + //SA + // A + // B + // C + // D + //if S is where you start, B needs to be air for a movementfall + //A is plausibly breakable by either descend or fall + //C, D, etc determine the length of the fall + + IBlockState below = BlockStateInterface.get(destX, y - 2, destZ); + if (!MovementHelper.canWalkOn(destX, y - 2, destZ, below)) { + return dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below); + } + + Block tmp1 = BlockStateInterface.get(destX, y - 1, destZ).getBlock(); + if (tmp1 == Blocks.LADDER || tmp1 == Blocks.VINE) { + return IMPOSSIBLE; + } + + // we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel) + double walk = WALK_OFF_BLOCK_COST; + if (fromDown == Blocks.SOUL_SAND) { + // use this ratio to apply the soul sand speed penalty to our 0.8 block distance + walk = WALK_ONE_OVER_SOUL_SAND_COST; + } + totalCost += walk + Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST); + return new MoveResult(destX, y - 1, destZ, totalCost); + } + + public static MoveResult dynamicFallCost(CalculationContext context, int x, int y, int z, int destX, int destZ, double frontBreak, IBlockState below) { + if (frontBreak != 0 && BlockStateInterface.get(destX, y + 2, destZ).getBlock() instanceof BlockFalling) { + // if frontBreak is 0 we can actually get through this without updating the falling block and making it actually fall + // but if frontBreak is nonzero, we're breaking blocks in front, so don't let anything fall through this column, + // and potentially replace the water we're going to fall into + return IMPOSSIBLE; + } + if (!MovementHelper.canWalkThrough(destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) { + return IMPOSSIBLE; + } + for (int fallHeight = 3; true; fallHeight++) { + int newY = y - fallHeight; + if (newY < 0) { + // when pathing in the end, where you could plausibly fall into the void + // this check prevents it from getting the block at y=-1 and crashing + return IMPOSSIBLE; + } + IBlockState ontoBlock = BlockStateInterface.get(destX, newY, destZ); + double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[fallHeight] + frontBreak; + if (ontoBlock.getBlock() == Blocks.WATER && !BlockStateInterface.isFlowing(ontoBlock)) { // TODO flowing check required here? + if (Baritone.settings().assumeWalkOnWater.get()) { + return IMPOSSIBLE; // TODO fix + } + // found a fall into water + return new MoveResult(destX, newY, destZ, tentativeCost); // TODO incorporate water swim up cost? + } + if (ontoBlock.getBlock() == Blocks.FLOWING_WATER) { + return IMPOSSIBLE; + } + if (MovementHelper.canWalkThrough(destX, newY, destZ, ontoBlock)) { + continue; + } + if (!MovementHelper.canWalkOn(destX, newY, destZ, ontoBlock)) { + return IMPOSSIBLE; + } + if (MovementHelper.isBottomSlab(ontoBlock)) { + return IMPOSSIBLE; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect + } + if (context.hasWaterBucket() && fallHeight <= context.maxFallHeightBucket() + 1) { + return new MoveResult(destX, newY + 1, destZ, tentativeCost + context.placeBlockCost()); // this is the block we're falling onto, so dest is +1 + } + if (fallHeight <= context.maxFallHeightNoWater() + 1) { + // fallHeight = 4 means onto.up() is 3 blocks down, which is the max + return new MoveResult(destX, newY + 1, destZ, tentativeCost); + } else { + return IMPOSSIBLE; + } + } + } @Override public MovementState updateState(MovementState state) { super.updateState(state); - switch (state.getStatus()) { - case WAITING: - state.setStatus(MovementStatus.RUNNING); - case RUNNING: - break; - default: - return state; + if (state.getStatus() != MovementStatus.RUNNING) { + return state; } BlockPos playerFeet = playerFeet(); if (playerFeet.equals(dest)) { if (BlockStateInterface.isLiquid(dest) || player().posY - playerFeet.getY() < 0.094) { // lilypads // Wait until we're actually on the ground before saying we're done because sometimes we continue to fall if the next action starts immediately - state.setStatus(MovementStatus.SUCCESS); - return state; + return state.setStatus(MovementStatus.SUCCESS); } else { System.out.println(player().posY + " " + playerFeet.getY() + " " + (player().posY - playerFeet.getY())); } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java index 1ce5537f..d1fe89a4 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -23,8 +23,8 @@ import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementState; import baritone.utils.BlockStateInterface; import baritone.utils.InputOverrideHandler; +import baritone.utils.pathing.BetterBlockPos; import net.minecraft.block.Block; -import net.minecraft.block.BlockMagma; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; @@ -37,74 +37,59 @@ public class MovementDiagonal extends Movement { private static final double SQRT_2 = Math.sqrt(2); - public MovementDiagonal(BlockPos start, EnumFacing dir1, EnumFacing dir2) { + public MovementDiagonal(BetterBlockPos start, EnumFacing dir1, EnumFacing dir2) { this(start, start.offset(dir1), start.offset(dir2), dir2); // super(start, start.offset(dir1).offset(dir2), new BlockPos[]{start.offset(dir1), start.offset(dir1).up(), start.offset(dir2), start.offset(dir2).up(), start.offset(dir1).offset(dir2), start.offset(dir1).offset(dir2).up()}, new BlockPos[]{start.offset(dir1).offset(dir2).down()}); } - public MovementDiagonal(BlockPos start, BlockPos dir1, BlockPos dir2, EnumFacing drr2) { + private MovementDiagonal(BetterBlockPos start, BetterBlockPos dir1, BetterBlockPos dir2, EnumFacing drr2) { this(start, dir1.offset(drr2), dir1, dir2); } - public MovementDiagonal(BlockPos start, BlockPos end, BlockPos dir1, BlockPos dir2) { - super(start, end, new BlockPos[]{dir1, dir1.up(), dir2, dir2.up(), end, end.up()}); - } - - @Override - public MovementState updateState(MovementState state) { - super.updateState(state); - switch (state.getStatus()) { - case WAITING: - state.setStatus(MovementState.MovementStatus.RUNNING); - case RUNNING: - break; - default: - return state; - } - - if (playerFeet().equals(dest)) { - state.setStatus(MovementState.MovementStatus.SUCCESS); - return state; - } - if (!BlockStateInterface.isLiquid(playerFeet())) { - state.setInput(InputOverrideHandler.Input.SPRINT, true); - } - MovementHelper.moveTowards(state, dest); - return state; + private MovementDiagonal(BetterBlockPos start, BetterBlockPos end, BetterBlockPos dir1, BetterBlockPos dir2) { + super(start, end, new BetterBlockPos[]{dir1, dir1.up(), dir2, dir2.up(), end, end.up()}); } @Override protected double calculateCost(CalculationContext context) { - if (!MovementHelper.canWalkThrough(positionsToBreak[4]) || !MovementHelper.canWalkThrough(positionsToBreak[5])) { + return cost(context, src.x, src.y, src.z, dest.x, dest.z); + } + + public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { + Block fromDown = BlockStateInterface.get(x, y - 1, z).getBlock(); + if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) { return COST_INF; } - BlockPos destDown = dest.down(); - IBlockState destWalkOn = BlockStateInterface.get(destDown); - if (!MovementHelper.canWalkOn(destDown, destWalkOn)) { + IBlockState destInto = BlockStateInterface.get(destX, y, destZ); + if (!MovementHelper.canWalkThrough(destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(destX, y + 1, destZ)) { + return COST_INF; + } + IBlockState destWalkOn = BlockStateInterface.get(destX, y - 1, destZ); + if (!MovementHelper.canWalkOn(destX, y - 1, destZ, destWalkOn)) { return COST_INF; } double multiplier = WALK_ONE_BLOCK_COST; // For either possible soul sand, that affects half of our walking - if (destWalkOn.getBlock().equals(Blocks.SOUL_SAND)) { + if (destWalkOn.getBlock() == Blocks.SOUL_SAND) { multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; } - if (BlockStateInterface.get(src.down()).getBlock().equals(Blocks.SOUL_SAND)) { + if (fromDown == Blocks.SOUL_SAND) { multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; } - Block cuttingOver1 = BlockStateInterface.get(positionsToBreak[2].down()).getBlock(); - if (cuttingOver1 instanceof BlockMagma || BlockStateInterface.isLava(cuttingOver1)) { + Block cuttingOver1 = BlockStateInterface.get(x, y - 1, destZ).getBlock(); + if (cuttingOver1 == Blocks.MAGMA || BlockStateInterface.isLava(cuttingOver1)) { return COST_INF; } - Block cuttingOver2 = BlockStateInterface.get(positionsToBreak[4].down()).getBlock(); - if (cuttingOver2 instanceof BlockMagma || BlockStateInterface.isLava(cuttingOver2)) { + Block cuttingOver2 = BlockStateInterface.get(destX, y - 1, z).getBlock(); + if (cuttingOver2 == Blocks.MAGMA || BlockStateInterface.isLava(cuttingOver2)) { return COST_INF; } - IBlockState pb0 = BlockStateInterface.get(positionsToBreak[0]); - IBlockState pb1 = BlockStateInterface.get(positionsToBreak[1]); - IBlockState pb2 = BlockStateInterface.get(positionsToBreak[2]); - IBlockState pb3 = BlockStateInterface.get(positionsToBreak[3]); - double optionA = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0], pb0, false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1], pb1, true); - double optionB = MovementHelper.getMiningDurationTicks(context, positionsToBreak[2], pb2, false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[3], pb3, true); + IBlockState pb0 = BlockStateInterface.get(x, y, destZ); + IBlockState pb1 = BlockStateInterface.get(x, y + 1, destZ); + IBlockState pb2 = BlockStateInterface.get(destX, y, z); + IBlockState pb3 = BlockStateInterface.get(destX, y + 1, z); + double optionA = MovementHelper.getMiningDurationTicks(context, x, y, destZ, pb0, false) + MovementHelper.getMiningDurationTicks(context, x, y + 1, destZ, pb1, true); + double optionB = MovementHelper.getMiningDurationTicks(context, destX, y, z, pb2, false) + MovementHelper.getMiningDurationTicks(context, destX, y + 1, z, pb3, true); if (optionA != 0 && optionB != 0) { return COST_INF; } @@ -118,7 +103,7 @@ public class MovementDiagonal extends Movement { return COST_INF; } } - if (BlockStateInterface.isWater(src) || BlockStateInterface.isWater(dest)) { + if (BlockStateInterface.isWater(BlockStateInterface.getBlock(x, y, z)) || BlockStateInterface.isWater(destInto.getBlock())) { // Ignore previous multiplier // Whatever we were walking on (possibly soul sand) doesn't matter as we're actually floating on water // Not even touching the blocks below @@ -135,6 +120,24 @@ public class MovementDiagonal extends Movement { return multiplier * SQRT_2; } + @Override + public MovementState updateState(MovementState state) { + super.updateState(state); + if (state.getStatus() != MovementState.MovementStatus.RUNNING) { + return state; + } + + if (playerFeet().equals(dest)) { + state.setStatus(MovementState.MovementStatus.SUCCESS); + return state; + } + if (!BlockStateInterface.isLiquid(playerFeet())) { + state.setInput(InputOverrideHandler.Input.SPRINT, true); + } + MovementHelper.moveTowards(state, dest); + return state; + } + @Override protected boolean prepared(MovementState state) { return true; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDownward.java b/src/main/java/baritone/pathing/movement/movements/MovementDownward.java index ece2c8f5..148dc3b3 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDownward.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDownward.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -22,18 +22,17 @@ import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementState; import baritone.utils.BlockStateInterface; +import baritone.utils.pathing.BetterBlockPos; import net.minecraft.block.Block; -import net.minecraft.block.BlockLadder; -import net.minecraft.block.BlockVine; import net.minecraft.block.state.IBlockState; -import net.minecraft.util.math.BlockPos; +import net.minecraft.init.Blocks; public class MovementDownward extends Movement { private int numTicks = 0; - public MovementDownward(BlockPos start, BlockPos end) { - super(start, end, new BlockPos[]{end}); + public MovementDownward(BetterBlockPos start, BetterBlockPos end) { + super(start, end, new BetterBlockPos[]{end}); } @Override @@ -44,35 +43,33 @@ public class MovementDownward extends Movement { @Override protected double calculateCost(CalculationContext context) { - if (!MovementHelper.canWalkOn(dest.down())) { + return cost(context, src.x, src.y, src.z); + } + + public static double cost(CalculationContext context, int x, int y, int z) { + if (!MovementHelper.canWalkOn(x, y - 2, z)) { return COST_INF; } - IBlockState d = BlockStateInterface.get(dest); + IBlockState d = BlockStateInterface.get(x, y - 1, z); Block td = d.getBlock(); - boolean ladder = td instanceof BlockLadder || td instanceof BlockVine; + boolean ladder = td == Blocks.LADDER || td == Blocks.VINE; if (ladder) { return LADDER_DOWN_ONE_COST; } else { // we're standing on it, while it might be block falling, it'll be air by the time we get here in the movement - return FALL_N_BLOCKS_COST[1] + MovementHelper.getMiningDurationTicks(context, dest, d, false); + return FALL_N_BLOCKS_COST[1] + MovementHelper.getMiningDurationTicks(context, x, y - 1, z, d, false); } } @Override public MovementState updateState(MovementState state) { super.updateState(state); - switch (state.getStatus()) { - case WAITING: - state.setStatus(MovementState.MovementStatus.RUNNING); - case RUNNING: - break; - default: - return state; + if (state.getStatus() != MovementState.MovementStatus.RUNNING) { + return state; } if (playerFeet().equals(dest)) { - state.setStatus(MovementState.MovementStatus.SUCCESS); - return state; + return state.setStatus(MovementState.MovementStatus.SUCCESS); } double diffX = player().posX - (dest.getX() + 0.5); double diffZ = player().posZ - (dest.getZ() + 0.5); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementFall.java b/src/main/java/baritone/pathing/movement/movements/MovementFall.java index ee019c98..0f165f6f 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementFall.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementFall.java @@ -2,30 +2,36 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.movement.movements; import baritone.Baritone; +import baritone.api.utils.Rotation; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementState; import baritone.pathing.movement.MovementState.MovementStatus; import baritone.pathing.movement.MovementState.MovementTarget; -import baritone.utils.*; -import net.minecraft.block.BlockFalling; +import baritone.utils.BlockStateInterface; +import baritone.utils.InputOverrideHandler; +import baritone.utils.RayTraceUtils; +import baritone.utils.Utils; +import baritone.utils.pathing.BetterBlockPos; +import baritone.utils.pathing.MoveResult; +import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; @@ -37,68 +43,31 @@ public class MovementFall extends Movement { private static final ItemStack STACK_BUCKET_WATER = new ItemStack(Items.WATER_BUCKET); private static final ItemStack STACK_BUCKET_EMPTY = new ItemStack(Items.BUCKET); - public MovementFall(BlockPos src, BlockPos dest) { + public MovementFall(BetterBlockPos src, BetterBlockPos dest) { super(src, dest, MovementFall.buildPositionsToBreak(src, dest)); } @Override protected double calculateCost(CalculationContext context) { - if (!MovementHelper.canWalkOn(dest.down())) { - return COST_INF; + MoveResult result = MovementDescend.cost(context, src.x, src.y, src.z, dest.x, dest.z); + if (result.destY != dest.y) { + return COST_INF; // doesn't apply to us, this position is a descend not a fall } - double placeBucketCost = 0.0; - if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > context.maxFallHeightNoWater()) { - if (!context.hasWaterBucket()) { - return COST_INF; - } - if (src.getY() - dest.getY() > context.maxFallHeightBucket()) { - return COST_INF; - } - placeBucketCost = context.placeBlockCost(); - } - double frontThree = 0; - for (int i = 0; i < 3; i++) { - frontThree += MovementHelper.getMiningDurationTicks(context, positionsToBreak[i], false); - // don't include falling because we will check falling right after this, and if it's there it's COST_INF - if (frontThree >= COST_INF) { - return COST_INF; - } - } - if (BlockStateInterface.get(positionsToBreak[0].up()).getBlock() instanceof BlockFalling) { - return COST_INF; - } - for (int i = 3; i < positionsToBreak.length; i++) { - // TODO is this the right check here? - // MiningDurationTicks is all right, but shouldn't it be canWalkThrough instead? - // Lilypads (i think?) are 0 ticks to mine, but they definitely cause fall damage - // Same thing for falling through water... we can't actually do that - // And falling through signs is possible, but they do have a mining duration, right? - if (MovementHelper.getMiningDurationTicks(context, positionsToBreak[i], false) > 0) { - //can't break while falling - return COST_INF; - } - } - return WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[positionsToBreak.length - 1] + placeBucketCost + frontThree; + return result.cost; } @Override public MovementState updateState(MovementState state) { super.updateState(state); - switch (state.getStatus()) { - case WAITING: - state.setStatus(MovementStatus.RUNNING); - case RUNNING: - break; - default: - return state; + if (state.getStatus() != MovementStatus.RUNNING) { + return state; } BlockPos playerFeet = playerFeet(); Rotation targetRotation = null; if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) { - if (!player().inventory.hasItemStack(STACK_BUCKET_WATER) || world().provider.isNether()) { - state.setStatus(MovementStatus.UNREACHABLE); - return state; + if (!InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) || world().provider.isNether()) { + return state.setStatus(MovementStatus.UNREACHABLE); } if (player().posY - dest.getY() < mc.playerController.getBlockReachDistance()) { @@ -117,17 +86,23 @@ public class MovementFall extends Movement { } else { state.setTarget(new MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.getBlockPosCenter(dest)), false)); } - if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 // lilypads - || BlockStateInterface.isWater(dest))) { - if (BlockStateInterface.isWater(dest) && player().inventory.hasItemStack(STACK_BUCKET_EMPTY)) { - player().inventory.currentItem = player().inventory.getSlotFor(STACK_BUCKET_EMPTY); - if (player().motionY >= 0) { - return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); + if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 || BlockStateInterface.isWater(dest))) { // 0.094 because lilypads + if (BlockStateInterface.isWater(dest)) { + if (InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_EMPTY))) { + player().inventory.currentItem = player().inventory.getSlotFor(STACK_BUCKET_EMPTY); + if (player().motionY >= 0) { + return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); + } else { + return state; + } } else { - return state; + if (player().motionY >= 0) { + return state.setStatus(MovementStatus.SUCCESS); + } // don't else return state; we need to stay centered because this water might be flowing under the surface } + } else { + return state.setStatus(MovementStatus.SUCCESS); } - return state.setStatus(MovementStatus.SUCCESS); } Vec3d destCenter = Utils.getBlockPosCenter(dest); // we are moving to the 0.5 center not the edge (like if we were falling on a ladder) if (Math.abs(player().posX - destCenter.x) > 0.2 || Math.abs(player().posZ - destCenter.z) > 0.2) { @@ -136,15 +111,30 @@ public class MovementFall extends Movement { return state; } - private static BlockPos[] buildPositionsToBreak(BlockPos src, BlockPos dest) { - BlockPos[] toBreak; + private static BetterBlockPos[] buildPositionsToBreak(BetterBlockPos src, BetterBlockPos dest) { + BetterBlockPos[] toBreak; int diffX = src.getX() - dest.getX(); int diffZ = src.getZ() - dest.getZ(); int diffY = src.getY() - dest.getY(); - toBreak = new BlockPos[diffY + 2]; + toBreak = new BetterBlockPos[diffY + 2]; for (int i = 0; i < toBreak.length; i++) { - toBreak[i] = new BlockPos(src.getX() - diffX, src.getY() + 1 - i, src.getZ() - diffZ); + toBreak[i] = new BetterBlockPos(src.getX() - diffX, src.getY() + 1 - i, src.getZ() - diffZ); } return toBreak; } + + @Override + protected boolean prepared(MovementState state) { + if (state.getStatus() == MovementStatus.WAITING) { + return true; + } + // only break if one of the first three needs to be broken + // specifically ignore the last one which might be water + for (int i = 0; i < 4 && i < positionsToBreak.length; i++) { + if (!MovementHelper.canWalkThrough(positionsToBreak[i])) { + return super.prepared(state); + } + } + return true; + } } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java new file mode 100644 index 00000000..43391b01 --- /dev/null +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -0,0 +1,209 @@ +/* + * 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 . + */ + +package baritone.pathing.movement.movements; + +import baritone.Baritone; +import baritone.behavior.LookBehaviorUtils; +import baritone.pathing.movement.CalculationContext; +import baritone.pathing.movement.Movement; +import baritone.pathing.movement.MovementHelper; +import baritone.pathing.movement.MovementState; +import baritone.utils.BlockStateInterface; +import baritone.utils.InputOverrideHandler; +import baritone.utils.Utils; +import baritone.utils.pathing.BetterBlockPos; +import baritone.utils.pathing.MoveResult; +import net.minecraft.block.state.IBlockState; +import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + +import java.util.Objects; + +import static baritone.utils.pathing.MoveResult.IMPOSSIBLE; + +public class MovementParkour extends Movement { + + private static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN}; + private static final BetterBlockPos[] EMPTY = new BetterBlockPos[]{}; + + private final EnumFacing direction; + private final int dist; + + private MovementParkour(BetterBlockPos src, int dist, EnumFacing dir) { + super(src, src.offset(dir, dist), EMPTY); + this.direction = dir; + this.dist = dist; + } + + public static MovementParkour cost(CalculationContext context, BetterBlockPos src, EnumFacing direction) { + MoveResult res = cost(context, src.x, src.y, src.z, direction); + int dist = Math.abs(res.destX - src.x) + Math.abs(res.destZ - src.z); + return new MovementParkour(src, dist, direction); + } + + public static MoveResult cost(CalculationContext context, int x, int y, int z, EnumFacing dir) { + if (!Baritone.settings().allowParkour.get()) { + return IMPOSSIBLE; + } + IBlockState standingOn = BlockStateInterface.get(x, y - 1, z); + if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || MovementHelper.isBottomSlab(standingOn)) { + return IMPOSSIBLE; + } + int xDiff = dir.getXOffset(); + int zDiff = dir.getZOffset(); + IBlockState adj = BlockStateInterface.get(x + xDiff, y - 1, z + zDiff); + if (MovementHelper.avoidWalkingInto(adj.getBlock()) && adj.getBlock() != Blocks.WATER && adj.getBlock() != Blocks.FLOWING_WATER) { // magma sucks + return IMPOSSIBLE; + } + if (MovementHelper.canWalkOn(x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now) + return IMPOSSIBLE; + } + + if (!MovementHelper.fullyPassable(x + xDiff, y, z + zDiff)) { + return IMPOSSIBLE; + } + if (!MovementHelper.fullyPassable(x + xDiff, y + 1, z + zDiff)) { + return IMPOSSIBLE; + } + if (!MovementHelper.fullyPassable(x + xDiff, y + 2, z + zDiff)) { + return IMPOSSIBLE; + } + if (!MovementHelper.fullyPassable(x, y + 2, z)) { + return IMPOSSIBLE; + } + for (int i = 2; i <= (context.canSprint() ? 4 : 3); i++) { + // TODO perhaps dest.up(3) doesn't need to be fullyPassable, just canWalkThrough, possibly? + for (int y2 = 0; y2 < 4; y2++) { + if (!MovementHelper.fullyPassable(x + xDiff * i, y + y2, z + zDiff * i)) { + return IMPOSSIBLE; + } + } + if (MovementHelper.canWalkOn(x + xDiff * i, y - 1, z + zDiff * i)) { + return new MoveResult(x + xDiff * i, y, z + zDiff * i, costFromJumpDistance(i)); + } + } + if (!context.canSprint()) { + return IMPOSSIBLE; + } + if (!Baritone.settings().allowParkourPlace.get()) { + return IMPOSSIBLE; + } + int destX = x + 4 * xDiff; + int destZ = z + 4 * zDiff; + IBlockState toPlace = BlockStateInterface.get(destX, y - 1, destZ); + if (!context.hasThrowaway()) { + return IMPOSSIBLE; + } + if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y - 1, destZ, toPlace)) { + return IMPOSSIBLE; + } + for (int i = 0; i < 5; i++) { + int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset(); + int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getZOffset(); + if (againstX == x + xDiff * 3 && againstZ == z + zDiff * 3) { // we can't turn around that fast + continue; + } + if (MovementHelper.canPlaceAgainst(againstX, y - 1, againstZ)) { + return new MoveResult(destX, y, destZ, costFromJumpDistance(i) + context.placeBlockCost()); + } + } + return IMPOSSIBLE; + } + + private static double costFromJumpDistance(int dist) { + switch (dist) { + case 2: + return WALK_ONE_BLOCK_COST * 2; // IDK LOL + case 3: + return WALK_ONE_BLOCK_COST * 3; + case 4: + return SPRINT_ONE_BLOCK_COST * 4; + default: + throw new IllegalStateException("LOL"); + } + } + + + @Override + protected double calculateCost(CalculationContext context) { + MoveResult res = cost(context, src.x, src.y, src.z, direction); + if (res.destX != dest.x || res.destZ != dest.z) { + return COST_INF; + } + return res.cost; + } + + @Override + public MovementState updateState(MovementState state) { + super.updateState(state); + if (state.getStatus() != MovementState.MovementStatus.RUNNING) { + return state; + } + if (dist >= 4) { + state.setInput(InputOverrideHandler.Input.SPRINT, true); + } + MovementHelper.moveTowards(state, dest); + if (playerFeet().equals(dest)) { + if (player().posY - playerFeet().getY() < 0.01) { + state.setStatus(MovementState.MovementStatus.SUCCESS); + } + } else if (!playerFeet().equals(src)) { + if (playerFeet().equals(src.offset(direction)) || player().posY - playerFeet().getY() > 0.0001) { + + if (!MovementHelper.canWalkOn(dest.down())) { + BlockPos positionToPlace = dest.down(); + for (int i = 0; i < 5; i++) { + BlockPos against1 = positionToPlace.offset(HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i]); + if (against1.up().equals(src.offset(direction, 3))) { // we can't turn around that fast + continue; + } + if (MovementHelper.canPlaceAgainst(against1)) { + if (!MovementHelper.throwaway(true)) {//get ready to place a throwaway block + return state.setStatus(MovementState.MovementStatus.UNREACHABLE); + } + double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D; + double faceY = (dest.getY() + against1.getY()) * 0.5D; + double faceZ = (dest.getZ() + against1.getZ() + 1.0D) * 0.5D; + state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true)); + EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit; + + LookBehaviorUtils.getSelectedBlock().ifPresent(selectedBlock -> { + if (Objects.equals(selectedBlock, against1) && selectedBlock.offset(side).equals(dest.down())) { + state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); + } + }); + } + } + } + + state.setInput(InputOverrideHandler.Input.JUMP, true); + } else { + state.setInput(InputOverrideHandler.Input.SPRINT, false); + if (playerFeet().equals(src.offset(direction, -1))) { + MovementHelper.moveTowards(state, src); + } else { + MovementHelper.moveTowards(state, src.offset(direction, -1)); + } + } + } + return state; + } +} \ No newline at end of file diff --git a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java index d7ff3016..227a9162 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java @@ -2,39 +2,42 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.movement.movements; +import baritone.api.utils.Rotation; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementState; import baritone.utils.BlockStateInterface; import baritone.utils.InputOverrideHandler; -import baritone.utils.Rotation; import baritone.utils.Utils; +import baritone.utils.pathing.BetterBlockPos; import net.minecraft.block.*; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; +import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; public class MovementPillar extends Movement { private int numTicks = 0; - public MovementPillar(BlockPos start, BlockPos end) { - super(start, end, new BlockPos[]{start.up(2)}, start); + public MovementPillar(BetterBlockPos start, BetterBlockPos end) { + super(start, end, new BetterBlockPos[]{start.up(2)}, start); } @Override @@ -45,36 +48,58 @@ public class MovementPillar extends Movement { @Override protected double calculateCost(CalculationContext context) { - Block fromDown = BlockStateInterface.get(src).getBlock(); + return cost(context, src.x, src.y, src.z); + } + + public static double cost(CalculationContext context, int x, int y, int z) { + Block fromDown = BlockStateInterface.get(x, y, z).getBlock(); boolean ladder = fromDown instanceof BlockLadder || fromDown instanceof BlockVine; - Block fromDownDown = BlockStateInterface.get(src.down()).getBlock(); + IBlockState fromDownDown = BlockStateInterface.get(x, y - 1, z); if (!ladder) { - if (fromDownDown instanceof BlockLadder || fromDownDown instanceof BlockVine) { + if (fromDownDown.getBlock() instanceof BlockLadder || fromDownDown.getBlock() instanceof BlockVine) { return COST_INF; } + if (fromDownDown.getBlock() instanceof BlockSlab) { + if (!((BlockSlab) fromDownDown.getBlock()).isDouble() && fromDownDown.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM) { + return COST_INF; // can't pillar up from a bottom slab onto a non ladder + } + } } if (!context.hasThrowaway() && !ladder) { return COST_INF; } if (fromDown instanceof BlockVine) { - if (getAgainst(src) == null) { + if (!hasAgainst(x, y, z)) { return COST_INF; } } - double hardness = getTotalHardnessOfBlocksToBreak(context); + IBlockState toBreak = BlockStateInterface.get(x, y + 2, z); + Block toBreakBlock = toBreak.getBlock(); + if (toBreakBlock instanceof BlockFenceGate) { + return COST_INF; + } + Block srcUp = null; + if (BlockStateInterface.isWater(toBreakBlock) && BlockStateInterface.isWater(fromDown)) { + srcUp = BlockStateInterface.get(x, y + 1, z).getBlock(); + if (BlockStateInterface.isWater(srcUp)) { + return LADDER_UP_ONE_COST; + } + } + double hardness = MovementHelper.getMiningDurationTicks(context, x, y + 2, z, toBreak, true); if (hardness >= COST_INF) { return COST_INF; } if (hardness != 0) { - Block tmp = BlockStateInterface.get(src.up(2)).getBlock(); - if (tmp instanceof BlockLadder || tmp instanceof BlockVine) { + if (toBreakBlock instanceof BlockLadder || toBreakBlock instanceof BlockVine) { hardness = 0; // we won't actually need to break the ladder / vine because we're going to use it } else { - BlockPos chkPos = src.up(3); - IBlockState check = BlockStateInterface.get(chkPos); + IBlockState check = BlockStateInterface.get(x, y + 3, z); if (check.getBlock() instanceof BlockFalling) { // see MovementAscend's identical check for breaking a falling block above our head - if (!(tmp instanceof BlockFalling) || !(BlockStateInterface.get(src.up(1)).getBlock() instanceof BlockFalling)) { + if (srcUp == null) { + srcUp = BlockStateInterface.get(x, y + 1, z).getBlock(); + } + if (!(toBreakBlock instanceof BlockFalling) || !(srcUp instanceof BlockFalling)) { return COST_INF; } } @@ -87,16 +112,23 @@ public class MovementPillar extends Movement { //} } } - if (fromDown instanceof BlockLiquid || fromDownDown instanceof BlockLiquid) {//can't pillar on water or in water + if (fromDown instanceof BlockLiquid || fromDownDown.getBlock() instanceof BlockLiquid) {//can't pillar on water or in water return COST_INF; } if (ladder) { - return LADDER_UP_ONE_COST + hardness; + return LADDER_UP_ONE_COST + hardness * 5; } else { return JUMP_ONE_BLOCK_COST + context.placeBlockCost() + hardness; } } + public static boolean hasAgainst(int x, int y, int z) { + return BlockStateInterface.get(x + 1, y, z).isBlockNormalCube() || + BlockStateInterface.get(x - 1, y, z).isBlockNormalCube() || + BlockStateInterface.get(x, y, z + 1).isBlockNormalCube() || + BlockStateInterface.get(x, y, z - 1).isBlockNormalCube(); + } + public static BlockPos getAgainst(BlockPos vine) { if (BlockStateInterface.get(vine.north()).isBlockNormalCube()) { return vine.north(); @@ -116,16 +148,23 @@ public class MovementPillar extends Movement { @Override public MovementState updateState(MovementState state) { super.updateState(state); - switch (state.getStatus()) { - case WAITING: - state.setStatus(MovementState.MovementStatus.RUNNING); - case RUNNING: - break; - default: - return state; + if (state.getStatus() != MovementState.MovementStatus.RUNNING) { + return state; } IBlockState fromDown = BlockStateInterface.get(src); + if (BlockStateInterface.isWater(fromDown.getBlock()) && BlockStateInterface.isWater(dest)) { + // stay centered while swimming up a water column + state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.getBlockPosCenter(dest)), false)); + Vec3d destCenter = Utils.getBlockPosCenter(dest); + if (Math.abs(player().posX - destCenter.x) > 0.2 || Math.abs(player().posZ - destCenter.z) > 0.2) { + state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true); + } + if (playerFeet().equals(dest)) { + return state.setStatus(MovementState.MovementStatus.SUCCESS); + } + return state; + } boolean ladder = fromDown.getBlock() instanceof BlockLadder || fromDown.getBlock() instanceof BlockVine; boolean vine = fromDown.getBlock() instanceof BlockVine; if (!ladder) { @@ -138,13 +177,16 @@ public class MovementPillar extends Movement { if (ladder) { BlockPos against = vine ? getAgainst(src) : src.offset(fromDown.getValue(BlockLadder.FACING).getOpposite()); if (against == null) { - displayChatMessageRaw("Unable to climb vines"); + logDebug("Unable to climb vines"); return state.setStatus(MovementState.MovementStatus.UNREACHABLE); } - if (playerFeet().equals(against.up()) || playerFeet().equals(dest)) + if (playerFeet().equals(against.up()) || playerFeet().equals(dest)) { return state.setStatus(MovementState.MovementStatus.SUCCESS); - + } + if (MovementHelper.isBottomSlab(src.down())) { + state.setInput(InputOverrideHandler.Input.JUMP, true); + } /* if (thePlayer.getPosition0().getX() != from.getX() || thePlayer.getPosition0().getZ() != from.getZ()) { Baritone.moveTowardsBlock(from); @@ -156,8 +198,7 @@ public class MovementPillar extends Movement { } else { // Get ready to place a throwaway block if (!MovementHelper.throwaway(true)) { - state.setStatus(MovementState.MovementStatus.UNREACHABLE); - return state; + return state.setStatus(MovementState.MovementStatus.UNREACHABLE); } numTicks++; @@ -166,7 +207,7 @@ public class MovementPillar extends Movement { state.setInput(InputOverrideHandler.Input.SNEAK, true); // Otherwise jump - if (numTicks > 40) { + if (numTicks > 20) { double diffX = player().posX - (dest.getX() + 0.5); double diffZ = player().posZ - (dest.getZ() + 0.5); double dist = Math.sqrt(diffX * diffX + diffZ * diffZ); @@ -197,4 +238,18 @@ public class MovementPillar extends Movement { return state; } + + @Override + protected boolean prepared(MovementState state) { + if (playerFeet().equals(src) || playerFeet().equals(src.down())) { + Block block = BlockStateInterface.getBlock(src.down()); + if (block == Blocks.LADDER || block == Blocks.VINE) { + state.setInput(InputOverrideHandler.Input.SNEAK, true); + } + } + if (BlockStateInterface.isWater(dest.up())) { + return true; + } + return super.prepared(state); + } } \ No newline at end of file diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java index a959455b..a16a50a1 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java @@ -2,22 +2,24 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.movement.movements; -import baritone.behavior.impl.LookBehaviorUtils; +import baritone.Baritone; +import baritone.api.utils.Rotation; +import baritone.behavior.LookBehaviorUtils; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; @@ -25,6 +27,7 @@ import baritone.pathing.movement.MovementState; import baritone.utils.BlockStateInterface; import baritone.utils.InputOverrideHandler; import baritone.utils.Utils; +import baritone.utils.pathing.BetterBlockPos; import net.minecraft.block.*; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -42,8 +45,8 @@ public class MovementTraverse extends Movement { */ private boolean wasTheBridgeBlockAlwaysThere = true; - public MovementTraverse(BlockPos from, BlockPos to) { - super(from, to, new BlockPos[]{to.up(), to}, to.down()); + public MovementTraverse(BetterBlockPos from, BetterBlockPos to) { + super(from, to, new BetterBlockPos[]{to.up(), to}, to.down()); } @Override @@ -54,26 +57,31 @@ public class MovementTraverse extends Movement { @Override protected double calculateCost(CalculationContext context) { - IBlockState pb0 = BlockStateInterface.get(positionsToBreak[0]); - IBlockState pb1 = BlockStateInterface.get(positionsToBreak[1]); - IBlockState destOn = BlockStateInterface.get(positionToPlace); - if (MovementHelper.canWalkOn(positionToPlace, destOn)) {//this is a walk, not a bridge + return cost(context, src.x, src.y, src.z, dest.x, dest.z); + } + + public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { + IBlockState pb0 = BlockStateInterface.get(destX, y + 1, destZ); + IBlockState pb1 = BlockStateInterface.get(destX, y, destZ); + IBlockState destOn = BlockStateInterface.get(destX, y - 1, destZ); + Block srcDown = BlockStateInterface.getBlock(x, y - 1, z); + if (MovementHelper.canWalkOn(destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge double WC = WALK_ONE_BLOCK_COST; if (BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock())) { WC = WALK_ONE_IN_WATER_COST; } else { - if (Blocks.SOUL_SAND.equals(destOn.getBlock())) { + if (destOn.getBlock() == Blocks.SOUL_SAND) { WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; } - if (Blocks.SOUL_SAND.equals(BlockStateInterface.get(src.down()).getBlock())) { + if (srcDown == Blocks.SOUL_SAND) { WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; } } - double hardness1 = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0], pb0, true); + double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true); if (hardness1 >= COST_INF) { return COST_INF; } - double hardness2 = MovementHelper.getMiningDurationTicks(context, positionsToBreak[1], pb1, false); + double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb1, false); if (hardness1 == 0 && hardness2 == 0) { if (WC == WALK_ONE_BLOCK_COST && context.canSprint()) { // If there's nothing in the way, and this isn't water or soul sand, and we aren't sneak placing @@ -82,13 +90,16 @@ public class MovementTraverse extends Movement { } return WC; } + if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) { + hardness1 *= 5; + hardness2 *= 5; + } return WC + hardness1 + hardness2; } else {//this is a bridge, so we need to place a block - Block srcDown = BlockStateInterface.get(src.down()).getBlock(); - if (srcDown instanceof BlockLadder || srcDown instanceof BlockVine) { + if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) { return COST_INF; } - if (destOn.getBlock().equals(Blocks.AIR) || MovementHelper.isReplacable(positionToPlace, destOn)) { + if (destOn.getBlock().equals(Blocks.AIR) || MovementHelper.isReplacable(destX, y - 1, destZ, destOn)) { boolean throughWater = BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock()); if (BlockStateInterface.isWater(destOn.getBlock()) && throughWater) { return COST_INF; @@ -96,22 +107,31 @@ public class MovementTraverse extends Movement { if (!context.hasThrowaway()) { return COST_INF; } + double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb0, false); + if (hardness1 >= COST_INF) { + return COST_INF; + } + double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb1, true); + double WC = throughWater ? WALK_ONE_IN_WATER_COST : WALK_ONE_BLOCK_COST; for (int i = 0; i < 4; i++) { - BlockPos against1 = dest.offset(HORIZONTALS[i]); - if (against1.equals(src)) { + int againstX = destX + HORIZONTALS[i].getXOffset(); + int againstZ = destZ + HORIZONTALS[i].getZOffset(); + if (againstX == x && againstZ == z) { continue; } - against1 = against1.down(); - if (MovementHelper.canPlaceAgainst(against1)) { - return WC + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context); + if (MovementHelper.canPlaceAgainst(againstX, y - 1, againstZ)) { + return WC + context.placeBlockCost() + hardness1 + hardness2; } } - if (Blocks.SOUL_SAND.equals(srcDown)) { - return COST_INF; // can't sneak and backplace against soul sand =/ + if (srcDown == Blocks.SOUL_SAND || (srcDown instanceof BlockSlab && !((BlockSlab) srcDown).isDouble())) { + return COST_INF; // can't sneak and backplace against soul sand or half slabs =/ + } + if (srcDown == Blocks.FLOWING_WATER || srcDown == Blocks.WATER) { + return COST_INF; // this is obviously impossible } WC = WC * SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST;//since we are placing, we are sneaking - return WC + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context); + return WC + context.placeBlockCost() + hardness1 + hardness2; } return COST_INF; // Out.log("Can't walk on " + Baritone.get(positionsToPlace[0]).getBlock()); @@ -121,15 +141,40 @@ public class MovementTraverse extends Movement { @Override public MovementState updateState(MovementState state) { super.updateState(state); - switch (state.getStatus()) { - case WAITING: - state.setStatus(MovementState.MovementStatus.RUNNING); - case RUNNING: - break; - default: + if (state.getStatus() != MovementState.MovementStatus.RUNNING) { + // if the setting is enabled + if (!Baritone.settings().walkWhileBreaking.get()) { return state; + } + // and if we're prepping (aka mining the block in front) + if (state.getStatus() != MovementState.MovementStatus.PREPPING) { + return state; + } + // and if it's fine to walk into the blocks in front + if (MovementHelper.avoidWalkingInto(BlockStateInterface.get(positionsToBreak[0]).getBlock())) { + return state; + } + if (MovementHelper.avoidWalkingInto(BlockStateInterface.get(positionsToBreak[1]).getBlock())) { + return state; + } + // and we aren't already pressed up against the block + double dist = Math.max(Math.abs(player().posX - (dest.getX() + 0.5D)), Math.abs(player().posZ - (dest.getZ() + 0.5D))); + if (dist < 0.83) { + return state; + } + + // combine the yaw to the center of the destination, and the pitch to the specific block we're trying to break + // it's safe to do this since the two blocks we break (in a traverse) are right on top of each other and so will have the same yaw + float yawToDest = Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(dest, world())).getYaw(); + float pitchToBreak = state.getTarget().getRotation().get().getPitch(); + + state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true)); + return state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true); } + //sneak may have been set to true in the PREPPING state while mining an adjacent block + state.setInput(InputOverrideHandler.Input.SNEAK, false); + Block fd = BlockStateInterface.get(src.down()).getBlock(); boolean ladder = fd instanceof BlockLadder || fd instanceof BlockVine; IBlockState pb0 = BlockStateInterface.get(positionsToBreak[0]); @@ -145,9 +190,8 @@ public class MovementTraverse extends Movement { } if (isDoorActuallyBlockingUs) { if (!(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) { - state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(positionsToBreak[0], world())), true)); - state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); - return state; + return state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(positionsToBreak[0], world())), true)) + .setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); } } } @@ -161,16 +205,15 @@ public class MovementTraverse extends Movement { } if (blocked != null) { - state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(blocked, world())), true)); - state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); - return state; + return state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(blocked, world())), true)) + .setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); } } boolean isTheBridgeBlockThere = MovementHelper.canWalkOn(positionToPlace) || ladder; BlockPos whereAmI = playerFeet(); if (whereAmI.getY() != dest.getY() && !ladder) { - displayChatMessageRaw("Wrong Y coordinate"); + logDebug("Wrong Y coordinate"); if (whereAmI.getY() < dest.getY()) { state.setInput(InputOverrideHandler.Input.JUMP, true); } @@ -179,14 +222,13 @@ public class MovementTraverse extends Movement { if (isTheBridgeBlockThere) { if (playerFeet().equals(dest)) { - state.setStatus(MovementState.MovementStatus.SUCCESS); - return state; + return state.setStatus(MovementState.MovementStatus.SUCCESS); } if (wasTheBridgeBlockAlwaysThere && !BlockStateInterface.isLiquid(playerFeet())) { state.setInput(InputOverrideHandler.Input.SPRINT, true); } Block destDown = BlockStateInterface.get(dest.down()).getBlock(); - if (ladder && (destDown instanceof BlockVine || destDown instanceof BlockLadder)) { + if (whereAmI.getY() != dest.getY() && ladder && (destDown instanceof BlockVine || destDown instanceof BlockLadder)) { new MovementPillar(dest.down(), dest).updateState(state); // i'm sorry return state; } @@ -202,17 +244,19 @@ public class MovementTraverse extends Movement { against1 = against1.down(); if (MovementHelper.canPlaceAgainst(against1)) { if (!MovementHelper.throwaway(true)) { // get ready to place a throwaway block - displayChatMessageRaw("bb pls get me some blocks. dirt or cobble"); + logDebug("bb pls get me some blocks. dirt or cobble"); return state.setStatus(MovementState.MovementStatus.UNREACHABLE); } - state.setInput(InputOverrideHandler.Input.SNEAK, true); - if (BlockStateInterface.get(playerFeet().down()).getBlock().equals(Blocks.SOUL_SAND)) { // see issue #118 + if (!Baritone.settings().assumeSafeWalk.get()) { + state.setInput(InputOverrideHandler.Input.SNEAK, true); + } + Block standingOn = BlockStateInterface.get(playerFeet().down()).getBlock(); + if (standingOn.equals(Blocks.SOUL_SAND) || standingOn instanceof BlockSlab) { // see issue #118 double dist = Math.max(Math.abs(dest.getX() + 0.5 - player().posX), Math.abs(dest.getZ() + 0.5 - player().posZ)); if (dist < 0.85) { // 0.5 + 0.3 + epsilon MovementHelper.moveTowards(state, dest); - state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, false); - state.setInput(InputOverrideHandler.Input.MOVE_BACK, true); - return state; + return state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, false) + .setInput(InputOverrideHandler.Input.MOVE_BACK, true); } } state.setInput(InputOverrideHandler.Input.MOVE_BACK, false); @@ -225,20 +269,21 @@ public class MovementTraverse extends Movement { if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), against1) && Minecraft.getMinecraft().player.isSneaking()) { if (LookBehaviorUtils.getSelectedBlock().get().offset(side).equals(positionToPlace)) { return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); - } else { - // Out.gui("Wrong. " + side + " " + LookBehaviorUtils.getSelectedBlock().get().offset(side) + " " + positionsToPlace[0], Out.Mode.Debug); } + // wrong side? } System.out.println("Trying to look at " + against1 + ", actually looking at" + LookBehaviorUtils.getSelectedBlock()); return state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true); } } - state.setInput(InputOverrideHandler.Input.SNEAK, true); + if (!Baritone.settings().assumeSafeWalk.get()) { + state.setInput(InputOverrideHandler.Input.SNEAK, true); + } if (whereAmI.equals(dest)) { // If we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of // Out.log(from + " " + to + " " + faceX + "," + faceY + "," + faceZ + " " + whereAmI); if (!MovementHelper.throwaway(true)) {// get ready to place a throwaway block - displayChatMessageRaw("bb pls get me some blocks. dirt or cobble"); + logDebug("bb pls get me some blocks. dirt or cobble"); return state.setStatus(MovementState.MovementStatus.UNREACHABLE); } double faceX = (dest.getX() + src.getX() + 1.0D) * 0.5D; @@ -251,8 +296,7 @@ public class MovementTraverse extends Movement { state.setInput(InputOverrideHandler.Input.MOVE_BACK, true); state.setInput(InputOverrideHandler.Input.SNEAK, true); if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), goalLook)) { - state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); // wait to right click until we are able to place - return state; + return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); // wait to right click until we are able to place } // Out.log("Trying to look at " + goalLook + ", actually looking at" + Baritone.whatAreYouLookingAt()); return state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true); @@ -263,4 +307,15 @@ public class MovementTraverse extends Movement { } } } + + @Override + protected boolean prepared(MovementState state) { + if (playerFeet().equals(src) || playerFeet().equals(src.down())) { + Block block = BlockStateInterface.getBlock(src.down()); + if (block == Blocks.LADDER || block == Blocks.VINE) { + state.setInput(InputOverrideHandler.Input.SNEAK, true); + } + } + return super.prepared(state); + } } diff --git a/src/main/java/baritone/pathing/path/CutoffPath.java b/src/main/java/baritone/pathing/path/CutoffPath.java index 51618918..e517452e 100644 --- a/src/main/java/baritone/pathing/path/CutoffPath.java +++ b/src/main/java/baritone/pathing/path/CutoffPath.java @@ -2,21 +2,22 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.path; +import baritone.api.pathing.goals.Goal; import baritone.pathing.movement.Movement; import baritone.utils.pathing.BetterBlockPos; @@ -25,16 +26,24 @@ import java.util.List; public class CutoffPath implements IPath { - final List path; + private final List path; - final List movements; + private final List movements; private final int numNodes; + private final Goal goal; + public CutoffPath(IPath prev, int lastPositionToInclude) { path = prev.positions().subList(0, lastPositionToInclude + 1); movements = prev.movements().subList(0, lastPositionToInclude + 1); numNodes = prev.getNumNodesConsidered(); + goal = prev.getGoal(); + } + + @Override + public Goal getGoal() { + return goal; } @Override diff --git a/src/main/java/baritone/pathing/path/IPath.java b/src/main/java/baritone/pathing/path/IPath.java index 39c17993..0701abf6 100644 --- a/src/main/java/baritone/pathing/path/IPath.java +++ b/src/main/java/baritone/pathing/path/IPath.java @@ -2,23 +2,23 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.path; import baritone.Baritone; -import baritone.pathing.goals.Goal; +import baritone.api.pathing.goals.Goal; import baritone.pathing.movement.Movement; import baritone.utils.Helper; import baritone.utils.Utils; @@ -49,6 +49,12 @@ public interface IPath extends Helper { */ List positions(); + /** + * This path is actually going to be executed in the world. Do whatever additional processing is required. + * (as opposed to Path objects that are just constructed every frame for rendering) + */ + default void postprocess() {} + /** * Number of positions in this path * @@ -59,37 +65,17 @@ public interface IPath extends Helper { } /** - * What's the next step + * What goal was this path calculated towards? * - * @param currentPosition the current position * @return */ - default Movement subsequentMovement(BlockPos currentPosition) { - List pos = positions(); - List movements = movements(); - for (int i = 0; i < pos.size(); i++) { - if (currentPosition.equals(pos.get(i))) { - return movements.get(i); - } - } - throw new UnsupportedOperationException(currentPosition + " not in path"); - } + Goal getGoal(); - /** - * Determines whether or not a position is within this path. - * - * @param pos The position to check - * @return Whether or not the specified position is in this class - */ - default boolean isInPath(BlockPos pos) { - return positions().contains(pos); - } - - default Tuple closestPathPos(double x, double y, double z) { + default Tuple closestPathPos() { double best = -1; BlockPos bestPos = null; for (BlockPos pos : positions()) { - double dist = Utils.distanceToCenter(pos, x, y, z); + double dist = Utils.playerDistanceToCenter(pos); if (dist < best || best == -1) { best = dist; bestPos = pos; @@ -128,12 +114,12 @@ public interface IPath extends Helper { for (int i = 0; i < positions().size(); i++) { BlockPos pos = positions().get(i); if (Minecraft.getMinecraft().world.getChunk(pos) instanceof EmptyChunk) { - displayChatMessageRaw("Cutting off path at edge of loaded chunks"); - displayChatMessageRaw("Length decreased by " + (positions().size() - i - 1)); + logDebug("Cutting off path at edge of loaded chunks"); + logDebug("Length decreased by " + (positions().size() - i - 1)); return new CutoffPath(this, i); } } - displayChatMessageRaw("Path ends within loaded chunks"); + logDebug("Path ends within loaded chunks"); return this; } @@ -146,7 +132,7 @@ public interface IPath extends Helper { } double factor = Baritone.settings().pathCutoffFactor.get(); int newLength = (int) (length() * factor); - //displayChatMessageRaw("Static cutoff " + length() + " to " + newLength); + logDebug("Static cutoff " + length() + " to " + newLength); return new CutoffPath(this, newLength); } } diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java index 88ca6e30..e8e74c7d 100644 --- a/src/main/java/baritone/pathing/path/PathExecutor.java +++ b/src/main/java/baritone/pathing/path/PathExecutor.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -19,17 +19,13 @@ package baritone.pathing.path; import baritone.Baritone; import baritone.api.event.events.TickEvent; -import baritone.pathing.movement.ActionCosts; -import baritone.pathing.movement.Movement; -import baritone.pathing.movement.MovementHelper; -import baritone.pathing.movement.MovementState; -import baritone.pathing.movement.movements.MovementDescend; -import baritone.pathing.movement.movements.MovementDiagonal; -import baritone.pathing.movement.movements.MovementFall; -import baritone.pathing.movement.movements.MovementTraverse; +import baritone.api.pathing.movement.ActionCosts; +import baritone.pathing.movement.*; +import baritone.pathing.movement.movements.*; import baritone.utils.BlockStateInterface; import baritone.utils.Helper; -import net.minecraft.client.entity.EntityPlayerSP; +import baritone.utils.Utils; +import baritone.utils.pathing.BetterBlockPos; import net.minecraft.init.Blocks; import net.minecraft.util.Tuple; import net.minecraft.util.math.BlockPos; @@ -49,12 +45,21 @@ import static baritone.pathing.movement.MovementState.MovementStatus.*; public class PathExecutor implements Helper { private static final double MAX_MAX_DIST_FROM_PATH = 3; private static final double MAX_DIST_FROM_PATH = 2; - private static final double MAX_TICKS_AWAY = 200; // ten seconds. ok to decrease this, but it must be at least 110, see issue #102 + + /** + * Default value is equal to 10 seconds. It's find to decrease it, but it must be at least 5.5s (110 ticks). + * For more information, see issue #102. + * + * @see Issue #102 + * @see Anime + */ + private static final double MAX_TICKS_AWAY = 200; + private final IPath path; private int pathPosition; private int ticksAway; private int ticksOnCurrent; - private Double currentMovementInitialCostEstimate; + private Double currentMovementOriginalCostEstimate; private Integer costEstimateIndex; private boolean failed; private boolean recalcBP = true; @@ -78,72 +83,66 @@ public class PathExecutor implements Helper { if (event.getType() == TickEvent.Type.OUT) { throw new IllegalStateException(); } - if (pathPosition >= path.length()) { - //stop bugging me, I'm done - //TODO Baritone.INSTANCE.behaviors.remove(this) - return true; - } - BlockPos whereShouldIBe = path.positions().get(pathPosition); - EntityPlayerSP thePlayer = mc.player; - BlockPos whereAmI = playerFeet(); if (pathPosition == path.length() - 1) { pathPosition++; - return true; } + if (pathPosition >= path.length()) { + return true; // stop bugging me, I'm done + } + BetterBlockPos whereShouldIBe = path.positions().get(pathPosition); + BetterBlockPos whereAmI = playerFeet(); if (!whereShouldIBe.equals(whereAmI)) { + + if (pathPosition == 0 && whereAmI.equals(whereShouldIBe.up()) && Math.abs(player().motionY) < 0.1 && !(path.movements().get(0) instanceof MovementAscend) && !(path.movements().get(0) instanceof MovementPillar)) { + // avoid the Wrong Y coordinate bug + // TODO add a timer here + new MovementDownward(whereAmI, whereShouldIBe).update(); + return false; + } + //System.out.println("Should be at " + whereShouldIBe + " actually am at " + whereAmI); if (!Blocks.AIR.equals(BlockStateInterface.getBlock(whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip - for (int i = 0; i < pathPosition - 2 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks + for (int i = 0; i < pathPosition - 1 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks if (whereAmI.equals(path.positions().get(i))) { - displayChatMessageRaw("Skipping back " + (pathPosition - i) + " steps, to " + i); + logDebug("Skipping back " + (pathPosition - i) + " steps, to " + i); int previousPos = pathPosition; pathPosition = Math.max(i - 1, 0); // previous step might not actually be done for (int j = pathPosition; j <= previousPos; j++) { path.movements().get(j).reset(); } - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); + clearKeys(); return false; } } for (int i = pathPosition + 2; i < path.length(); i++) { //dont check pathPosition+1. the movement tells us when it's done (e.g. sneak placing) if (whereAmI.equals(path.positions().get(i))) { if (i - pathPosition > 2) { - displayChatMessageRaw("Skipping forward " + (i - pathPosition) + " steps, to " + i); + logDebug("Skipping forward " + (i - pathPosition) + " steps, to " + i); } System.out.println("Double skip sundae"); pathPosition = i - 1; - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); + clearKeys(); return false; } } } } - Tuple status = path.closestPathPos(thePlayer.posX, thePlayer.posY, thePlayer.posZ); - double distanceFromPath = status.getFirst(); - if (distanceFromPath > MAX_DIST_FROM_PATH) { + Tuple status = path.closestPathPos(); + if (possiblyOffPath(status, MAX_DIST_FROM_PATH)) { ticksAway++; - System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + distanceFromPath + ". Threshold: " + MAX_DIST_FROM_PATH); + System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.getFirst() + ". Threshold: " + MAX_DIST_FROM_PATH); if (ticksAway > MAX_TICKS_AWAY) { - displayChatMessageRaw("Too far away from path for too long, cancelling path"); - System.out.println("Too many ticks"); - pathPosition = path.length() + 3; - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); - failed = true; + logDebug("Too far away from path for too long, cancelling path"); + cancel(); return false; } } else { ticksAway = 0; } - if (distanceFromPath > MAX_MAX_DIST_FROM_PATH) { - if (!(path.movements().get(pathPosition) instanceof MovementFall)) { // might be midair - if (pathPosition == 0 || !(path.movements().get(pathPosition - 1) instanceof MovementFall)) { // might have overshot the landing - displayChatMessageRaw("too far from path"); - pathPosition = path.length() + 3; - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); - failed = true; - return false; - } - } + if (possiblyOffPath(status, MAX_MAX_DIST_FROM_PATH)) { // ok, stop right away, we're way too far. + logDebug("too far from path"); + cancel(); + return false; } //this commented block is literally cursed. /*Out.log(actions.get(pathPosition)); @@ -179,23 +178,24 @@ public class PathExecutor implements Helper { }*/ long start = System.nanoTime() / 1000000L; for (int i = pathPosition - 10; i < pathPosition + 10; i++) { - if (i >= 0 && i < path.movements().size()) { - Movement m = path.movements().get(i); - HashSet prevBreak = new HashSet<>(m.toBreak()); - HashSet prevPlace = new HashSet<>(m.toPlace()); - HashSet prevWalkInto = new HashSet<>(m.toWalkInto()); - m.toBreakCached = null; - m.toPlaceCached = null; - m.toWalkIntoCached = null; - if (!prevBreak.equals(new HashSet<>(m.toBreak()))) { - recalcBP = true; - } - if (!prevPlace.equals(new HashSet<>(m.toPlace()))) { - recalcBP = true; - } - if (!prevWalkInto.equals(new HashSet<>(m.toWalkInto()))) { - recalcBP = true; - } + if (i < 0 || i >= path.movements().size()) { + continue; + } + Movement m = path.movements().get(i); + HashSet prevBreak = new HashSet<>(m.toBreak()); + HashSet prevPlace = new HashSet<>(m.toPlace()); + HashSet prevWalkInto = new HashSet<>(m.toWalkInto()); + m.toBreakCached = null; + m.toPlaceCached = null; + m.toWalkIntoCached = null; + if (!prevBreak.equals(new HashSet<>(m.toBreak()))) { + recalcBP = true; + } + if (!prevPlace.equals(new HashSet<>(m.toPlace()))) { + recalcBP = true; + } + if (!prevWalkInto.equals(new HashSet<>(m.toWalkInto()))) { + recalcBP = true; } } if (recalcBP) { @@ -214,118 +214,155 @@ public class PathExecutor implements Helper { } long end = System.nanoTime() / 1000000L; if (end - start > 0) { - //displayChatMessageRaw("Recalculating break and place took " + (end - start) + "ms"); + System.out.println("Recalculating break and place took " + (end - start) + "ms"); } Movement movement = path.movements().get(pathPosition); if (costEstimateIndex == null || costEstimateIndex != pathPosition) { costEstimateIndex = pathPosition; // do this only once, when the movement starts, and deliberately get the cost as cached when this path was calculated, not the cost as it is right now - currentMovementInitialCostEstimate = movement.getCost(null); + currentMovementOriginalCostEstimate = movement.getCost(null); for (int i = 1; i < Baritone.settings().costVerificationLookahead.get() && pathPosition + i < path.length() - 1; i++) { if (path.movements().get(pathPosition + i).calculateCostWithoutCaching() >= ActionCosts.COST_INF) { - displayChatMessageRaw("Something has changed in the world and a future movement has become impossible. Cancelling."); - pathPosition = path.length() + 3; - failed = true; - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); + logDebug("Something has changed in the world and a future movement has become impossible. Cancelling."); + cancel(); return true; } } } double currentCost = movement.recalculateCost(); if (currentCost >= ActionCosts.COST_INF) { - displayChatMessageRaw("Something has changed in the world and this movement has become impossible. Cancelling."); - pathPosition = path.length() + 3; - failed = true; - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); + logDebug("Something has changed in the world and this movement has become impossible. Cancelling."); + cancel(); + return true; + } + if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.get()) { + logDebug("Original cost " + currentMovementOriginalCostEstimate + " current cost " + currentCost + ". Cancelling."); + cancel(); return true; } MovementState.MovementStatus movementStatus = movement.update(); if (movementStatus == UNREACHABLE || movementStatus == FAILED) { - displayChatMessageRaw("Movement returns status " + movementStatus); - pathPosition = path.length() + 3; - failed = true; - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); + logDebug("Movement returns status " + movementStatus); + cancel(); return true; } if (movementStatus == SUCCESS) { //System.out.println("Movement done, next path"); pathPosition++; ticksOnCurrent = 0; - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); + clearKeys(); onTick(event); return true; } else { sprintIfRequested(); ticksOnCurrent++; - if (ticksOnCurrent > currentMovementInitialCostEstimate + Baritone.settings().movementTimeoutTicks.get()) { - // only fail if the total time has exceeded the initial estimate + if (ticksOnCurrent > currentMovementOriginalCostEstimate + Baritone.settings().movementTimeoutTicks.get()) { + // only cancel if the total time has exceeded the initial estimate // as you break the blocks required, the remaining cost goes down, to the point where // ticksOnCurrent is greater than recalculateCost + 100 // this is why we cache cost at the beginning, and don't recalculate for this comparison every tick - displayChatMessageRaw("This movement has taken too long (" + ticksOnCurrent + " ticks, expected " + currentMovementInitialCostEstimate + "). Cancelling."); - movement.cancel(); - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); - pathPosition = path.length() + 3; - failed = true; + logDebug("This movement has taken too long (" + ticksOnCurrent + " ticks, expected " + currentMovementOriginalCostEstimate + "). Cancelling."); + cancel(); return true; } } return false; // movement is in progress } + private boolean possiblyOffPath(Tuple status, double leniency) { + double distanceFromPath = status.getFirst(); + if (distanceFromPath > leniency) { + // when we're midair in the middle of a fall, we're very far from both the beginning and the end, but we aren't actually off path + if (path.movements().get(pathPosition) instanceof MovementFall) { + BlockPos fallDest = path.positions().get(pathPosition + 1); // .get(pathPosition) is the block we fell off of + if (Utils.playerFlatDistanceToCenter(fallDest) < leniency) { // ignore Y by using flat distance + return false; + } + return true; + } else { + return true; + } + } else { + return false; + } + } + private void sprintIfRequested() { - if (!Baritone.settings().allowSprint.get()) { + + // first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint + if (!new CalculationContext().canSprint()) { player().setSprinting(false); return; } + + // if the movement requested sprinting, then we're done if (Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown(mc.gameSettings.keyBindSprint)) { if (!player().isSprinting()) { player().setSprinting(true); } return; } - Movement movement = path.movements().get(pathPosition); - if (movement instanceof MovementDescend && pathPosition < path.length() - 2) { + + // however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it + Movement current = path.movements().get(pathPosition); + if (current instanceof MovementDescend && pathPosition < path.length() - 2) { + + // (dest - src) + dest is offset 1 more in the same direction + // so it's the block we'd need to worry about running into if we decide to sprint straight through this descend + + BlockPos into = current.getDest().subtract(current.getSrc().down()).add(current.getDest()); + for (int y = 0; y <= 2; y++) { // we could hit any of the three blocks + if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(into.up(y)))) { + logDebug("Sprinting would be unsafe"); + player().setSprinting(false); + return; + } + } + Movement next = path.movements().get(pathPosition + 1); - if (next instanceof MovementDescend) { - if (next.getDirection().equals(movement.getDirection())) { - if (playerFeet().equals(movement.getDest())) { - pathPosition++; - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); - } - if (!player().isSprinting()) { - player().setSprinting(true); - } - return; - } - } - if (next instanceof MovementTraverse) { - if (next.getDirection().down().equals(movement.getDirection()) && MovementHelper.canWalkOn(next.getDest().down())) { - if (playerFeet().equals(movement.getDest())) { - pathPosition++; - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); - } - if (!player().isSprinting()) { - player().setSprinting(true); - } - return; - } - } - if (next instanceof MovementDiagonal && Baritone.settings().allowOvershootDiagonalDescend.get()) { - if (playerFeet().equals(movement.getDest())) { + if (canSprintInto(current, next)) { + if (playerFeet().equals(current.getDest())) { pathPosition++; - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); + clearKeys(); } if (!player().isSprinting()) { player().setSprinting(true); } return; } - //displayChatMessageRaw("Turning off sprinting " + movement + " " + next + " " + movement.getDirection() + " " + next.getDirection().down() + " " + next.getDirection().down().equals(movement.getDirection())); + //logDebug("Turning off sprinting " + movement + " " + next + " " + movement.getDirection() + " " + next.getDirection().down() + " " + next.getDirection().down().equals(movement.getDirection())); } player().setSprinting(false); } + private static boolean canSprintInto(Movement current, Movement next) { + if (next instanceof MovementDescend) { + if (next.getDirection().equals(current.getDirection())) { + return true; + } + } + if (next instanceof MovementTraverse) { + if (next.getDirection().down().equals(current.getDirection()) && MovementHelper.canWalkOn(next.getDest().down())) { + return true; + } + } + if (next instanceof MovementDiagonal && Baritone.settings().allowOvershootDiagonalDescend.get()) { + return true; + } + return false; + } + + private static void clearKeys() { + // i'm just sick and tired of this snippet being everywhere lol + Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); + } + + private void cancel() { + clearKeys(); + pathPosition = path.length() + 3; + failed = true; + } + public int getPosition() { return pathPosition; } diff --git a/src/main/java/baritone/utils/BlockBreakHelper.java b/src/main/java/baritone/utils/BlockBreakHelper.java index 8c224a2b..1bc4a44a 100644 --- a/src/main/java/baritone/utils/BlockBreakHelper.java +++ b/src/main/java/baritone/utils/BlockBreakHelper.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -27,14 +27,14 @@ import net.minecraft.util.math.BlockPos; */ public final class BlockBreakHelper implements Helper { - private BlockBreakHelper() {} - /** * The last block that we tried to break, if this value changes * between attempts, then we re-initialize the breaking process. */ private static BlockPos lastBlock; + private BlockBreakHelper() {} + public static void tryBreakBlock(BlockPos pos, EnumFacing side) { if (!pos.equals(lastBlock)) { mc.playerController.clickBlock(pos, side); @@ -46,7 +46,9 @@ public final class BlockBreakHelper implements Helper { } public static void stopBreakingBlock() { - mc.playerController.resetBlockRemoving(); + if (mc.playerController != null) { + mc.playerController.resetBlockRemoving(); + } lastBlock = null; } } diff --git a/src/main/java/baritone/utils/BlockStateInterface.java b/src/main/java/baritone/utils/BlockStateInterface.java index cd3ca646..068721cd 100644 --- a/src/main/java/baritone/utils/BlockStateInterface.java +++ b/src/main/java/baritone/utils/BlockStateInterface.java @@ -2,41 +2,54 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.utils; import baritone.Baritone; -import baritone.chunk.WorldData; -import baritone.chunk.WorldProvider; +import baritone.cache.CachedRegion; +import baritone.cache.WorldData; +import baritone.cache.WorldProvider; import net.minecraft.block.Block; -import net.minecraft.block.BlockFalling; import net.minecraft.block.BlockLiquid; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.Chunk; +/** + * Wraps get for chuck caching capability + * + * @author leijurv + */ public class BlockStateInterface implements Helper { private static Chunk prev = null; + private static CachedRegion prevCached = null; - public static IBlockState get(BlockPos pos) { // wrappers for chunk caching capability + private static IBlockState AIR = Blocks.AIR.getDefaultState(); + + public static IBlockState get(BlockPos pos) { + return get(pos.getX(), pos.getY(), pos.getZ()); + } + + public static IBlockState get(int x, int y, int z) { // Invalid vertical position - if (pos.getY() < 0 || pos.getY() >= 256) - return Blocks.AIR.getDefaultState(); + if (y < 0 || y >= 256) { + return AIR; + } if (!Baritone.settings().pathThroughCachedOnly.get()) { Chunk cached = prev; @@ -45,39 +58,76 @@ public class BlockStateInterface implements Helper { // if it's the same chunk as last time // we can just skip the mc.world.getChunk lookup // which is a Long2ObjectOpenHashMap.get - if (cached != null && cached.x == pos.getX() >> 4 && cached.z == pos.getZ() >> 4) { - return cached.getBlockState(pos); + // see issue #113 + if (cached != null && cached.x == x >> 4 && cached.z == z >> 4) { + return cached.getBlockState(x, y, z); } - Chunk chunk = mc.world.getChunk(pos); + Chunk chunk = mc.world.getChunk(x >> 4, z >> 4); if (chunk.isLoaded()) { prev = chunk; - return chunk.getBlockState(pos); + return chunk.getBlockState(x, y, z); } } + // same idea here, skip the Long2ObjectOpenHashMap.get if at all possible + // except here, it's 512x512 tiles instead of 16x16, so even better repetition + CachedRegion cached = prevCached; + if (cached == null || cached.getX() != x >> 9 || cached.getZ() != z >> 9) { + WorldData world = WorldProvider.INSTANCE.getCurrentWorld(); + if (world == null) { + return AIR; + } + CachedRegion region = world.cache.getRegion(x >> 9, z >> 9); + if (region == null) { + return AIR; + } + prevCached = region; + cached = region; + } + IBlockState type = cached.getBlock(x & 511, y, z & 511); + if (type == null) { + return AIR; + } + return type; + } + + public static boolean isLoaded(int x, int z) { + Chunk prevChunk = prev; + if (prevChunk != null && prevChunk.x == x >> 4 && prevChunk.z == z >> 4) { + return true; + } + prevChunk = mc.world.getChunk(x >> 4, z >> 4); + if (prevChunk.isLoaded()) { + prev = prevChunk; + return true; + } + CachedRegion prevRegion = prevCached; + if (prevRegion != null && prevRegion.getX() == x >> 9 && prevRegion.getZ() == z >> 9) { + return prevRegion.isCached(x & 511, z & 511); + } WorldData world = WorldProvider.INSTANCE.getCurrentWorld(); - if (world != null) { - IBlockState type = world.cache.getBlock(pos); - if (type != null) { - return type; - } + if (world == null) { + return false; } - - - return Blocks.AIR.getDefaultState(); + prevRegion = world.cache.getRegion(x >> 9, z >> 9); + if (prevRegion == null) { + return false; + } + prevCached = prevRegion; + return prevRegion.isCached(x & 511, z & 511); } public static void clearCachedChunk() { prev = null; + prevCached = null; } public static Block getBlock(BlockPos pos) { return get(pos).getBlock(); } - public static final Block waterFlowing = Blocks.FLOWING_WATER; - public static final Block waterStill = Blocks.WATER; - public static final Block lavaFlowing = Blocks.FLOWING_LAVA; - public static final Block lavaStill = Blocks.LAVA; + public static Block getBlock(int x, int y, int z) { + return get(x, y, z).getBlock(); + } /** * Returns whether or not the specified block is @@ -87,7 +137,7 @@ public class BlockStateInterface implements Helper { * @return Whether or not the block is water */ public static boolean isWater(Block b) { - return waterFlowing.equals(b) || waterStill.equals(b); + return b == Blocks.FLOWING_WATER || b == Blocks.WATER; } /** @@ -102,7 +152,7 @@ public class BlockStateInterface implements Helper { } public static boolean isLava(Block b) { - return lavaFlowing.equals(b) || lavaStill.equals(b); + return b == Blocks.FLOWING_LAVA || b == Blocks.LAVA; } /** @@ -121,18 +171,4 @@ public class BlockStateInterface implements Helper { && state.getPropertyKeys().contains(BlockLiquid.LEVEL) && state.getValue(BlockLiquid.LEVEL) != 0; } - - public static boolean isAir(BlockPos pos) { - return BlockStateInterface.getBlock(pos).equals(Blocks.AIR); - } - - public static boolean isAir(IBlockState state) { - return state.getBlock().equals(Blocks.AIR); - } - - static boolean canFall(BlockPos pos) { - return BlockStateInterface.get(pos).getBlock() instanceof BlockFalling; - } - - } diff --git a/src/main/java/baritone/utils/ExampleBaritoneControl.java b/src/main/java/baritone/utils/ExampleBaritoneControl.java index 75a36994..ee58fd60 100644 --- a/src/main/java/baritone/utils/ExampleBaritoneControl.java +++ b/src/main/java/baritone/utils/ExampleBaritoneControl.java @@ -2,48 +2,49 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.utils; import baritone.Baritone; -import baritone.Settings; +import baritone.api.Settings; +import baritone.api.cache.IWaypoint; import baritone.api.event.events.ChatEvent; +import baritone.api.pathing.goals.*; +import baritone.api.pathing.movement.ActionCosts; import baritone.behavior.Behavior; -import baritone.behavior.impl.FollowBehavior; -import baritone.behavior.impl.MineBehavior; -import baritone.behavior.impl.PathingBehavior; -import baritone.chunk.ChunkPacker; -import baritone.chunk.Waypoint; -import baritone.chunk.WorldProvider; -import baritone.pathing.calc.AStarPathFinder; +import baritone.behavior.FollowBehavior; +import baritone.behavior.MineBehavior; +import baritone.behavior.PathingBehavior; +import baritone.cache.ChunkPacker; +import baritone.cache.Waypoint; +import baritone.cache.WorldProvider; import baritone.pathing.calc.AbstractNodeCostSearch; -import baritone.pathing.goals.*; -import baritone.pathing.movement.ActionCosts; -import baritone.pathing.movement.CalculationContext; -import baritone.pathing.movement.Movement; -import baritone.pathing.movement.MovementHelper; -import baritone.utils.pathing.BetterBlockPos; +import baritone.pathing.movement.*; import net.minecraft.block.Block; +import net.minecraft.client.multiplayer.ChunkProviderClient; import net.minecraft.entity.Entity; +import net.minecraft.entity.player.EntityPlayer; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.chunk.EmptyChunk; +import net.minecraft.world.chunk.Chunk; import java.util.*; import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class ExampleBaritoneControl extends Behavior implements Helper { -public class ExampleBaritoneControl extends Behavior { public static ExampleBaritoneControl INSTANCE = new ExampleBaritoneControl(); private ExampleBaritoneControl() { @@ -61,16 +62,69 @@ public class ExampleBaritoneControl extends Behavior { return; } } - String msg = event.getMessage(); + String msg = event.getMessage().toLowerCase(Locale.US); if (Baritone.settings().prefix.get()) { if (!msg.startsWith("#")) { return; } msg = msg.substring(1); } - if (msg.toLowerCase().startsWith("goal")) { + + List> toggleable = Baritone.settings().getAllValuesByType(Boolean.class); + for (Settings.Setting setting : toggleable) { + if (msg.equalsIgnoreCase(setting.getName())) { + setting.value ^= true; + event.cancel(); + logDirect("Toggled " + setting.getName() + " to " + setting.value); + return; + } + } + if (msg.equals("baritone") || msg.equals("settings")) { + for (Settings.Setting setting : Baritone.settings().allSettings) { + logDirect(setting.toString()); + } event.cancel(); - String[] params = msg.toLowerCase().substring(4).trim().split(" "); + return; + } + if (msg.contains(" ")) { + String[] data = msg.split(" "); + if (data.length == 2) { + Settings.Setting setting = Baritone.settings().byLowerName.get(data[0]); + if (setting != null) { + try { + if (setting.value.getClass() == Long.class) { + setting.value = Long.parseLong(data[1]); + } + if (setting.value.getClass() == Integer.class) { + setting.value = Integer.parseInt(data[1]); + } + if (setting.value.getClass() == Double.class) { + setting.value = Double.parseDouble(data[1]); + } + if (setting.value.getClass() == Float.class) { + setting.value = Float.parseFloat(data[1]); + } + } catch (NumberFormatException e) { + logDirect("Unable to parse " + data[1]); + event.cancel(); + return; + } + logDirect(setting.toString()); + event.cancel(); + return; + } + } + } + if (Baritone.settings().byLowerName.containsKey(msg)) { + Settings.Setting setting = Baritone.settings().byLowerName.get(msg); + logDirect(setting.toString()); + event.cancel(); + return; + } + + if (msg.startsWith("goal")) { + event.cancel(); + String[] params = msg.substring(4).trim().split(" "); if (params[0].equals("")) { params = new String[]{}; } @@ -94,39 +148,81 @@ public class ExampleBaritoneControl extends Behavior { goal = new GoalBlock(new BlockPos(Integer.parseInt(params[0]), Integer.parseInt(params[1]), Integer.parseInt(params[2]))); break; default: - displayChatMessageRaw("unable to understand lol"); + logDirect("unable to understand lol"); return; } } catch (NumberFormatException ex) { - displayChatMessageRaw("unable to parse integer " + ex); + logDirect("unable to parse integer " + ex); return; } PathingBehavior.INSTANCE.setGoal(goal); - displayChatMessageRaw("Goal: " + goal); + logDirect("Goal: " + goal); return; } if (msg.equals("path")) { if (!PathingBehavior.INSTANCE.path()) { - displayChatMessageRaw("Currently executing a path. Please cancel it first."); + if (PathingBehavior.INSTANCE.getGoal() == null) { + logDirect("No goal."); + } else { + if (PathingBehavior.INSTANCE.getGoal().isInGoal(playerFeet())) { + logDirect("Already in goal"); + } else { + logDirect("Currently executing a path. Please cancel it first."); + } + } } event.cancel(); return; } - if (msg.toLowerCase().equals("cancel")) { - PathingBehavior.INSTANCE.cancel(); - FollowBehavior.INSTANCE.cancel(); + if (msg.equals("repack") || msg.equals("rescan")) { + ChunkProviderClient cli = world().getChunkProvider(); + int playerChunkX = playerFeet().getX() >> 4; + int playerChunkZ = playerFeet().getZ() >> 4; + int count = 0; + for (int x = playerChunkX - 40; x <= playerChunkX + 40; x++) { + for (int z = playerChunkZ - 40; z <= playerChunkZ + 40; z++) { + Chunk chunk = cli.getLoadedChunk(x, z); + if (chunk != null) { + count++; + WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().queueForPacking(chunk); + } + } + } + logDirect("Queued " + count + " chunks for repacking"); + event.cancel(); + return; + } + if (msg.equals("axis")) { + PathingBehavior.INSTANCE.setGoal(new GoalAxis()); + PathingBehavior.INSTANCE.path(); + event.cancel(); + return; + } + if (msg.equals("cancel")) { MineBehavior.INSTANCE.cancel(); + FollowBehavior.INSTANCE.cancel(); + PathingBehavior.INSTANCE.cancel(); event.cancel(); - displayChatMessageRaw("ok canceled"); + logDirect("ok canceled"); return; } - if (msg.toLowerCase().equals("forcecancel")) { + if (msg.equals("forcecancel")) { + MineBehavior.INSTANCE.cancel(); + FollowBehavior.INSTANCE.cancel(); + PathingBehavior.INSTANCE.cancel(); AbstractNodeCostSearch.forceCancel(); + PathingBehavior.INSTANCE.forceCancel(); event.cancel(); - displayChatMessageRaw("ok force canceled"); + logDirect("ok force canceled"); return; } - if (msg.toLowerCase().equals("invert")) { + if (msg.equals("gc")) { + System.gc(); + event.cancel(); + logDirect("Called System.gc();"); + return; + } + if (msg.equals("invert")) { Goal goal = PathingBehavior.INSTANCE.getGoal(); BlockPos runAwayFrom; if (goal instanceof GoalXZ) { @@ -134,8 +230,8 @@ public class ExampleBaritoneControl extends Behavior { } else if (goal instanceof GoalBlock) { runAwayFrom = ((GoalBlock) goal).getGoalPos(); } else { - displayChatMessageRaw("Goal must be GoalXZ or GoalBlock to invert"); - displayChatMessageRaw("Inverting goal of player feet"); + logDirect("Goal must be GoalXZ or GoalBlock to invert"); + logDirect("Inverting goal of player feet"); runAwayFrom = playerFeet(); } PathingBehavior.INSTANCE.setGoal(new GoalRunAway(1, runAwayFrom) { @@ -145,39 +241,52 @@ public class ExampleBaritoneControl extends Behavior { } }); if (!PathingBehavior.INSTANCE.path()) { - displayChatMessageRaw("Currently executing a path. Please cancel it first."); + logDirect("Currently executing a path. Please cancel it first."); } event.cancel(); return; } - if (msg.toLowerCase().equals("follow")) { - Optional entity = MovementHelper.whatEntityAmILookingAt(); - if (!entity.isPresent()) { - displayChatMessageRaw("You aren't looking at an entity bruh"); + if (msg.startsWith("follow")) { + String name = msg.substring(6).trim(); + Optional toFollow = Optional.empty(); + if (name.length() == 0) { + toFollow = MovementHelper.whatEntityAmILookingAt(); + } else { + for (EntityPlayer pl : world().playerEntities) { + String theirName = pl.getName().trim().toLowerCase(); + if (!theirName.equals(player().getName().trim().toLowerCase())) { // don't follow ourselves lol + if (theirName.contains(name) || name.contains(theirName)) { + toFollow = Optional.of(pl); + } + } + } + } + if (!toFollow.isPresent()) { + logDirect("Not found"); event.cancel(); return; } - FollowBehavior.INSTANCE.follow(entity.get()); - displayChatMessageRaw("Following " + entity.get()); + FollowBehavior.INSTANCE.follow(toFollow.get()); + logDirect("Following " + toFollow.get()); event.cancel(); return; } - if (msg.toLowerCase().equals("reloadall")) { - WorldProvider.INSTANCE.getCurrentWorld().cache.reloadAllFromDisk(); - displayChatMessageRaw("ok"); + if (msg.equals("reloadall")) { + WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().reloadAllFromDisk(); + logDirect("ok"); event.cancel(); return; } - if (msg.toLowerCase().equals("saveall")) { - WorldProvider.INSTANCE.getCurrentWorld().cache.save(); - displayChatMessageRaw("ok"); + if (msg.equals("saveall")) { + WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().save(); + logDirect("ok"); event.cancel(); return; } - if (msg.toLowerCase().startsWith("find")) { - String blockType = msg.toLowerCase().substring(4).trim(); - LinkedList locs = WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(blockType, 1, 4); - displayChatMessageRaw("Have " + locs.size() + " locations"); + if (msg.startsWith("find")) { + String blockType = msg.substring(4).trim(); + LinkedList locs = WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().getLocationsOf(blockType, 1, 4); + logDirect("Have " + locs.size() + " locations"); for (BlockPos pos : locs) { Block actually = BlockStateInterface.get(pos).getBlock(); if (!ChunkPacker.blockToString(actually).equalsIgnoreCase(blockType)) { @@ -187,125 +296,174 @@ public class ExampleBaritoneControl extends Behavior { event.cancel(); return; } - if (msg.toLowerCase().startsWith("mine")) { - String blockType = msg.toLowerCase().substring(4).trim(); - MineBehavior.INSTANCE.mine(blockType); - displayChatMessageRaw("Started mining blocks of type " + blockType); + if (msg.startsWith("mine")) { + String[] blockTypes = msg.substring(4).trim().split(" "); + try { + int quantity = Integer.parseInt(blockTypes[1]); + Block block = ChunkPacker.stringToBlock(blockTypes[0]); + Objects.requireNonNull(block); + MineBehavior.INSTANCE.mine(quantity, block); + logDirect("Will mine " + quantity + " " + blockTypes[0]); + event.cancel(); + return; + } catch (NumberFormatException | ArrayIndexOutOfBoundsException | NullPointerException ex) {} + for (String s : blockTypes) { + if (ChunkPacker.stringToBlock(s) == null) { + logDirect(s + " isn't a valid block name"); + event.cancel(); + return; + } + + } + MineBehavior.INSTANCE.mine(0, blockTypes); + logDirect("Started mining blocks of type " + Arrays.toString(blockTypes)); event.cancel(); return; } - if (msg.toLowerCase().startsWith("thisway")) { - Goal goal = GoalXZ.fromDirection(playerFeetAsVec(), player().rotationYaw, Double.parseDouble(msg.substring(7).trim())); - PathingBehavior.INSTANCE.setGoal(goal); - displayChatMessageRaw("Goal: " + goal); + if (msg.startsWith("thisway")) { + try { + Goal goal = GoalXZ.fromDirection(playerFeetAsVec(), player().rotationYaw, Double.parseDouble(msg.substring(7).trim())); + PathingBehavior.INSTANCE.setGoal(goal); + logDirect("Goal: " + goal); + } catch (NumberFormatException ex) { + logDirect("Error unable to parse '" + msg.substring(7).trim() + "' to a double."); + } event.cancel(); return; } - if (msg.toLowerCase().startsWith("list") || msg.toLowerCase().startsWith("get ") || msg.toLowerCase().startsWith("show")) { - String waypointType = msg.toLowerCase().substring(4).trim(); + if (msg.startsWith("list") || msg.startsWith("get ") || msg.startsWith("show")) { + String waypointType = msg.substring(4).trim(); if (waypointType.endsWith("s")) { // for example, "show deaths" waypointType = waypointType.substring(0, waypointType.length() - 1); } Waypoint.Tag tag = Waypoint.Tag.fromString(waypointType); if (tag == null) { - displayChatMessageRaw("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase()); + logDirect("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase()); event.cancel(); return; } - Set waypoints = WorldProvider.INSTANCE.getCurrentWorld().waypoints.getByTag(tag); + Set waypoints = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getByTag(tag); // might as well show them from oldest to newest - List sorted = new ArrayList<>(waypoints); - sorted.sort(Comparator.comparingLong(Waypoint::creationTimestamp)); - displayChatMessageRaw("Waypoints under tag " + tag + ":"); - for (Waypoint waypoint : sorted) { - displayChatMessageRaw(waypoint.toString()); + List sorted = new ArrayList<>(waypoints); + sorted.sort(Comparator.comparingLong(IWaypoint::getCreationTimestamp)); + logDirect("Waypoints under tag " + tag + ":"); + for (IWaypoint waypoint : sorted) { + logDirect(waypoint.toString()); } event.cancel(); return; } - if (msg.toLowerCase().startsWith("goto")) { - String waypointType = msg.toLowerCase().substring(4).trim(); + if (msg.startsWith("save")) { + event.cancel(); + String name = msg.substring(4).trim(); + BlockPos pos = playerFeet(); + if (name.contains(" ")) { + logDirect("Name contains a space, assuming it's in the format 'save waypointName X Y Z'"); + String[] parts = name.split(" "); + if (parts.length != 4) { + logDirect("Unable to parse, expected four things"); + return; + } + try { + pos = new BlockPos(Integer.parseInt(parts[1]), Integer.parseInt(parts[2]), Integer.parseInt(parts[3])); + } catch (NumberFormatException ex) { + logDirect("Unable to parse coordinate integers"); + return; + } + name = parts[0]; + } + WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint(name, Waypoint.Tag.USER, pos)); + logDirect("Saved user defined position " + pos + " under name '" + name + "'. Say 'goto user' to set goal, say 'list user' to list."); + return; + } + if (msg.startsWith("goto")) { + String waypointType = msg.substring(4).trim(); if (waypointType.endsWith("s") && Waypoint.Tag.fromString(waypointType.substring(0, waypointType.length() - 1)) != null) { // for example, "show deaths" waypointType = waypointType.substring(0, waypointType.length() - 1); } Waypoint.Tag tag = Waypoint.Tag.fromString(waypointType); + IWaypoint waypoint; if (tag == null) { String mining = waypointType; - //displayChatMessageRaw("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase()); + Block block = ChunkPacker.stringToBlock(mining); + //logDirect("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase()); event.cancel(); - List locs = new ArrayList<>(WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(mining, 1, 1)); - if (locs.isEmpty()) { - displayChatMessageRaw("No locations for " + mining + " known, cancelling"); + if (block == null) { + waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getAllWaypoints().stream().filter(w -> w.getName().equalsIgnoreCase(mining)).max(Comparator.comparingLong(IWaypoint::getCreationTimestamp)).orElse(null); + if (waypoint == null) { + logDirect("No locations for " + mining + " known, cancelling"); + return; + } + } else { + List locs = MineBehavior.INSTANCE.scanFor(Collections.singletonList(block), 64); + if (locs.isEmpty()) { + logDirect("No locations for " + mining + " known, cancelling"); + return; + } + PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new))); + PathingBehavior.INSTANCE.path(); return; } - BlockPos playerFeet = playerFeet(); - locs.sort(Comparator.comparingDouble(playerFeet::distanceSq)); - - // remove any that are within loaded chunks that aren't actually what we want - locs.removeAll(locs.stream() - .filter(pos -> !(world().getChunk(pos) instanceof EmptyChunk)) - .filter(pos -> !ChunkPacker.blockToString(BlockStateInterface.get(pos).getBlock()).equalsIgnoreCase(mining)) - .collect(Collectors.toList())); - if (locs.size() > 30) { - locs = locs.subList(0, 30); + } else { + waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(tag); + if (waypoint == null) { + logDirect("None saved for tag " + tag); + event.cancel(); + return; } - PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new))); - PathingBehavior.INSTANCE.path(); - return; } - Waypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().waypoints.getMostRecentByTag(tag); - if (waypoint == null) { - displayChatMessageRaw("None saved for tag " + tag); - event.cancel(); - return; - } - Goal goal = new GoalBlock(waypoint.location); + Goal goal = new GoalBlock(waypoint.getLocation()); PathingBehavior.INSTANCE.setGoal(goal); if (!PathingBehavior.INSTANCE.path()) { - displayChatMessageRaw("Currently executing a path. Please cancel it first."); + if (!goal.isInGoal(playerFeet())) { + logDirect("Currently executing a path. Please cancel it first."); + } } event.cancel(); return; } - if (msg.toLowerCase().equals("spawn") || msg.toLowerCase().equals("bed")) { - Waypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().waypoints.getMostRecentByTag(Waypoint.Tag.BED); + if (msg.equals("spawn") || msg.equals("bed")) { + IWaypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(Waypoint.Tag.BED); if (waypoint == null) { BlockPos spawnPoint = player().getBedLocation(); // for some reason the default spawnpoint is underground sometimes Goal goal = new GoalXZ(spawnPoint.getX(), spawnPoint.getZ()); - displayChatMessageRaw("spawn not saved, defaulting to world spawn. set goal to " + goal); + logDirect("spawn not saved, defaulting to world spawn. set goal to " + goal); PathingBehavior.INSTANCE.setGoal(goal); } else { - Goal goal = new GoalBlock(waypoint.location); + Goal goal = new GoalBlock(waypoint.getLocation()); PathingBehavior.INSTANCE.setGoal(goal); - displayChatMessageRaw("Set goal to most recent bed " + goal); + logDirect("Set goal to most recent bed " + goal); } event.cancel(); return; } - if (msg.toLowerCase().equals("sethome")) { - WorldProvider.INSTANCE.getCurrentWorld().waypoints.addWaypoint(new Waypoint("", Waypoint.Tag.HOME, playerFeet())); - displayChatMessageRaw("Saved. Say home to set goal."); + if (msg.equals("sethome")) { + WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("", Waypoint.Tag.HOME, playerFeet())); + logDirect("Saved. Say home to set goal."); event.cancel(); return; } - if (msg.toLowerCase().equals("home")) { - Waypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().waypoints.getMostRecentByTag(Waypoint.Tag.HOME); + if (msg.equals("home")) { + IWaypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(Waypoint.Tag.HOME); if (waypoint == null) { - displayChatMessageRaw("home not saved"); + logDirect("home not saved"); } else { - Goal goal = new GoalBlock(waypoint.location); + Goal goal = new GoalBlock(waypoint.getLocation()); PathingBehavior.INSTANCE.setGoal(goal); - displayChatMessageRaw("Set goal to saved home " + goal); + PathingBehavior.INSTANCE.path(); + logDirect("Going to saved home " + goal); } event.cancel(); return; } - if (msg.toLowerCase().equals("costs")) { - Movement[] movements = AStarPathFinder.getConnectedPositions(new BetterBlockPos(playerFeet()), new CalculationContext()); - List moves = new ArrayList<>(Arrays.asList(movements)); + if (msg.equals("costs")) { + List moves = Stream.of(Moves.values()).map(x -> x.apply0(playerFeet())).collect(Collectors.toCollection(ArrayList::new)); + while (moves.contains(null)) { + moves.remove(null); + } moves.sort(Comparator.comparingDouble(movement -> movement.getCost(new CalculationContext()))); for (Movement move : moves) { String[] parts = move.getClass().toString().split("\\."); @@ -314,58 +472,10 @@ public class ExampleBaritoneControl extends Behavior { if (cost >= ActionCosts.COST_INF) { strCost = "IMPOSSIBLE"; } - displayChatMessageRaw(parts[parts.length - 1] + " " + move.getDest().getX() + "," + move.getDest().getY() + "," + move.getDest().getZ() + " " + strCost); + logDirect(parts[parts.length - 1] + " " + move.getDest().getX() + "," + move.getDest().getY() + "," + move.getDest().getZ() + " " + strCost); } event.cancel(); return; } - List> toggleable = Baritone.settings().getAllValuesByType(Boolean.class); - for (Settings.Setting setting : toggleable) { - if (msg.equalsIgnoreCase(setting.getName())) { - setting.value ^= true; - event.cancel(); - displayChatMessageRaw("Toggled " + setting.getName() + " to " + setting.value); - return; - } - } - if (msg.toLowerCase().equals("baritone") || msg.toLowerCase().equals("settings")) { - for (Settings.Setting setting : Baritone.settings().allSettings) { - displayChatMessageRaw(setting.toString()); - } - event.cancel(); - return; - } - if (msg.contains(" ")) { - String[] data = msg.split(" "); - if (data.length == 2) { - Settings.Setting setting = Baritone.settings().byLowerName.get(data[0].toLowerCase()); - if (setting != null) { - try { - if (setting.value.getClass() == Long.class) { - setting.value = Long.parseLong(data[1]); - } - if (setting.value.getClass() == Integer.class) { - setting.value = Integer.parseInt(data[1]); - } - if (setting.value.getClass() == Double.class) { - setting.value = Double.parseDouble(data[1]); - } - } catch (NumberFormatException e) { - displayChatMessageRaw("Unable to parse " + data[1]); - event.cancel(); - return; - } - displayChatMessageRaw(setting.toString()); - event.cancel(); - return; - } - } - } - if (Baritone.settings().byLowerName.containsKey(msg.toLowerCase())) { - Settings.Setting setting = Baritone.settings().byLowerName.get(msg.toLowerCase()); - displayChatMessageRaw(setting.toString()); - event.cancel(); - return; - } } } diff --git a/src/main/java/baritone/utils/Helper.java b/src/main/java/baritone/utils/Helper.java index c973b1ca..a0ffdb96 100755 --- a/src/main/java/baritone/utils/Helper.java +++ b/src/main/java/baritone/utils/Helper.java @@ -2,26 +2,28 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.utils; import baritone.Baritone; +import baritone.api.utils.Rotation; +import baritone.utils.pathing.BetterBlockPos; +import net.minecraft.block.BlockSlab; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.multiplayer.WorldClient; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentString; @@ -33,7 +35,18 @@ import net.minecraft.util.text.TextFormatting; */ public interface Helper { - ITextComponent MESSAGE_PREFIX = new TextComponentString("§5[§dBaritone§5]§7"); + /** + * Instance of {@link Helper}. Used for static-context reference. + */ + Helper HELPER = new Helper() {}; + + ITextComponent MESSAGE_PREFIX = new TextComponentString(String.format( + "%s[%sBaritone%s]%s", + TextFormatting.DARK_PURPLE, + TextFormatting.LIGHT_PURPLE, + TextFormatting.DARK_PURPLE, + TextFormatting.GRAY + )); Minecraft mc = Minecraft.getMinecraft(); @@ -45,12 +58,13 @@ public interface Helper { return mc.world; } - default BlockPos playerFeet() { + default BetterBlockPos playerFeet() { // TODO find a better way to deal with soul sand!!!!! - return new BlockPos(player().posX, player().posY + 0.1251, player().posZ); - /*if (BlockStateInterface.get(feet).getBlock().equals(Blocks.SOUL_SAND) && player().posY > feet.getY() + 0.874999) { + BetterBlockPos feet = new BetterBlockPos(player().posX, player().posY + 0.1251, player().posZ); + if (BlockStateInterface.get(feet).getBlock() instanceof BlockSlab) { return feet.up(); - }*/ + } + return feet; } default Vec3d playerFeetAsVec() { @@ -65,16 +79,29 @@ public interface Helper { return new Rotation(player().rotationYaw, player().rotationPitch); } - default void displayChatMessageRaw(String message) { + /** + * Send a message to chat only if chatDebug is on + * + * @param message + */ + default void logDebug(String message) { if (!Baritone.settings().chatDebug.get()) { System.out.println("Suppressed debug message:"); System.out.println(message); return; } + logDirect(message); + } + /** + * Send a message to chat regardless of chatDebug (should only be used for critically important messages, or as a direct response to a chat command) + * + * @param message + */ + default void logDirect(String message) { ITextComponent component = MESSAGE_PREFIX.createCopy(); component.getStyle().setColor(TextFormatting.GRAY); component.appendSibling(new TextComponentString(" " + message)); - mc.ingameGUI.getChatGUI().printChatMessage(component); + Baritone.settings().logger.get().accept(component); } } diff --git a/src/main/java/baritone/utils/InputOverrideHandler.java b/src/main/java/baritone/utils/InputOverrideHandler.java index 9860e2e1..9cf7d1da 100755 --- a/src/main/java/baritone/utils/InputOverrideHandler.java +++ b/src/main/java/baritone/utils/InputOverrideHandler.java @@ -2,40 +2,22 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License - * along with Baritone. If not, see . - */ - -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.utils; import net.minecraft.client.settings.KeyBinding; -import org.lwjgl.input.Keyboard; import java.util.HashMap; import java.util.Map; @@ -50,21 +32,13 @@ import java.util.Map; */ public final class InputOverrideHandler implements Helper { - public InputOverrideHandler() {} - /** * Maps keybinds to whether or not we are forcing their state down. */ private final Map inputForceStateMap = new HashMap<>(); - /** - * Maps keycodes to whether or not we are forcing their state down. - */ - private final Map keyCodeForceStateMap = new HashMap<>(); - public final void clearAllKeys() { inputForceStateMap.clear(); - keyCodeForceStateMap.clear(); } /** @@ -87,25 +61,6 @@ public final class InputOverrideHandler implements Helper { inputForceStateMap.put(input.getKeyBinding(), forced); } - /** - * A redirection in multiple places of {@link Keyboard#isKeyDown}. - * - * @return Whether or not the specified key is down or overridden. - */ - public boolean isKeyDown(int keyCode) { - return Keyboard.isKeyDown(keyCode) || keyCodeForceStateMap.getOrDefault(keyCode, false); - } - - /** - * Sets whether or not the specified key code is being forced down. - * - * @param keyCode The key code - * @param forced Whether or not the state is being forced - */ - public final void setKeyForceState(int keyCode, boolean forced) { - keyCodeForceStateMap.put(keyCode, forced); - } - /** * An {@link Enum} representing the possible inputs that we may want to force. */ @@ -159,7 +114,7 @@ public final class InputOverrideHandler implements Helper { /** * The actual game {@link KeyBinding} being forced. */ - private KeyBinding keyBinding; + private final KeyBinding keyBinding; Input(KeyBinding keyBinding) { this.keyBinding = keyBinding; diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 6fd3466e..a66bc0ae 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -2,26 +2,28 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.utils; import baritone.Baritone; -import baritone.pathing.goals.Goal; -import baritone.pathing.goals.GoalBlock; -import baritone.pathing.goals.GoalXZ; +import baritone.api.pathing.goals.Goal; +import baritone.api.pathing.goals.GoalComposite; +import baritone.api.pathing.goals.GoalTwoBlocks; +import baritone.api.pathing.goals.GoalXZ; import baritone.pathing.path.IPath; +import baritone.api.utils.interfaces.IGoalRenderPos; import baritone.utils.pathing.BetterBlockPos; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -47,14 +49,13 @@ import static org.lwjgl.opengl.GL11.*; * @since 8/9/2018 4:39 PM */ public final class PathRenderer implements Helper { - - private PathRenderer() { - } - + private static final Tessellator TESSELLATOR = Tessellator.getInstance(); private static final BufferBuilder BUFFER = TESSELLATOR.getBuffer(); - public static void drawPath(IPath path, int startIndex, EntityPlayerSP player, float partialTicks, Color color, boolean fadeOut, int fadeStart, int fadeEnd) { + private PathRenderer() {} + + public static void drawPath(IPath path, int startIndex, EntityPlayerSP player, float partialTicks, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) { GlStateManager.enableBlend(); GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.4F); @@ -64,8 +65,8 @@ public final class PathRenderer implements Helper { List positions = path.positions(); int next; Tessellator tessellator = Tessellator.getInstance(); - fadeStart += startIndex; - fadeEnd += startIndex; + int fadeStart = fadeStart0 + startIndex; + int fadeEnd = fadeEnd0 + startIndex; for (int i = startIndex; i < positions.size() - 1; i = next) { BlockPos start = positions.get(i); @@ -183,17 +184,25 @@ public final class PathRenderer implements Helper { double maxY; double y1; double y2; - if (goal instanceof GoalBlock) { - BlockPos goalPos = ((GoalBlock) goal).getGoalPos(); + if (goal instanceof IGoalRenderPos) { + BlockPos goalPos = ((IGoalRenderPos) goal).getGoalPos(); minX = goalPos.getX() + 0.002 - renderPosX; maxX = goalPos.getX() + 1 - 0.002 - renderPosX; minZ = goalPos.getZ() + 0.002 - renderPosZ; maxZ = goalPos.getZ() + 1 - 0.002 - renderPosZ; - double y = MathHelper.sin((float) (((float) (System.nanoTime() / 1000000L) % 2000L) / 2000F * Math.PI * 2)); + double y = MathHelper.cos((float) (((float) ((System.nanoTime() / 100000L) % 20000L)) / 20000F * Math.PI * 2)); + if (goal instanceof GoalTwoBlocks) { + y /= 2; + } y1 = 1 + y + goalPos.getY() - renderPosY; y2 = 1 - y + goalPos.getY() - renderPosY; minY = goalPos.getY() - renderPosY; maxY = minY + 2; + if (goal instanceof GoalTwoBlocks) { + y1 -= 0.5; + y2 -= 0.5; + maxY--; + } } else if (goal instanceof GoalXZ) { GoalXZ goalPos = (GoalXZ) goal; @@ -206,8 +215,12 @@ public final class PathRenderer implements Helper { y2 = 0; minY = 0 - renderPosY; maxY = 256 - renderPosY; + } else if (goal instanceof GoalComposite) { + for (Goal g : ((GoalComposite) goal).goals()) { + drawLitDankGoalBox(player, g, partialTicks, color); + } + return; } else { - // TODO GoalComposite return; } diff --git a/src/main/java/baritone/utils/RayTraceUtils.java b/src/main/java/baritone/utils/RayTraceUtils.java index 123e283d..b313f1fe 100644 --- a/src/main/java/baritone/utils/RayTraceUtils.java +++ b/src/main/java/baritone/utils/RayTraceUtils.java @@ -2,25 +2,26 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.utils; +import baritone.api.utils.Rotation; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; -import static baritone.behavior.impl.LookBehaviorUtils.calcVec3dFromRotation; +import static baritone.behavior.LookBehaviorUtils.calcVec3dFromRotation; /** * @author Brady @@ -30,6 +31,18 @@ public final class RayTraceUtils implements Helper { private RayTraceUtils() {} + /** + * Simulates a "vanilla" raytrace. A RayTraceResult returned by this method + * will be that of the next render pass given that the local player's yaw and + * pitch match the specified yaw and pitch values. This is particularly useful + * when you would like to simulate a "legit" raytrace with certainty that the only + * thing to achieve the desired outcome (whether it is hitting and entity or placing + * a block) can be done just by modifying user input. + * + * @param yaw The yaw to raytrace with + * @param pitch The pitch to raytrace with + * @return The calculated raytrace result + */ public static RayTraceResult simulateRayTrace(float yaw, float pitch) { RayTraceResult oldTrace = mc.objectMouseOver; float oldYaw = mc.player.rotationYaw; @@ -48,6 +61,14 @@ public final class RayTraceUtils implements Helper { return result; } + /** + * Performs a block raytrace with the specified rotations. This should only be used when + * any entity collisions can be ignored, because this method will not recognize if an + * entity is in the way or not. The local player's block reach distance will be used. + * + * @param rotation The rotation to raytrace towards + * @return The calculated raytrace result + */ public static RayTraceResult rayTraceTowards(Rotation rotation) { double blockReachDistance = mc.playerController.getBlockReachDistance(); Vec3d start = mc.player.getPositionEyes(1.0F); diff --git a/src/main/java/baritone/utils/ToolSet.java b/src/main/java/baritone/utils/ToolSet.java index 415d8ebd..62115f24 100644 --- a/src/main/java/baritone/utils/ToolSet.java +++ b/src/main/java/baritone/utils/ToolSet.java @@ -2,108 +2,44 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.utils; import baritone.Baritone; -import baritone.api.event.events.ItemSlotEvent; -import baritone.api.event.listener.AbstractGameEventListener; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityPlayerSP; -import net.minecraft.item.Item; -import net.minecraft.item.ItemAir; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.init.Enchantments; +import net.minecraft.init.MobEffects; import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemTool; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; /** * A cached list of the best tools on the hotbar for any block * - * @author avecowa, Brady + * @author avecowa, Brady, leijurv */ public class ToolSet implements Helper { /** - * Instance of the internal event listener used to hook into Baritone's event bus - */ - private static final InternalEventListener INTERNAL_EVENT_LISTENER = new InternalEventListener(); - - static { - Baritone.INSTANCE.getGameEventHandler().registerEventListener(INTERNAL_EVENT_LISTENER); - } - - /** - * A list of tools on the hotbar that should be considered. - * Note that if there are no tools on the hotbar this list will still have one (null) entry. - */ - private List tools; - - /** - * A mapping from the tools array to what hotbar slots the tool is actually in. - * tools.get(i) will be on your hotbar in slot slots.get(i) - */ - private List slots; - - /** - * A mapping from a block to which tool index is best for it. - * The values in this map are *not* hotbar slots indexes, they need to be looked up in slots - * in order to be converted into hotbar slots. - */ - private Map slotCache = new HashMap<>(); - - /** - * A cache mapping a {@link IBlockState} to how long it will take to break + * A cache mapping a {@link Block} to how long it will take to break * with this toolset, given the optimum tool is used. */ - private Map breakStrengthCache = new HashMap<>(); - - /** - * Create a toolset from the current player's inventory (but don't calculate any hardness values just yet) - */ - public ToolSet() { - EntityPlayerSP p = Minecraft.getMinecraft().player; - NonNullList inv = p.inventory.mainInventory; - tools = new ArrayList<>(); - slots = new ArrayList<>(); - boolean fnull = false; - for (byte i = 0; i < 9; i++) { - if (!fnull || ((!(inv.get(i).getItem() instanceof ItemAir)) && inv.get(i).getItem() instanceof ItemTool)) { - tools.add(inv.get(i).getItem() instanceof ItemTool ? (ItemTool) inv.get(i).getItem() : null); - slots.add(i); - fnull |= (inv.get(i).getItem() instanceof ItemAir) || (!inv.get(i).getItem().isDamageable()); - } - } - } - - /** - * A caching wrapper around getBestToolIndex - * - * @param state the blockstate to be mined - * @return get which tool on the hotbar is best for mining it - */ - public Item getBestTool(IBlockState state) { - return tools.get(slotCache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state))); - } + private Map breakStrengthCache = new HashMap<>(); /** * Calculate which tool on the hotbar is best for mining @@ -111,15 +47,11 @@ public class ToolSet implements Helper { * @param b the blockstate to be mined * @return a byte indicating the index in the tools array that worked best */ - private byte getBestToolIndex(IBlockState b) { + public byte getBestSlot(IBlockState b) { byte best = 0; - float value = -1; - for (byte i = 0; i < tools.size(); i++) { - Item item = tools.get(i); - if (item == null) - continue; - - float v = item.getDestroySpeed(new ItemStack(item), b); + double value = -1; + for (byte i = 0; i < 9; i++) { + double v = calculateStrVsBlock(i, b); if (v > value || value == -1) { value = v; best = i; @@ -128,62 +60,66 @@ public class ToolSet implements Helper { return best; } - /** - * Get which hotbar slot should be selected for fastest mining - * - * @param state the blockstate to be mined - * @return a byte indicating which hotbar slot worked best - */ - public byte getBestSlot(IBlockState state) { - return slots.get(slotCache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state))); - } - /** * Using the best tool on the hotbar, how long would it take to mine this block * * @param state the blockstate to be mined - * @param pos the blockpos to be mined * @return how long it would take in ticks */ - public double getStrVsBlock(IBlockState state, BlockPos pos) { - return this.breakStrengthCache.computeIfAbsent(state, s -> calculateStrVsBlock(s, pos)); + public double getStrVsBlock(IBlockState state) { + return this.breakStrengthCache.computeIfAbsent(state.getBlock(), b -> calculateStrVsBlock(getBestSlot(state), state)); } /** * Calculates how long would it take to mine the specified block given the best tool - * in this toolset is used. + * in this toolset is used. A negative value is returned if the specified block is unbreakable. * * @param state the blockstate to be mined - * @param pos the blockpos to be mined * @return how long it would take in ticks */ - private double calculateStrVsBlock(IBlockState state, BlockPos pos) { + private double calculateStrVsBlock(byte slot, IBlockState state) { // Calculate the slot with the best item - byte slot = this.getBestSlot(state); + ItemStack contents = player().inventory.getStackInSlot(slot); - INTERNAL_EVENT_LISTENER.setOverrideSlot(slot); - - // Calculate the relative hardness of the block to the player - float hardness = state.getPlayerRelativeBlockHardness(player(), world(), pos); - - // Restore the old slot - INTERNAL_EVENT_LISTENER.setOverrideSlot(-1); - - return hardness; - } - - private static final class InternalEventListener implements AbstractGameEventListener { - - private int overrideSlot; - - @Override - public void onQueryItemSlotForBlocks(ItemSlotEvent event) { - if (this.overrideSlot >= 0) - event.setSlot(this.overrideSlot); + float blockHard = state.getBlockHardness(null, null); + if (blockHard < 0) { + return -1; } - final void setOverrideSlot(int overrideSlot) { - this.overrideSlot = overrideSlot; + float speed = contents.getDestroySpeed(state); + if (speed > 1) { + int effLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.EFFICIENCY, contents); + if (effLevel > 0 && !contents.isEmpty()) { + speed += effLevel * effLevel + 1; + } + } + + if (Baritone.settings().considerPotionEffects.get()) { + if (player().isPotionActive(MobEffects.HASTE)) { + speed *= 1 + (player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2; + } + if (player().isPotionActive(MobEffects.MINING_FATIGUE)) { + switch (player().getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) { + case 0: + speed *= 0.3; + break; + case 1: + speed *= 0.09; + break; + case 2: + speed *= 0.0027; + break; + default: + speed *= 0.00081; + break; + } + } + } + speed /= blockHard; + if (state.getMaterial().isToolNotRequired() || (!contents.isEmpty() && contents.canHarvestBlock(state))) { + return speed / 30; + } else { + return speed / 100; } } } diff --git a/src/main/java/baritone/utils/Utils.java b/src/main/java/baritone/utils/Utils.java index 9f1ac3b3..0de61461 100755 --- a/src/main/java/baritone/utils/Utils.java +++ b/src/main/java/baritone/utils/Utils.java @@ -2,29 +2,33 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.utils; +import baritone.api.utils.Rotation; import net.minecraft.block.BlockFire; import net.minecraft.block.state.IBlockState; +import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import static baritone.utils.Helper.HELPER; + /** * @author Brady * @since 8/1/2018 12:56 AM @@ -95,10 +99,7 @@ public final class Utils { } public static Rotation wrapAnglesToRelative(Rotation current, Rotation target) { - return new Rotation( - MathHelper.wrapDegrees(target.getFirst() - current.getFirst()) + current.getFirst(), - MathHelper.wrapDegrees(target.getSecond() - current.getSecond()) + current.getSecond() - ); + return target.subtract(current).normalize().add(current); } public static Vec3d vec3dFromBlockPos(BlockPos orig) { @@ -112,6 +113,16 @@ public final class Utils { return Math.sqrt(xdiff * xdiff + ydiff * ydiff + zdiff * zdiff); } + public static double playerDistanceToCenter(BlockPos pos) { + EntityPlayerSP player = HELPER.player(); + return distanceToCenter(pos, player.posX, player.posY, player.posZ); + } + + public static double playerFlatDistanceToCenter(BlockPos pos) { + EntityPlayerSP player = HELPER.player(); + return distanceToCenter(pos, player.posX, pos.getY() + 0.5, player.posZ); + } + public static double degToRad(double deg) { return deg * DEG_TO_RAD; } diff --git a/src/main/java/baritone/launch/mixins/accessor/IAnvilChunkLoader.java b/src/main/java/baritone/utils/accessor/IAnvilChunkLoader.java similarity index 57% rename from src/main/java/baritone/launch/mixins/accessor/IAnvilChunkLoader.java rename to src/main/java/baritone/utils/accessor/IAnvilChunkLoader.java index 3972ff32..c243ae0e 100644 --- a/src/main/java/baritone/launch/mixins/accessor/IAnvilChunkLoader.java +++ b/src/main/java/baritone/utils/accessor/IAnvilChunkLoader.java @@ -2,24 +2,20 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.launch.mixins.accessor; - -import net.minecraft.world.chunk.storage.AnvilChunkLoader; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; +package baritone.utils.accessor; import java.io.File; @@ -27,8 +23,7 @@ import java.io.File; * @author Brady * @since 8/4/2018 11:36 AM */ -@Mixin(AnvilChunkLoader.class) public interface IAnvilChunkLoader { - @Accessor File getChunkSaveLocation(); + File getChunkSaveLocation(); } diff --git a/src/main/java/baritone/launch/mixins/accessor/IChunkProviderServer.java b/src/main/java/baritone/utils/accessor/IChunkProviderServer.java similarity index 58% rename from src/main/java/baritone/launch/mixins/accessor/IChunkProviderServer.java rename to src/main/java/baritone/utils/accessor/IChunkProviderServer.java index 460014fc..78a471b2 100644 --- a/src/main/java/baritone/launch/mixins/accessor/IChunkProviderServer.java +++ b/src/main/java/baritone/utils/accessor/IChunkProviderServer.java @@ -2,32 +2,28 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.launch.mixins.accessor; +package baritone.utils.accessor; import net.minecraft.world.chunk.storage.IChunkLoader; -import net.minecraft.world.gen.ChunkProviderServer; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.gen.Accessor; /** * @author Brady * @since 8/4/2018 11:33 AM */ -@Mixin(ChunkProviderServer.class) public interface IChunkProviderServer { - @Accessor IChunkLoader getChunkLoader(); + IChunkLoader getChunkLoader(); } diff --git a/src/main/java/baritone/utils/pathing/BetterBlockPos.java b/src/main/java/baritone/utils/pathing/BetterBlockPos.java index 6e4fc599..7aed17c6 100644 --- a/src/main/java/baritone/utils/pathing/BetterBlockPos.java +++ b/src/main/java/baritone/utils/pathing/BetterBlockPos.java @@ -2,31 +2,37 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.utils.pathing; +import baritone.pathing.calc.AbstractNodeCostSearch; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3i; /** * A better BlockPos that has fewer hash collisions (and slightly more performant offsets) + *

+ * Is it really faster to subclass BlockPos and calculate a hash in the constructor like this, taking everything into account? + * Yes. 20% faster actually. It's called BETTER BlockPos for a reason. Source: + * Benchmark Spreadsheet * * @author leijurv */ -public class BetterBlockPos extends BlockPos { +public final class BetterBlockPos extends BlockPos { public final int x; public final int y; public final int z; @@ -37,22 +43,11 @@ public class BetterBlockPos extends BlockPos { this.x = x; this.y = y; this.z = z; - /* - * This is the hashcode implementation of Vec3i, the superclass of BlockPos - * - * public int hashCode() { - * return (this.getY() + this.getZ() * 31) * 31 + this.getX(); - * } - * - * That is terrible and has tons of collisions and makes the HashMap terribly inefficient. - * - * That's why we grab out the X, Y, Z and calculate our own hashcode - */ - long hash = 3241; - hash = 3457689L * hash + x; - hash = 8734625L * hash + y; - hash = 2873465L * hash + z; - this.hashCode = hash; + this.hashCode = AbstractNodeCostSearch.posHash(x, y, z); + } + + public BetterBlockPos(double x, double y, double z) { + this(MathHelper.floor(x), MathHelper.floor(y), MathHelper.floor(z)); } public BetterBlockPos(BlockPos pos) { @@ -60,12 +55,12 @@ public class BetterBlockPos extends BlockPos { } @Override - public final int hashCode() { + public int hashCode() { return (int) hashCode; } @Override - public final boolean equals(Object o) { + public boolean equals(Object o) { if (o == null) { return false; } @@ -83,7 +78,7 @@ public class BetterBlockPos extends BlockPos { } @Override - public BlockPos up() { + public BetterBlockPos up() { // this is unimaginably faster than blockpos.up // that literally calls // this.up(1) @@ -97,26 +92,75 @@ public class BetterBlockPos extends BlockPos { } @Override - public BlockPos up(int amt) { + public BetterBlockPos up(int amt) { // see comment in up() return amt == 0 ? this : new BetterBlockPos(x, y + amt, z); } @Override - public BlockPos down() { + public BetterBlockPos down() { // see comment in up() return new BetterBlockPos(x, y - 1, z); } @Override - public BlockPos down(int amt) { + public BetterBlockPos down(int amt) { // see comment in up() - return new BetterBlockPos(x, y - amt, z); + return amt == 0 ? this : new BetterBlockPos(x, y - amt, z); } @Override - public BlockPos offset(EnumFacing dir) { + public BetterBlockPos offset(EnumFacing dir) { Vec3i vec = dir.getDirectionVec(); return new BetterBlockPos(x + vec.getX(), y + vec.getY(), z + vec.getZ()); } + + @Override + public BetterBlockPos offset(EnumFacing dir, int dist) { + if (dist == 0) { + return this; + } + Vec3i vec = dir.getDirectionVec(); + return new BetterBlockPos(x + vec.getX() * dist, y + vec.getY() * dist, z + vec.getZ() * dist); + } + + @Override + public BetterBlockPos north() { + return new BetterBlockPos(x, y, z - 1); + } + + @Override + public BetterBlockPos north(int amt) { + return amt == 0 ? this : new BetterBlockPos(x, y, z - amt); + } + + @Override + public BetterBlockPos south() { + return new BetterBlockPos(x, y, z + 1); + } + + @Override + public BetterBlockPos south(int amt) { + return amt == 0 ? this : new BetterBlockPos(x, y, z + amt); + } + + @Override + public BetterBlockPos east() { + return new BetterBlockPos(x + 1, y, z); + } + + @Override + public BetterBlockPos east(int amt) { + return amt == 0 ? this : new BetterBlockPos(x + amt, y, z); + } + + @Override + public BetterBlockPos west() { + return new BetterBlockPos(x - 1, y, z); + } + + @Override + public BetterBlockPos west(int amt) { + return amt == 0 ? this : new BetterBlockPos(x - amt, y, z); + } } diff --git a/src/main/java/baritone/utils/pathing/MoveResult.java b/src/main/java/baritone/utils/pathing/MoveResult.java new file mode 100644 index 00000000..8478a617 --- /dev/null +++ b/src/main/java/baritone/utils/pathing/MoveResult.java @@ -0,0 +1,40 @@ +/* + * 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 . + */ + +package baritone.utils.pathing; + +import static baritone.api.pathing.movement.ActionCosts.COST_INF; + +/** + * The result of a calculated movement, with destination x, y, z, and the cost of performing the movement + * + * @author leijurv + */ +public final class MoveResult { + public static final MoveResult IMPOSSIBLE = new MoveResult(0, 0, 0, COST_INF); + public final int destX; + public final int destY; + public final int destZ; + public final double cost; + + public MoveResult(int x, int y, int z, double cost) { + this.destX = x; + this.destY = y; + this.destZ = z; + this.cost = cost; + } +} diff --git a/src/main/java/baritone/utils/pathing/PathingBlockType.java b/src/main/java/baritone/utils/pathing/PathingBlockType.java index 61dbf2fc..80c92dcb 100644 --- a/src/main/java/baritone/utils/pathing/PathingBlockType.java +++ b/src/main/java/baritone/utils/pathing/PathingBlockType.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ diff --git a/src/test/java/baritone/chunk/CachedRegionTest.java b/src/test/java/baritone/cache/CachedRegionTest.java similarity index 85% rename from src/test/java/baritone/chunk/CachedRegionTest.java rename to src/test/java/baritone/cache/CachedRegionTest.java index 8350390c..19874990 100644 --- a/src/test/java/baritone/chunk/CachedRegionTest.java +++ b/src/test/java/baritone/cache/CachedRegionTest.java @@ -2,20 +2,20 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ -package baritone.chunk; +package baritone.cache; import org.junit.Test; diff --git a/src/test/java/baritone/pathing/calc/openset/OpenSetsTest.java b/src/test/java/baritone/pathing/calc/openset/OpenSetsTest.java index 6812f90d..8cc0bec7 100644 --- a/src/test/java/baritone/pathing/calc/openset/OpenSetsTest.java +++ b/src/test/java/baritone/pathing/calc/openset/OpenSetsTest.java @@ -2,44 +2,55 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.pathing.calc.openset; +import baritone.api.pathing.goals.Goal; import baritone.pathing.calc.PathNode; -import baritone.pathing.goals.Goal; -import baritone.utils.pathing.BetterBlockPos; -import net.minecraft.util.math.BlockPos; import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; import java.util.*; import static org.junit.Assert.*; +@RunWith(Parameterized.class) public class OpenSetsTest { - @Test - public void testOpenSets() { - for (int size = 1; size < 100; size++) { - testSize(size); - } - for (int size = 100; size < 10000; size += 100) { - testSize(size); - } + private final int size; + + public OpenSetsTest(int size) { + this.size = size; } - public void removeAndTest(int amount, IOpenSet[] test, Optional> mustContain) { + @Parameterized.Parameters + public static Collection data() { + ArrayList testSizes = new ArrayList<>(); + for (int size = 1; size < 20; size++) { + testSizes.add(new Object[]{size}); + } + for (int size = 100; size <= 1000; size += 100) { + testSizes.add(new Object[]{size}); + } + testSizes.add(new Object[]{5000}); + testSizes.add(new Object[]{10000}); + return testSizes; + } + + private static void removeAndTest(int amount, IOpenSet[] test, Optional> mustContain) { double[][] results = new double[test.length][amount]; for (int i = 0; i < test.length; i++) { long before = System.nanoTime() / 1000000L; @@ -62,7 +73,8 @@ public class OpenSetsTest { } } - public void testSize(int size) { + @Test + public void testSize() { System.out.println("Testing size " + size); // Include LinkedListOpenSet even though it's not performant because I absolutely trust that it behaves properly // I'm really testing the heap implementations against it as the ground truth @@ -77,14 +89,14 @@ public class OpenSetsTest { // can't use an existing goal // because they use Baritone.settings() // and we can't do that because Minecraft itself isn't initted - PathNode pn = new PathNode(new BetterBlockPos(0, 0, 0), new Goal() { + PathNode pn = new PathNode(0, 0, 0, new Goal() { @Override - public boolean isInGoal(BlockPos pos) { + public boolean isInGoal(int x, int y, int z) { return false; } @Override - public double heuristic(BlockPos pos) { + public double heuristic(int x, int y, int z) { return 0; } }); diff --git a/src/test/java/baritone/pathing/goals/GoalGetToBlockTest.java b/src/test/java/baritone/pathing/goals/GoalGetToBlockTest.java new file mode 100644 index 00000000..6234e050 --- /dev/null +++ b/src/test/java/baritone/pathing/goals/GoalGetToBlockTest.java @@ -0,0 +1,50 @@ +/* + * 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 . + */ + +package baritone.pathing.goals; + +import baritone.api.pathing.goals.GoalGetToBlock; +import net.minecraft.util.math.BlockPos; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertTrue; + +public class GoalGetToBlockTest { + + @Test + public void isInGoal() { + List acceptableOffsets = new ArrayList<>(Arrays.asList("0,0,0", "0,0,1", "0,0,-1", "1,0,0", "-1,0,0", "0,-1,1", "0,-1,-1", "1,-1,0", "-1,-1,0", "0,1,0", "0,-1,0", "0,-2,0")); + for (int x = -10; x <= 10; x++) { + for (int y = -10; y <= 10; y++) { + for (int z = -10; z <= 10; z++) { + boolean inGoal = new GoalGetToBlock(new BlockPos(0, 0, 0)).isInGoal(new BlockPos(x, y, z)); + String repr = x + "," + y + "," + z; + System.out.println(repr + " " + inGoal); + if (inGoal) { + assertTrue(repr, acceptableOffsets.contains(repr)); + acceptableOffsets.remove(repr); + } + } + } + } + assertTrue(acceptableOffsets.toString(), acceptableOffsets.isEmpty()); + } +} \ No newline at end of file diff --git a/src/test/java/baritone/pathing/movement/ActionCostsButOnlyTheOnesThatMakeMickeyDieInsideTest.java b/src/test/java/baritone/pathing/movement/ActionCostsTest.java similarity index 83% rename from src/test/java/baritone/pathing/movement/ActionCostsButOnlyTheOnesThatMakeMickeyDieInsideTest.java rename to src/test/java/baritone/pathing/movement/ActionCostsTest.java index 50ba6245..a3108c59 100644 --- a/src/test/java/baritone/pathing/movement/ActionCostsButOnlyTheOnesThatMakeMickeyDieInsideTest.java +++ b/src/test/java/baritone/pathing/movement/ActionCostsTest.java @@ -2,16 +2,16 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ @@ -19,10 +19,10 @@ package baritone.pathing.movement; import org.junit.Test; -import static baritone.pathing.movement.ActionCostsButOnlyTheOnesThatMakeMickeyDieInside.*; +import static baritone.api.pathing.movement.ActionCosts.*; import static org.junit.Assert.assertEquals; -public class ActionCostsButOnlyTheOnesThatMakeMickeyDieInsideTest { +public class ActionCostsTest { @Test public void testFallNBlocksCost() { assertEquals(FALL_N_BLOCKS_COST.length, 257); // Fall 0 blocks through fall 256 blocks diff --git a/src/test/java/baritone/utils/pathing/BetterBlockPosTest.java b/src/test/java/baritone/utils/pathing/BetterBlockPosTest.java index 3200969a..13b76c73 100644 --- a/src/test/java/baritone/utils/pathing/BetterBlockPosTest.java +++ b/src/test/java/baritone/utils/pathing/BetterBlockPosTest.java @@ -2,26 +2,32 @@ * This file is part of Baritone. * * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by + * 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 General Public License for more details. + * GNU Lesser General Public License for more details. * - * You should have received a copy of the GNU General Public License + * You should have received a copy of the GNU Lesser General Public License * along with Baritone. If not, see . */ package baritone.utils.pathing; +import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class BetterBlockPosTest { - //@Test + // disabled since this is a benchmark, not really a test. also including it makes the tests take 50 seconds for no reason + /*@Test public void benchMulti() { System.out.println("Benching up()"); for (int i = 0; i < 10; i++) { @@ -32,7 +38,42 @@ public class BetterBlockPosTest { for (int i = 0; i < 10; i++) { // eliminate any advantage to going first benchN(); + assertTrue(i<10); } + }*/ + + /** + * Make sure BetterBlockPos behaves just like BlockPos + */ + @Test + public void testSimple() { + BlockPos pos = new BlockPos(1, 2, 3); + BetterBlockPos better = new BetterBlockPos(1, 2, 3); + assertEquals(pos, better); + assertEquals(pos.up(), better.up()); + assertEquals(pos.down(), better.down()); + assertEquals(pos.north(), better.north()); + assertEquals(pos.south(), better.south()); + assertEquals(pos.east(), better.east()); + assertEquals(pos.west(), better.west()); + for (EnumFacing dir : EnumFacing.values()) { + assertEquals(pos.offset(dir), better.offset(dir)); + assertEquals(pos.offset(dir, 0), pos); + assertEquals(better.offset(dir, 0), better); + for (int i = -10; i < 10; i++) { + assertEquals(pos.offset(dir, i), better.offset(dir, i)); + } + assertTrue(better.offset(dir, 0) == better); + } + for (int i = -10; i < 10; i++) { + assertEquals(pos.up(i), better.up(i)); + assertEquals(pos.down(i), better.down(i)); + assertEquals(pos.north(i), better.north(i)); + assertEquals(pos.south(i), better.south(i)); + assertEquals(pos.east(i), better.east(i)); + assertEquals(pos.west(i), better.west(i)); + } + assertTrue(better.offset(null, 0) == better); } public void benchOne() { diff --git a/src/test/java/baritone/utils/pathing/PathingBlockTypeTest.java b/src/test/java/baritone/utils/pathing/PathingBlockTypeTest.java new file mode 100644 index 00000000..1582b66f --- /dev/null +++ b/src/test/java/baritone/utils/pathing/PathingBlockTypeTest.java @@ -0,0 +1,32 @@ +/* + * 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 . + */ + +package baritone.utils.pathing; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class PathingBlockTypeTest { + @Test + public void testBits() { + for (PathingBlockType type : PathingBlockType.values()) { + boolean[] bits = type.getBits(); + assertTrue(type == PathingBlockType.fromBits(bits[0], bits[1])); + } + } +} \ No newline at end of file