Compare commits

..

99 Commits

Author SHA1 Message Date
Brady 9a33c5cd9f Merge branch 'master' into bot-system 2020-01-01 19:23:01 -06:00
Brady 9f5f275a17 Merge branch 'master' into bot-system 2019-10-07 09:42:35 -05:00
Brady ac4895823e Remove comms 2019-10-04 15:52:08 -05:00
Brady 62cea04080 Fix compiler errors 2019-10-04 15:51:44 -05:00
Brady d772a97a0b Fix 2019-10-04 10:22:06 -05:00
Brady 7af0ed6ea1 Merge conflicts 2019-10-04 10:19:35 -05:00
Brady fe3f3a66ce Format bot code 2019-01-22 13:30:11 -06:00
Brady 9c5f82c814 Merge branch 'master' into bot-system 2019-01-18 13:52:22 -06:00
Brady 7c66762f48 Bot system API exposure 2019-01-17 14:43:44 -06:00
Leijurv 830c8190de Merge branch 'comms' into bot-system 2019-01-17 12:18:27 -08:00
Leijurv 47b258d7a4 Merge branch 'master' into comms 2019-01-17 12:16:45 -08:00
Brady df80858c49 Remove duplicate MovementInput implementation, Fixes #312 2019-01-16 13:55:24 -06:00
Brady 5dec544802 Minor fix LOL 2019-01-15 14:59:56 -06:00
Brady 494c056613 Resolve merge conflicts 2019-01-15 14:53:05 -06:00
Brady c0e947f016 Clean up canBreak 2018-12-24 12:23:57 -06:00
Brady c6ce5ea160 Nobody cares about creative mode 2018-12-24 12:19:09 -06:00
Brady 7b2930d5e5 Bot Breaking that is moderately cursed
DMCA gang
2018-12-24 12:11:28 -06:00
Brady 44ca284717 Merge branch 'master' into bot-system 2018-12-18 19:36:10 -06:00
Leijurv 380a645a6c only report items that are actually in the echest 2018-12-17 19:51:24 -08:00
Leijurv 0249bd5dd7 a few more packets, and consistent indexing 2018-12-17 15:15:20 -08:00
Leijurv 8cd8a95763 little fix 2018-12-16 20:14:07 -08:00
Brady 029a2b7f3e Fix NullPointerException 2018-12-15 12:27:19 -06:00
Leijurv 767d0c8ec1 better reporting 2018-12-14 21:57:20 -08:00
Brady 8febed2e42 Remove dependency for PlayerControllerMP implementation 2018-12-14 17:24:07 -06:00
Leijurv 37b1604e5d Merge branch 'master' into comms 2018-12-14 09:38:40 -08:00
Leijurv 82d15570f3 fix rare exception 2018-12-02 16:05:21 -08:00
Leijurv 2c2c420b3a Merge branch 'comms' into bot-system 2018-12-02 13:35:40 -08:00
Leijurv 1422b0a149 Merge branch 'master' into bot-system 2018-12-02 13:35:23 -08:00
Leijurv 6b6dd916b4 Merge branch 'calc-request' into comms 2018-11-23 19:09:01 -08:00
Leijurv 11e44acf65 helper to handle pending msgs 2018-11-23 16:35:03 -08:00
Leijurv 16fec4a1a0 buffered connection creation helper 2018-11-23 16:09:59 -08:00
Leijurv bbded21afb Merge branch 'master' into bot-system 2018-11-23 14:12:02 -08:00
Leijurv 5ae4f23886 Merge branch 'comms' into calc-request 2018-11-23 13:34:48 -08:00
Leijurv f222980a1a move comms to cabaletta.comms 2018-11-23 13:32:18 -08:00
Leijurv c57f65f832 complete new segmented calculation system 2018-11-23 13:17:03 -08:00
Leijurv 85a6ec022e Merge branch 'comms' into calc-request 2018-11-23 13:13:35 -08:00
Leijurv c1032da828 Merge branch 'master' into comms 2018-11-23 13:12:38 -08:00
Leijurv e0d894d296 computation request and response 2018-11-23 12:09:35 -08:00
Leijurv 27c818f873 Merge branch 'comms' into calc-request 2018-11-23 11:49:49 -08:00
Leijurv fdd758bc90 too much log spam 2018-11-23 11:48:01 -08:00
Leijurv 3a2620192b too much log spam 2018-11-23 11:46:47 -08:00
Leijurv c423d5f575 report path start position 2018-11-23 11:35:13 -08:00
Leijurv 81a9b71429 Merge branch 'segment-calculation' into comms 2018-11-23 10:36:56 -08:00
Leijurv 81ecc209d3 synchronize partial reads and writes to a socket 2018-11-23 10:09:13 -08:00
Leijurv 0dc67593bb lots more status 2018-11-18 21:56:46 -08:00
Leijurv 2e180e81ed Merge branch 'comms' of github.com:cabaletta/baritone into comms 2018-11-18 21:42:04 -08:00
Leijurv 0b11057449 Merge branch 'master' into comms 2018-11-18 21:41:50 -08:00
Brady 186652a8d8 Protocol lol 2018-11-18 19:52:11 -06:00
Leijurv 168c151901 Merge branch 'comms' into bot-system 2018-11-18 17:39:35 -08:00
Leijurv 18d8cfb6de Merge branch 'master' into comms 2018-11-18 17:39:26 -08:00
Leijurv f99befd307 oh thats important 2018-11-18 12:04:37 -08:00
Leijurv 9ad35dbf28 remove the useless stuff 2018-11-18 11:35:54 -08:00
Leijurv dfb49179c5 not a handler lol 2018-11-18 11:27:53 -08:00
Brady 3c913a7b85 Fix jar export 2018-11-18 13:27:25 -06:00
Leijurv f01cf669e8 wtf 2018-11-18 11:06:40 -08:00
Leijurv 2d87033f49 f 2018-11-18 11:06:11 -08:00
Leijurv f014e42aa4 initial comms 2018-11-18 11:01:46 -08:00
Brady 46de72e28c Comms Sourceset 2018-11-17 18:07:16 -06:00
Brady 3d5cf9772e Less cancer 2018-11-14 20:55:37 -06:00
Leijurv 7cb38352ac bots 2018-11-14 17:17:52 -08:00
Leijurv 42c78337c7 Merge branch 'master' into bot-system 2018-11-14 16:41:52 -08:00
Brady 0f81212f17 Compile fix 2018-11-13 21:41:52 -06:00
Brady ad0041c2c5 Merge branch 'master' into bot-system 2018-11-13 17:14:29 -06:00
Brady 19e7585cd2 Merge branch 'master' into bot-system 2018-11-11 16:23:47 -06:00
Brady 3aeb29ab22 Merge branch 'master' into bot-system 2018-11-11 13:36:22 -06:00
Brady 8dfe5dfd32 Fix jce.jar not being included as library jar in proguard config 2018-11-09 22:43:00 -06:00
Brady 90236962c4 nice 2018-11-09 22:17:00 -06:00
Brady 2e9e8c1ea1 Actually entirely epic, we're okay 2018-11-09 22:00:11 -06:00
Brady 4bf659e14e Fix ConcurrentModificationException 2018-11-09 21:10:49 -06:00
Brady ceca258867 MORE handlers
also removed scoreboard handlers because lol
2018-11-09 20:50:43 -06:00
Leijurv abda4b3a31 begone 2018-11-09 13:28:49 -08:00
Brady 98664540e2 Merge branch 'master' into bot-system 2018-11-09 14:42:23 -06:00
Brady 484dac66b7 JUMP 2018-11-09 13:58:55 -06:00
Brady 40282cd140 Automatic Disconnect 2018-11-07 16:53:32 -06:00
Brady 41c74cb08c More handlers 2018-11-07 12:23:28 -06:00
Brady 7c92817801 Offline bot testing 2018-11-07 12:01:26 -06:00
Brady 1d56585c67 Fix success connection result 2018-11-06 16:22:24 -06:00
Brady a4ac9c6f8d Bot Connecting 2018-11-06 15:25:25 -06:00
Brady 42d15a7b93 Merge branch 'master' into bot-system 2018-11-06 14:10:11 -06:00
Brady 335c97bae6 Merge branch 'master' into bot-system 2018-11-05 16:06:53 -06:00
Brady 8a8afddce3 Fix bad stack overflow error 2018-10-30 13:57:50 -05:00
Brady c3f6ee87b3 Feed codacy 2018-10-29 23:27:54 -05:00
Brady f45fb3cd8c Add reminder lol 2018-10-29 23:20:11 -05:00
Brady 71c7ed54e5 Reverse increment/decrement 2018-10-29 23:10:46 -05:00
Brady 4f978be2a2 Begin MovementInput implementation 2018-10-29 23:04:26 -05:00
Brady 133d956b3a Create login handler 2018-10-29 22:43:36 -05:00
Brady 095e452632 Merge branch 'master' into bot-system 2018-10-29 22:08:29 -05:00
Brady 047d7f06b8 More handlers 2018-10-26 11:38:52 -05:00
Brady 09a119c4ca More handlers 2018-10-24 20:51:01 -05:00
Brady 746e1f6652 handleTimeUpdate 2018-10-24 19:04:49 -05:00
Brady 1d22cf63f0 Lol 2018-10-23 23:08:43 -05:00
Brady d4b3e71694 handleCombatEvent 2018-10-23 23:07:58 -05:00
Brady a08b406af9 handleCooldown 2018-10-23 23:04:13 -05:00
Brady 1afd367e53 handleResourcePack 2018-10-23 23:00:58 -05:00
Brady 59e920b7b1 Meme 3 2018-10-23 09:58:36 -05:00
Brady 79d230d924 another thought 2018-10-23 00:49:38 -05:00
Brady 29cf79fe17 We don't need the connection handler from the user 2018-10-23 00:46:31 -05:00
Brady 8e75817e29 Meme 2 2018-10-23 00:29:30 -05:00
Brady c6bd3f4f00 Meme 2018-10-23 00:05:48 -05:00
168 changed files with 5018 additions and 2317 deletions
-2
View File
@@ -11,8 +11,6 @@ build/
classes/
*.class
/out
# IntelliJ Files
.idea/
*.iml
+1 -1
View File
@@ -10,7 +10,7 @@ install:
script:
- docker run --rm cabaletta/baritone ./gradlew javadoc
- docker run --name baritone 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 runAutoTest; cat /code/autotest/success"
- docker run --name baritone cabaletta/baritone /bin/sh -c "set -e; /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"
- docker cp baritone:/code/dist dist
- ls dist
- cat dist/checksums.txt
+36
View File
@@ -0,0 +1,36 @@
# Baritone Comms Protocol
## Data Types
| Name | Descriptor | Java |
|------------|-----------------------------------------------------------|-----------------------------|
| coordinate | Big endian 8-byte floating point number | [readDouble], [writeDouble] |
| string | unsigned short (length) followed by UTF-8 character bytes | [readUTF], [writeUTF] |
## Inbound
Allows the server to execute a chat command on behalf of the client's player
### Chat
| Name | Type |
|---------|--------|
| Message | string |
## Outbound
Update the player position with the server
### Status
| Name | Type |
|------|------------|
| X | coordinate |
| Y | coordinate |
| Z | coordinate |
<!-- External links -->
[readUTF]: https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#readUTF()
[writeUTF]: https://docs.oracle.com/javase/7/docs/api/java/io/DataOutputStream.html#writeUTF(java.lang.String)
[readDouble]: https://docs.oracle.com/javase/7/docs/api/java/io/DataInputStream.html#readDouble()
[writeDouble]: https://docs.oracle.com/javase/7/docs/api/java/io/DataOutputStream.html#writeDouble(double)
+13 -68
View File
@@ -16,7 +16,7 @@
*/
group 'baritone'
version '1.5.1'
version '1.2.10'
buildscript {
repositories {
@@ -25,24 +25,24 @@ buildscript {
url = 'http://files.minecraftforge.net/maven'
}
maven {
name = 'impactdevelopment-repo'
url = 'https://impactdevelopment.github.io/maven/'
name = 'SpongePowered'
url = 'http://repo.spongepowered.org/maven'
}
jcenter()
}
dependencies {
classpath group: 'com.github.ImpactDevelopment', name: 'ForgeGradle', version: '3.0.115'
classpath group: 'com.github.ImpactDevelopment', name: 'MixinGradle', version: '0.6.2'
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
classpath 'org.spongepowered:mixingradle:0.6-SNAPSHOT'
}
}
import baritone.gradle.task.CreateDistTask
import baritone.gradle.task.ProguardTask
import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'java'
apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'net.minecraftforge.gradle.tweaker-client'
apply plugin: 'org.spongepowered.mixin'
sourceCompatibility = targetCompatibility = '1.8'
@@ -52,19 +52,8 @@ compileJava {
}
sourceSets {
api {
compileClasspath += main.compileClasspath
}
main {
compileClasspath += api.output
}
test {
compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output
runtimeClasspath += main.compileClasspath + main.runtimeClasspath + main.output
}
launch {
compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output
runtimeClasspath += main.compileClasspath + main.runtimeClasspath + main.output
}
schematica_api {
@@ -76,51 +65,14 @@ sourceSets {
}
}
task sourceJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
from sourceSets.api.allSource
}
minecraft {
mappings channel: 'snapshot', version: '20200213-1.15.1'
reobfMappings 'notch'
version = '1.12.2'
mappings = 'stable_39'
tweakClass = 'baritone.launch.BaritoneTweaker'
runDir = 'run'
runs {
client {
workingDirectory project.file('run')
source sourceSets.launch
main 'baritone.launch.LaunchTesting'
environment 'assetIndex', '{asset_index}'
environment 'assetDirectory', downloadAssets.output
environment 'nativesDirectory', extractNatives.output
environment 'tweakClass', 'baritone.launch.BaritoneTweaker'
if (Os.isFamily(Os.FAMILY_MAC)) {
jvmArgs "-XstartOnFirstThread"
}
}
autoTest {
workingDirectory project.file('autotest')
source sourceSets.launch
main 'baritone.launch.LaunchTesting'
environment 'assetIndex', '{asset_index}'
environment 'assetDirectory', downloadAssets.output
environment 'nativesDirectory', extractNatives.output
environment 'tweakClass', 'baritone.launch.BaritoneTweaker'
environment 'BARITONE_AUTO_TEST', 'true'
if (Os.isFamily(Os.FAMILY_MAC)) {
jvmArgs "-XstartOnFirstThread"
}
}
}
// The sources jar should use SRG names not MCP to ensure compatibility with all mappings
makeObfSourceJar = true
}
repositories {
@@ -138,12 +90,6 @@ repositories {
}
dependencies {
minecraft 'com.github.ImpactDevelopment:Vanilla:1.15.2'
runtime launchCompile('net.minecraft:launchwrapper:1.12') {
exclude module: 'lwjgl'
}
runtime launchCompile('org.ow2.asm:asm-debug-all:5.2')
runtime launchCompile('com.github.ImpactDevelopment:SimpleTweaker:1.2')
runtime launchCompile('org.spongepowered:mixin:0.7.11-SNAPSHOT') {
// Mixin includes a lot of dependencies that are too up-to-date
@@ -153,7 +99,6 @@ dependencies {
exclude module: 'commons-io'
exclude module: 'log4j-core'
}
testImplementation 'junit:junit:4.12'
}
@@ -40,13 +40,17 @@ class BaritoneGradleTask extends DefaultTask {
PROGUARD_STANDALONE_CONFIG = "standalone.pro",
PROGUARD_EXPORT_PATH = "proguard_out.jar",
TEMP_LIBRARY_DIR = "tempLibraries/",
ARTIFACT_STANDARD = "%s-%s.jar",
ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar",
ARTIFACT_API = "%s-api-%s.jar",
ARTIFACT_STANDALONE = "%s-standalone-%s.jar";
ARTIFACT_STANDALONE = "%s-standalone-%s.jar",
ARTIFACT_FORGE_API = "%s-api-forge-%s.jar",
ARTIFACT_FORGE_STANDALONE = "%s-standalone-forge-%s.jar";
protected String artifactName, artifactVersion;
protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, proguardOut;
protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, artifactForgeApiPath, artifactForgeStandalonePath, proguardOut;
protected void verifyArtifacts() throws IllegalStateException {
this.artifactName = getProject().getName();
@@ -56,6 +60,8 @@ class BaritoneGradleTask extends DefaultTask {
this.artifactUnoptimizedPath = this.getBuildFile(formatVersion(ARTIFACT_UNOPTIMIZED));
this.artifactApiPath = this.getBuildFile(formatVersion(ARTIFACT_API));
this.artifactStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_STANDALONE));
this.artifactForgeApiPath = this.getBuildFile(formatVersion(ARTIFACT_FORGE_API));
this.artifactForgeStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_FORGE_STANDALONE));
this.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH);
@@ -45,6 +45,8 @@ public class CreateDistTask extends BaritoneGradleTask {
Path api = getRelativeFile("dist/" + formatVersion(ARTIFACT_API));
Path standalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_STANDALONE));
Path unoptimized = getRelativeFile("dist/" + formatVersion(ARTIFACT_UNOPTIMIZED));
Path forgeApi = getRelativeFile("dist/" + formatVersion(ARTIFACT_FORGE_API));
Path forgeStandalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_FORGE_STANDALONE));
// NIO will not automatically create directories
Path dir = getRelativeFile("dist/");
@@ -56,9 +58,11 @@ public class CreateDistTask extends BaritoneGradleTask {
Files.copy(this.artifactApiPath, api, REPLACE_EXISTING);
Files.copy(this.artifactStandalonePath, standalone, REPLACE_EXISTING);
Files.copy(this.artifactUnoptimizedPath, unoptimized, REPLACE_EXISTING);
Files.copy(this.artifactForgeApiPath, forgeApi, REPLACE_EXISTING);
Files.copy(this.artifactForgeStandalonePath, forgeStandalone, REPLACE_EXISTING);
// Calculate all checksums and format them like "shasum"
List<String> shasum = Stream.of(api, standalone, unoptimized)
List<String> shasum = Stream.of(api, forgeApi, standalone, forgeStandalone, unoptimized)
.map(path -> sha1(path) + " " + path.getFileName().toString())
.collect(Collectors.toList());
@@ -18,18 +18,27 @@
package baritone.gradle.task;
import baritone.gradle.util.Determinizer;
import baritone.gradle.util.MappingType;
import baritone.gradle.util.ReobfWrapper;
import org.apache.commons.io.IOUtils;
import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.NamedDomainObjectContainer;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.internal.plugins.DefaultConvention;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.TaskAction;
import org.gradle.internal.Pair;
import java.io.*;
import java.lang.reflect.Field;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import java.nio.file.Paths;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
@@ -41,12 +50,18 @@ import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
*/
public class ProguardTask extends BaritoneGradleTask {
private static final Pattern TEMP_LIBRARY_PATTERN = Pattern.compile("-libraryjars 'tempLibraries\\/([a-zA-Z0-9/_\\-\\.]+)\\.jar'");
@Input
private String url;
@Input
private String extract;
private List<String> requiredLibraries;
private File mixin;
@TaskAction
protected void exec() throws Exception {
super.verifyArtifacts();
@@ -56,6 +71,7 @@ public class ProguardTask extends BaritoneGradleTask {
downloadProguard();
extractProguard();
generateConfigs();
acquireDependencies();
proguardApi();
proguardStandalone();
cleanup();
@@ -66,7 +82,7 @@ public class ProguardTask extends BaritoneGradleTask {
Files.delete(this.artifactUnoptimizedPath);
}
Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString());
Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString(), Optional.empty());
}
private void downloadProguard() throws Exception {
@@ -98,19 +114,7 @@ public class ProguardTask extends BaritoneGradleTask {
Process p = new ProcessBuilder("java", "-verbose").start();
String out = IOUtils.toString(p.getInputStream(), "UTF-8").split("\n")[0].split("Opened ")[1].replace("]", "");
template.add(2, "-libraryjars '" + out + "'");
// Discover all of the libraries that we will need to acquire from gradle
acquireDependencies().forEach(f -> {
if (f.toString().endsWith("-recomp.jar")) {
// remove MCP mapped jar
return;
}
if (f.toString().endsWith("client-extra.jar")) {
// go from the extra to the original downloaded client
f = new File(f.getParentFile(), "client.jar");
}
template.add(2, "-libraryjars '" + f + "'");
});
template.add(3, "-libraryjars '" + Paths.get(out).resolveSibling("jce.jar") + "'");
// API config doesn't require any changes from the changes that we made to the template
Files.write(getTemporaryFile(PROGUARD_API_CONFIG), template);
@@ -119,20 +123,165 @@ public class ProguardTask extends BaritoneGradleTask {
List<String> standalone = new ArrayList<>(template);
standalone.removeIf(s -> s.contains("# this is the keep api"));
Files.write(getTemporaryFile(PROGUARD_STANDALONE_CONFIG), standalone);
// Discover all of the libraries that we will need to acquire from gradle
this.requiredLibraries = new ArrayList<>();
template.forEach(line -> {
if (!line.startsWith("#")) {
Matcher m = TEMP_LIBRARY_PATTERN.matcher(line);
if (m.find()) {
this.requiredLibraries.add(m.group(1));
}
}
});
}
private Stream<File> acquireDependencies() {
return getProject().getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().findByName("launch").getRuntimeClasspath().getFiles().stream().filter(File::isFile);
private void acquireDependencies() throws Exception {
// Create a map of all of the dependencies that we are able to access in this project
// Likely a better way to do this, I just pair the dependency with the first valid configuration
Map<String, Pair<Configuration, Dependency>> dependencyLookupMap = new HashMap<>();
getProject().getConfigurations().stream().filter(Configuration::isCanBeResolved).forEach(config ->
config.getAllDependencies().forEach(dependency ->
dependencyLookupMap.putIfAbsent(dependency.getName() + "-" + dependency.getVersion(), Pair.of(config, dependency))));
// Create the directory if it doesn't already exist
Path tempLibraries = getTemporaryFile(TEMP_LIBRARY_DIR);
if (!Files.exists(tempLibraries)) {
Files.createDirectory(tempLibraries);
}
// Iterate the required libraries to copy them to tempLibraries
for (String lib : this.requiredLibraries) {
// copy from the forgegradle cache
if (lib.equals("minecraft")) {
Path cachedJar = getMinecraftJar();
Path inTempDir = getTemporaryFile("tempLibraries/minecraft.jar");
// TODO: maybe try not to copy every time
Files.copy(cachedJar, inTempDir, REPLACE_EXISTING);
continue;
}
// Find a configuration/dependency pair that matches the desired library
Pair<Configuration, Dependency> pair = null;
for (Map.Entry<String, Pair<Configuration, Dependency>> entry : dependencyLookupMap.entrySet()) {
if (entry.getKey().startsWith(lib)) {
pair = entry.getValue();
}
}
// The pair must be non-null
Objects.requireNonNull(pair);
// Find the library jar file, and copy it to tempLibraries
for (File file : pair.getLeft().files(pair.getRight())) {
if (file.getName().startsWith(lib)) {
if (lib.contains("mixin")) {
mixin = file;
}
Files.copy(file.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), REPLACE_EXISTING);
}
}
}
if (mixin == null) {
throw new IllegalStateException("Unable to find mixin jar");
}
}
// a bunch of epic stuff to get the path to the cached jar
private Path getMinecraftJar() throws Exception {
MappingType mappingType;
try {
mappingType = getMappingType();
} catch (Exception e) {
System.err.println("Failed to get mapping type, assuming NOTCH.");
mappingType = MappingType.NOTCH;
}
String suffix;
switch (mappingType) {
case NOTCH:
suffix = "";
break;
case SEARGE:
suffix = "-srgBin";
break;
case CUSTOM:
throw new IllegalStateException("Custom mappings not supported!");
default:
throw new IllegalStateException("Unknown mapping type: " + mappingType);
}
DefaultConvention convention = (DefaultConvention) this.getProject().getConvention();
Object extension = convention.getAsMap().get("minecraft");
Objects.requireNonNull(extension);
// for some reason cant use Class.forName
Class<?> class_baseExtension = extension.getClass().getSuperclass().getSuperclass().getSuperclass(); // <-- cursed
Field f_replacer = class_baseExtension.getDeclaredField("replacer");
f_replacer.setAccessible(true);
Object replacer = f_replacer.get(extension);
Class<?> class_replacementProvider = replacer.getClass();
Field replacement_replaceMap = class_replacementProvider.getDeclaredField("replaceMap");
replacement_replaceMap.setAccessible(true);
Map<String, Object> replacements = (Map) replacement_replaceMap.get(replacer);
String cacheDir = replacements.get("CACHE_DIR").toString() + "/net/minecraft";
String mcVersion = replacements.get("MC_VERSION").toString();
String mcpInsert = replacements.get("MAPPING_CHANNEL").toString() + "/" + replacements.get("MAPPING_VERSION").toString();
String fullJarName = "minecraft-" + mcVersion + suffix + ".jar";
String baseDir = String.format("%s/minecraft/%s/", cacheDir, mcVersion);
String jarPath;
if (mappingType == MappingType.SEARGE) {
jarPath = String.format("%s/%s/%s", baseDir, mcpInsert, fullJarName);
} else {
jarPath = baseDir + fullJarName;
}
jarPath = jarPath
.replace("/", File.separator)
.replace("\\", File.separator); // hecking regex
return new File(jarPath).toPath();
}
// throws IllegalStateException if mapping type is ambiguous or it fails to find it
private MappingType getMappingType() {
// if it fails to find this then its probably a forgegradle version problem
Set<Object> reobf = (NamedDomainObjectContainer<Object>) this.getProject().getExtensions().getByName("reobf");
List<MappingType> mappingTypes = getUsedMappingTypes(reobf);
long mappingTypesUsed = mappingTypes.size();
if (mappingTypesUsed == 0) {
throw new IllegalStateException("Failed to find mapping type (no jar task?)");
}
if (mappingTypesUsed > 1) {
throw new IllegalStateException("Ambiguous mapping type (multiple jars with different mapping types?)");
}
return mappingTypes.get(0);
}
private List<MappingType> getUsedMappingTypes(Set<Object> reobf) {
return reobf.stream()
.map(ReobfWrapper::new)
.map(ReobfWrapper::getMappingType)
.distinct()
.collect(Collectors.toList());
}
private void proguardApi() throws Exception {
runProguard(getTemporaryFile(PROGUARD_API_CONFIG));
Determinizer.determinize(this.proguardOut.toString(), this.artifactApiPath.toString());
Determinizer.determinize(this.proguardOut.toString(), this.artifactApiPath.toString(), Optional.empty());
Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeApiPath.toString(), Optional.of(mixin));
}
private void proguardStandalone() throws Exception {
runProguard(getTemporaryFile(PROGUARD_STANDALONE_CONFIG));
Determinizer.determinize(this.proguardOut.toString(), this.artifactStandalonePath.toString());
Determinizer.determinize(this.proguardOut.toString(), this.artifactStandalonePath.toString(), Optional.empty());
Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeStandalonePath.toString(), Optional.of(mixin));
}
private void cleanup() {
@@ -22,10 +22,7 @@ import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import java.io.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
@@ -39,7 +36,7 @@ import java.util.stream.Collectors;
*/
public class Determinizer {
public static void determinize(String inputPath, String outputPath) throws IOException {
public static void determinize(String inputPath, String outputPath, Optional<File> toInclude) throws IOException {
System.out.println("Running Determinizer");
System.out.println(" Input path: " + inputPath);
System.out.println(" Output path: " + outputPath);
@@ -66,10 +63,30 @@ public class Determinizer {
if (entry.getName().endsWith(".refmap.json")) {
JsonObject object = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry))).getAsJsonObject();
jos.write(writeSorted(object).getBytes());
} else if (entry.getName().equals("META-INF/MANIFEST.MF") && toInclude.isPresent()) { // only replace for forge jar
ByteArrayOutputStream cancer = new ByteArrayOutputStream();
copy(jarFile.getInputStream(entry), cancer);
String manifest = new String(cancer.toByteArray());
if (!manifest.contains("baritone.launch.BaritoneTweaker")) {
throw new IllegalStateException("unable to replace");
}
manifest = manifest.replace("baritone.launch.BaritoneTweaker", "org.spongepowered.asm.launch.MixinTweaker");
jos.write(manifest.getBytes());
} else {
copy(jarFile.getInputStream(entry), jos);
}
}
if (toInclude.isPresent()) {
try (JarFile mixin = new JarFile(toInclude.get())) {
for (JarEntry entry : mixin.stream().sorted(Comparator.comparing(JarEntry::getName)).collect(Collectors.toList())) {
if (entry.getName().startsWith("META-INF") && !entry.getName().startsWith("META-INF/services")) {
continue;
}
jos.putNextEntry(entry);
copy(mixin.getInputStream(entry), jos);
}
}
}
jos.finish();
}
}
@@ -15,20 +15,15 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils.accessor;
package baritone.gradle.util;
import net.minecraft.world.chunk.Chunk;
import java.util.concurrent.atomic.AtomicReferenceArray;
public interface IChunkArray {
void copyFrom(IChunkArray other);
AtomicReferenceArray<Chunk> getChunks();
int centerX();
int centerZ();
int viewDistance();
/**
* All credits go to AsmLibGradle and its contributors.
*
* @see <a href="https://github.com/pozzed/AsmLibGradle/blob/8f917dbc3939eab7a3d9daf54d9d285fdf34f4b2/src/main/java/net/futureclient/asmlib/forgegradle/MappingType.java">Original Source</a>
*/
public enum MappingType {
SEARGE,
NOTCH,
CUSTOM // forgegradle
}
@@ -0,0 +1,63 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.gradle.util;
import java.lang.reflect.Field;
import java.util.Objects;
/**
* All credits go to AsmLibGradle and its contributors.
*
* @see <a href="https://github.com/pozzed/AsmLibGradle/blob/8f917dbc3939eab7a3d9daf54d9d285fdf34f4b2/src/main/java/net/futureclient/asmlib/forgegradle/ReobfWrapper.java">Original Source</a>
*/
public class ReobfWrapper {
private final Object instance;
private final Class<?> type;
public ReobfWrapper(Object instance) {
this.instance = instance;
Objects.requireNonNull(instance);
this.type = instance.getClass();
}
public String getName() {
try {
Field nameField = type.getDeclaredField("name");
nameField.setAccessible(true);
return (String) nameField.get(this.instance);
} catch (ReflectiveOperationException ex) {
throw new IllegalStateException(ex);
}
}
public MappingType getMappingType() {
try {
Field enumField = type.getDeclaredField("mappingType");
enumField.setAccessible(true);
Enum<?> aEnum = (Enum<?>) enumField.get(this.instance);
MappingType mappingType = MappingType.values()[aEnum.ordinal()];
if (!aEnum.name().equals(mappingType.name())) {
throw new IllegalStateException("ForgeGradle ReobfMappingType is not equivalent to MappingType (version error?)");
}
return mappingType;
} catch (ReflectiveOperationException ex) {
throw new IllegalStateException(ex);
}
}
}
+49 -2
View File
@@ -14,8 +14,6 @@
# lwjgl is weird
-dontwarn org.lwjgl.**
# also lwjgl lol
-dontwarn module-info
-keep class baritone.api.** { *; } # this is the keep api
@@ -38,6 +36,55 @@
#proguard doesnt like it when it cant find our fake schematica classes
-dontwarn baritone.utils.schematic.schematica.**
# copy all necessary libraries into tempLibraries to build
# The correct jar will be copied from the forgegradle cache based on the mapping type being compiled with
-libraryjars 'tempLibraries/minecraft.jar'
-libraryjars 'tempLibraries/SimpleTweaker-1.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/jinput-2.0.5.jar'
-libraryjars 'tempLibraries/jna-4.4.0.jar'
-libraryjars 'tempLibraries/jopt-simple-5.0.3.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'
# startsWith is used to check the library, and mac/linux differ in which version they use
# this is FINE
-libraryjars 'tempLibraries/lwjgl-.jar'
-libraryjars 'tempLibraries/lwjgl_util-.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.11-SNAPSHOT.jar'
-libraryjars 'tempLibraries/launchwrapper-1.11.jar' # TODO why does only 1.11.jar exist?
# Keep - Applications. Keep all application classes, along with their 'main'
# methods.
@@ -17,11 +17,12 @@
package baritone.api;
import baritone.api.bot.IUserManager;
import baritone.api.cache.IWorldScanner;
import baritone.api.command.ICommand;
import baritone.api.command.ICommandSystem;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import baritone.api.schematic.ISchematicSystem;
import net.minecraft.client.entity.EntityPlayerSP;
import java.util.List;
import java.util.Objects;
@@ -47,19 +48,19 @@ public interface IBaritoneProvider {
* returned by {@link #getPrimaryBaritone()}.
*
* @return All active {@link IBaritone} instances.
* @see #getBaritoneForPlayer(ClientPlayerEntity)
* @see #getBaritoneForPlayer(EntityPlayerSP)
*/
List<IBaritone> getAllBaritones();
/**
* Provides the {@link IBaritone} instance for a given {@link ClientPlayerEntity}. This will likely be
* Provides the {@link IBaritone} instance for a given {@link EntityPlayerSP}. This will likely be
* replaced with or be overloaded in addition to {@code #getBaritoneForUser(IBaritoneUser)} when
* {@code bot-system} is merged into {@code master}.
*
* @param player The player
* @return The {@link IBaritone} instance.
*/
default IBaritone getBaritoneForPlayer(ClientPlayerEntity player) {
default IBaritone getBaritoneForPlayer(EntityPlayerSP player) {
for (IBaritone baritone : getAllBaritones()) {
if (Objects.equals(player, baritone.getPlayerContext().player())) {
return baritone;
@@ -69,13 +70,18 @@ public interface IBaritoneProvider {
}
/**
* Returns the {@link IWorldScanner} instance. This is not a type returned by
* {@link IBaritone} implementation, because it is not linked with {@link IBaritone}.
* Returns the {@link IWorldScanner} instance. This is not a type returned by a
* {@link IBaritone} implementation because it is not linked with {@link IBaritone}.
*
* @return The {@link IWorldScanner} instance.
*/
IWorldScanner getWorldScanner();
/**
* @return The {@link IUserManager} instance.
*/
IUserManager getUserManager();
/**
* Returns the {@link ICommandSystem} instance. This is not bound to a specific {@link IBaritone}
* instance because {@link ICommandSystem} itself controls global behavior for {@link ICommand}s.
+11 -18
View File
@@ -20,8 +20,8 @@ package baritone.api;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.TypeUtils;
import net.minecraft.block.Block;
import net.minecraft.block.Blocks;
import net.minecraft.client.Minecraft;
import net.minecraft.init.Blocks;
import net.minecraft.item.Item;
import net.minecraft.util.math.Vec3i;
import net.minecraft.util.text.ITextComponent;
@@ -30,8 +30,8 @@ import java.awt.*;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.*;
import java.util.List;
import java.util.function.Consumer;
/**
@@ -158,10 +158,10 @@ public final class Settings {
* Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.)
*/
public final Setting<List<Item>> acceptableThrowawayItems = new Setting<>(new ArrayList<>(Arrays.asList(
Blocks.DIRT.asItem(),
Blocks.COBBLESTONE.asItem(),
Blocks.NETHERRACK.asItem(),
Blocks.STONE.asItem()
Item.getItemFromBlock(Blocks.DIRT),
Item.getItemFromBlock(Blocks.COBBLESTONE),
Item.getItemFromBlock(Blocks.NETHERRACK),
Item.getItemFromBlock(Blocks.STONE)
)));
/**
@@ -177,8 +177,11 @@ public final class Settings {
public final Setting<List<Block>> blocksToAvoidBreaking = new Setting<>(new ArrayList<>(Arrays.asList( // TODO can this be a HashSet or ImmutableSet?
Blocks.CRAFTING_TABLE,
Blocks.FURNACE,
Blocks.LIT_FURNACE,
Blocks.CHEST,
Blocks.TRAPPED_CHEST
Blocks.TRAPPED_CHEST,
Blocks.STANDING_SIGN,
Blocks.WALL_SIGN
)));
/**
@@ -259,11 +262,6 @@ public final class Settings {
*/
public final Setting<Integer> rightClickSpeed = new Setting<>(4);
/**
* How many degrees to randomize the yaw every tick. Set to 0 to disable
*/
public final Setting<Double> randomLooking113 = new Setting<>(2d);
/**
* Block reach distance
*/
@@ -956,12 +954,7 @@ public final class Settings {
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
* {@link Setting#value};
*/
public final Setting<Consumer<ITextComponent>> logger = new Setting<>(Minecraft.getInstance().ingameGUI.getChatGUI()::printChatMessage);
/**
* Print out ALL command exceptions as a stack trace to stdout, even simple syntax errors
*/
public final Setting<Boolean> verboseCommandExceptions = new Setting<>(false);
public final Setting<Consumer<ITextComponent>> logger = new Setting<>(Minecraft.getMinecraft().ingameGUI.getChatGUI()::printChatMessage);
/**
* The size of the box that is rendered when the current goal is a GoalYLevel
@@ -0,0 +1,80 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.bot;
import baritone.api.IBaritone;
import baritone.api.utils.IPlayerController;
import com.mojang.authlib.GameProfile;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.network.INetHandler;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.INetHandlerPlayClient;
import net.minecraft.util.Session;
/**
* @author Brady
* @since 10/23/2018
*/
public interface IBaritoneUser {
/**
* @return The network manager that is responsible for the current connection.
*/
NetworkManager getNetworkManager();
/**
* Returns the current play network handler. Can also be acquired via
* {@link NetworkManager#getNetHandler()} from {@link #getNetworkManager()},
* and checking if the {@link INetHandler} is an instance of {@link INetHandlerPlayClient}.
*
* @return The current play network handler
*/
INetHandlerPlayClient getConnection();
/**
* @return The locally managed entity for this user.
*/
EntityPlayerSP getEntity();
/**
* @return The bot player controller
*/
IPlayerController getPlayerController();
/**
* Returns the user login session. Should never be {@code null}, as this should be set when the
* user is constructed.
*
* @return This users's login session
*/
Session getSession();
/**
* Returns the game profile for the account represented by this user.
*
* @return This users's profile.
*/
GameProfile getProfile();
/**
* @return The manager that spawned this {@link IBaritoneUser}.
*/
IUserManager getManager();
IBaritone getBaritone();
}
@@ -0,0 +1,73 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.bot;
import baritone.api.bot.connect.IConnectionResult;
import com.mojang.authlib.GameProfile;
import net.minecraft.util.Session;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
/**
* @author Brady
* @since 1/17/2019
*/
public interface IUserManager {
/**
* Connects a new user with the specified {@link Session} to the current server.
*
* @param session The user session
* @return The result of the attempted connection
*/
IConnectionResult connect(Session session);
/**
* Disconnects the specified {@link IBaritoneUser} from its current server.
*
* @param user The user to disconnect
*/
void disconnect(IBaritoneUser user);
/**
* Finds the {@link IBaritoneUser} associated with the specified {@link GameProfile}
*
* @param profile The game profile of the user
* @return The user, {@link Optional#empty()} if no match or {@code profile} is {@code null}
*/
default Optional<IBaritoneUser> getUserByProfile(GameProfile profile) {
return profile == null ? Optional.empty() : users().stream().filter(user -> user.getProfile().equals(profile)).findFirst();
}
/**
* Finds the {@link IBaritoneUser} associated with the specified {@link UUID}
*
* @param uuid The uuid of the user
* @return The user, {@link Optional#empty()} if no match or {@code uuid} is {@code null}
*/
default Optional<IBaritoneUser> getUserByUUID(UUID uuid) {
return uuid == null ? Optional.empty() : users().stream().filter(user -> user.getProfile().getId().equals(uuid)).findFirst();
}
/**
* @return All of the users held by this manager
*/
List<IBaritoneUser> users();
}
@@ -15,13 +15,31 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils.accessor;
package baritone.api.bot.connect;
public interface IEntityRenderManager {
/**
* @author Brady
* @since 11/6/2018
*/
public enum ConnectionStatus {
double renderPosX();
/**
* The local player is not connected to a server, therefore, there is no target server to connect to.
*/
NO_CURRENT_CONNECTION,
double renderPosY();
/**
* The IP of the targetted address to connect to could not be resolved.
*/
CANT_RESOLVE_HOST,
double renderPosZ();
/**
* The connection initialization failed.
*/
CONNECTION_FAILED,
/**
* The connection was a success
*/
SUCCESS
}
@@ -0,0 +1,44 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.bot.connect;
import baritone.api.bot.IBaritoneUser;
import java.util.Optional;
/**
* @author Brady
* @since 1/17/2019
*/
public interface IConnectionResult {
/**
* @return The actual status of the connection attempt.
* @see ConnectionStatus
*/
ConnectionStatus getStatus();
/**
* Returns the user that was created in this connection this result reflects, if
* {@link #getStatus()} is {@link ConnectionStatus#SUCCESS}, otherwise it will
* return {@link Optional#empty()}.
*
* @return The user created in the connection
*/
Optional<IBaritoneUser> getUser();
}
+3 -3
View File
@@ -17,7 +17,7 @@
package baritone.api.cache;
import net.minecraft.block.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.BlockPos;
/**
@@ -26,9 +26,9 @@ import net.minecraft.util.math.BlockPos;
*/
public interface IBlockTypeAccess {
BlockState getBlock(int x, int y, int z);
IBlockState getBlock(int x, int y, int z);
default BlockState getBlock(BlockPos pos) {
default IBlockState getBlock(BlockPos pos) {
return getBlock(pos.getX(), pos.getY(), pos.getZ());
}
}
@@ -27,7 +27,7 @@ import baritone.api.command.datatypes.IDatatypePost;
import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandInvalidTypeException;
import baritone.api.command.exception.CommandNotEnoughArgumentsException;
import net.minecraft.util.Direction;
import net.minecraft.util.EnumFacing;
import java.util.Deque;
import java.util.LinkedList;
@@ -404,8 +404,8 @@ public interface IArgConsumer {
/**
* Gets an enum value from the enum class with the same name as the next argument's value
* <p>
* For example if you getEnum as an {@link Direction}, and the next argument's value is "up", this will return
* {@link Direction#UP}
* For example if you getEnum as an {@link EnumFacing}, and the next argument's value is "up", this will return
* {@link EnumFacing#UP}
*
* @param enumClass The enum class to search
* @return An enum constant of that class with the same name as the next argument's value
@@ -419,8 +419,8 @@ public interface IArgConsumer {
/**
* Gets an enum value from the enum class with the same name as the next argument's value
* <p>
* For example if you getEnum as an {@link Direction}, and the next argument's value is "up", this will return
* {@link Direction#UP}
* For example if you getEnum as an {@link EnumFacing}, and the next argument's value is "up", this will return
* {@link EnumFacing#UP}
*
* @param enumClass The enum class to search
* @param def The default value
@@ -436,8 +436,8 @@ public interface IArgConsumer {
/**
* Gets an enum value from the enum class with the same name as the next argument's value
* <p>
* For example if you getEnum as an {@link Direction}, and the next argument's value is "up", this will return
* {@link Direction#UP}
* For example if you getEnum as an {@link EnumFacing}, and the next argument's value is "up", this will return
* {@link EnumFacing#UP}
*
* @param enumClass The enum class to search
* @return An enum constant of that class with the same name as the next argument's value, or {@code null} if it
@@ -19,7 +19,7 @@ package baritone.api.command.argument;
import baritone.api.command.argparser.IArgParser;
import baritone.api.command.exception.CommandInvalidTypeException;
import net.minecraft.util.Direction;
import net.minecraft.util.EnumFacing;
/**
* A {@link ICommandArgument} is an immutable object representing one command argument. It contains data on the index of
@@ -50,8 +50,8 @@ public interface ICommandArgument {
/**
* Gets an enum value from the enum class with the same name as this argument's value
* <p>
* For example if you getEnum as an {@link Direction}, and this argument's value is "up", it will return {@link
* Direction#UP}
* For example if you getEnum as an {@link EnumFacing}, and this argument's value is "up", it will return {@link
* EnumFacing#UP}
*
* @param enumClass The enum class to search
* @return An enum constant of that class with the same name as this argument's value
@@ -17,11 +17,11 @@
package baritone.api.command.datatypes;
import baritone.api.command.exception.CommandException;
import baritone.api.command.helpers.TabCompleteHelper;
import baritone.api.command.exception.CommandException;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import java.util.stream.Stream;
@@ -32,7 +32,7 @@ public enum BlockById implements IDatatypeFor<Block> {
public Block get(IDatatypeContext ctx) throws CommandException {
ResourceLocation id = new ResourceLocation(ctx.getConsumer().getString());
Block block;
if ((block = Registry.BLOCK.getValue(id).orElse(null)) == null) {
if ((block = Block.REGISTRY.getObject(id)) == Blocks.AIR) {
throw new IllegalArgumentException("no block found by that id");
}
return block;
@@ -42,7 +42,7 @@ public enum BlockById implements IDatatypeFor<Block> {
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
return new TabCompleteHelper()
.append(
Registry.BLOCK.keySet()
Block.REGISTRY.getKeys()
.stream()
.map(Object::toString)
)
@@ -17,22 +17,22 @@
package baritone.api.command.datatypes;
import baritone.api.command.exception.CommandException;
import baritone.api.command.helpers.TabCompleteHelper;
import net.minecraft.entity.EntityType;
import baritone.api.command.exception.CommandException;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import java.util.stream.Stream;
public enum EntityClassById implements IDatatypeFor<EntityType> {
public enum EntityClassById implements IDatatypeFor<Class<? extends Entity>> {
INSTANCE;
@Override
public EntityType get(IDatatypeContext ctx) throws CommandException {
public Class<? extends Entity> get(IDatatypeContext ctx) throws CommandException {
ResourceLocation id = new ResourceLocation(ctx.getConsumer().getString());
EntityType entity;
if ((entity = Registry.ENTITY_TYPE.getValue(id).orElse(null)) == null) {
Class<? extends Entity> entity;
if ((entity = EntityList.REGISTRY.getObject(id)) == null) {
throw new IllegalArgumentException("no entity found by that id");
}
return entity;
@@ -41,7 +41,7 @@ public enum EntityClassById implements IDatatypeFor<EntityType> {
@Override
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
return new TabCompleteHelper()
.append(Registry.ENTITY_TYPE.stream().map(Object::toString))
.append(EntityList.getEntityNameList().stream().map(Object::toString))
.filterPrefixNamespaced(ctx.getConsumer().getString())
.sortAlphabetically()
.stream();
@@ -19,24 +19,24 @@ package baritone.api.command.datatypes;
import baritone.api.command.helpers.TabCompleteHelper;
import baritone.api.command.exception.CommandException;
import net.minecraft.util.Direction;
import net.minecraft.util.EnumFacing;
import java.util.Locale;
import java.util.stream.Stream;
public enum ForDirection implements IDatatypeFor<Direction> {
public enum ForEnumFacing implements IDatatypeFor<EnumFacing> {
INSTANCE;
@Override
public Direction get(IDatatypeContext ctx) throws CommandException {
return Direction.valueOf(ctx.getConsumer().getString().toUpperCase(Locale.US));
public EnumFacing get(IDatatypeContext ctx) throws CommandException {
return EnumFacing.valueOf(ctx.getConsumer().getString().toUpperCase(Locale.US));
}
@Override
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
return new TabCompleteHelper()
.append(Stream.of(Direction.values())
.map(Direction::getName).map(String::toLowerCase))
.append(Stream.of(EnumFacing.values())
.map(EnumFacing::getName).map(String::toLowerCase))
.filterPrefix(ctx.getConsumer().getString())
.stream();
}
@@ -18,10 +18,9 @@
package baritone.api.command.datatypes;
import baritone.api.IBaritone;
import baritone.api.command.exception.CommandException;
import baritone.api.command.helpers.TabCompleteHelper;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.util.text.ITextComponent;
import baritone.api.command.exception.CommandException;
import net.minecraft.entity.player.EntityPlayer;
import java.util.List;
import java.util.stream.Stream;
@@ -30,27 +29,27 @@ import java.util.stream.Stream;
* An {@link IDatatype} used to resolve nearby players, those within
* render distance of the target {@link IBaritone} instance.
*/
public enum NearbyPlayer implements IDatatypeFor<PlayerEntity> {
public enum NearbyPlayer implements IDatatypeFor<EntityPlayer> {
INSTANCE;
@Override
public PlayerEntity get(IDatatypeContext ctx) throws CommandException {
public EntityPlayer get(IDatatypeContext ctx) throws CommandException {
final String username = ctx.getConsumer().getString();
return getPlayers(ctx).stream()
.filter(s -> s.getName().getString().equalsIgnoreCase(username))
.filter(s -> s.getName().equalsIgnoreCase(username))
.findFirst().orElse(null);
}
@Override
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
return new TabCompleteHelper()
.append(getPlayers(ctx).stream().map(PlayerEntity::getName).map(ITextComponent::getString))
.append(getPlayers(ctx).stream().map(EntityPlayer::getName))
.filterPrefix(ctx.getConsumer().getString())
.sortAlphabetically()
.stream();
}
private static List<? extends PlayerEntity> getPlayers(IDatatypeContext ctx) {
return ctx.getBaritone().getPlayerContext().world().getPlayers();
private static List<EntityPlayer> getPlayers(IDatatypeContext ctx) {
return ctx.getBaritone().getPlayerContext().world().playerEntities;
}
}
@@ -37,7 +37,7 @@ public enum RelativeGoalXZ implements IDatatypePost<GoalXZ, BetterBlockPos> {
final IArgConsumer consumer = ctx.getConsumer();
return new GoalXZ(
MathHelper.floor(consumer.getDatatypePost(RelativeCoordinate.INSTANCE, (double) origin.x)),
MathHelper.floor(consumer.getDatatypePost(RelativeCoordinate.INSTANCE, (double) origin.z))
MathHelper.floor(consumer.getDatatypePost(RelativeCoordinate.INSTANCE, (double) origin.y))
);
}
@@ -22,7 +22,7 @@ import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandInvalidTypeException;
import baritone.api.command.argument.IArgConsumer;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.event.ClickEvent;
import net.minecraft.util.text.event.HoverEvent;
@@ -74,7 +74,7 @@ public class Paginator<E> implements Helper {
}
boolean hasPrevPage = commandPrefix != null && validPage(page - 1);
boolean hasNextPage = commandPrefix != null && validPage(page + 1);
ITextComponent prevPageComponent = new StringTextComponent("<<");
ITextComponent prevPageComponent = new TextComponentString("<<");
if (hasPrevPage) {
prevPageComponent.getStyle()
.setClickEvent(new ClickEvent(
@@ -83,12 +83,12 @@ public class Paginator<E> implements Helper {
))
.setHoverEvent(new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new StringTextComponent("Click to view previous page")
new TextComponentString("Click to view previous page")
));
} else {
prevPageComponent.getStyle().setColor(TextFormatting.DARK_GRAY);
}
ITextComponent nextPageComponent = new StringTextComponent(">>");
ITextComponent nextPageComponent = new TextComponentString(">>");
if (hasNextPage) {
nextPageComponent.getStyle()
.setClickEvent(new ClickEvent(
@@ -97,12 +97,12 @@ public class Paginator<E> implements Helper {
))
.setHoverEvent(new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new StringTextComponent("Click to view next page")
new TextComponentString("Click to view next page")
));
} else {
nextPageComponent.getStyle().setColor(TextFormatting.DARK_GRAY);
}
ITextComponent pagerComponent = new StringTextComponent("");
ITextComponent pagerComponent = new TextComponentString("");
pagerComponent.getStyle().setColor(TextFormatting.GRAY);
pagerComponent.appendSibling(prevPageComponent);
pagerComponent.appendText(" | ");
@@ -19,7 +19,7 @@ package baritone.api.event.events;
import baritone.api.event.events.type.EventState;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.IPacket;
import net.minecraft.network.Packet;
/**
* @author Brady
@@ -31,9 +31,9 @@ public final class PacketEvent {
private final EventState state;
private final IPacket<?> packet;
private final Packet<?> packet;
public PacketEvent(NetworkManager networkManager, EventState state, IPacket<?> packet) {
public PacketEvent(NetworkManager networkManager, EventState state, Packet<?> packet) {
this.networkManager = networkManager;
this.state = state;
this.packet = packet;
@@ -47,12 +47,12 @@ public final class PacketEvent {
return this.state;
}
public final IPacket<?> getPacket() {
public final Packet<?> getPacket() {
return this.packet;
}
@SuppressWarnings("unchecked")
public final <T extends IPacket<?>> T cast() {
public final <T extends Packet<?>> T cast() {
return (T) this.packet;
}
}
@@ -17,9 +17,6 @@
package baritone.api.event.events;
import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.renderer.Matrix4f;
/**
* @author Brady
* @since 8/5/2018
@@ -31,13 +28,8 @@ public final class RenderEvent {
*/
private final float partialTicks;
private final Matrix4f projectionMatrix;
private final MatrixStack modelViewStack;
public RenderEvent(float partialTicks, MatrixStack modelViewStack, Matrix4f projectionMatrix) {
public RenderEvent(float partialTicks) {
this.partialTicks = partialTicks;
this.modelViewStack = modelViewStack;
this.projectionMatrix = projectionMatrix;
}
/**
@@ -46,12 +38,4 @@ public final class RenderEvent {
public final float getPartialTicks() {
return this.partialTicks;
}
public MatrixStack getModelViewStack() {
return this.modelViewStack;
}
public Matrix4f getProjectionMatrix() {
return this.projectionMatrix;
}
}
@@ -18,6 +18,7 @@
package baritone.api.event.events;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
/**
* @author Brady
@@ -75,7 +76,7 @@ public final class RotationMoveEvent {
/**
* Called when the player jumps.
*
* @see LivingEntity#jump
* @see EntityLivingBase#jump
*/
JUMP
}
@@ -23,7 +23,7 @@ import baritone.api.event.events.type.Overrideable;
/**
* @author LoganDark
*/
public final class TabCompleteEvent extends Cancellable {
public class TabCompleteEvent extends Cancellable {
public final String prefix;
public String[] completions;
@@ -18,7 +18,7 @@
package baritone.api.event.events;
import baritone.api.event.events.type.EventState;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.client.multiplayer.WorldClient;
/**
* @author Brady
@@ -29,14 +29,14 @@ public final class WorldEvent {
/**
* The new world that is being loaded. {@code null} if being unloaded.
*/
private final ClientWorld world;
private final WorldClient world;
/**
* The state of the event
*/
private final EventState state;
public WorldEvent(ClientWorld world, EventState state) {
public WorldEvent(WorldClient world, EventState state) {
this.world = world;
this.state = state;
}
@@ -44,7 +44,7 @@ public final class WorldEvent {
/**
* @return The new world that is being loaded. {@code null} if being unloaded.
*/
public final ClientWorld getWorld() {
public final WorldClient getWorld() {
return this.world;
}
@@ -18,12 +18,14 @@
package baritone.api.event.listener;
import baritone.api.event.events.*;
import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.gui.screen.DeathScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiGameOver;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.Entity;
import net.minecraft.network.Packet;
/**
* @author Brady
@@ -43,7 +45,7 @@ public interface IGameEventListener {
* Run once per game tick from before and after the player rotation is sent to the server.
*
* @param event The event
* @see ClientPlayerEntity#tick()
* @see EntityPlayerSP#onUpdate()
*/
void onPlayerUpdate(PlayerUpdateEvent event);
@@ -51,7 +53,7 @@ public interface IGameEventListener {
* Runs whenever the client player sends a message to the server.
*
* @param event The event
* @see ClientPlayerEntity#sendChatMessage(String)
* @see EntityPlayerSP#sendChatMessage(String)
*/
void onSendChatMessage(ChatEvent event);
@@ -66,11 +68,14 @@ public interface IGameEventListener {
* Runs before and after whenever a chunk is either loaded, unloaded, or populated.
*
* @param event The event
* @see WorldClient#doPreChunk(int, int, boolean)
*/
void onChunkEvent(ChunkEvent event);
/**
* Runs once per world render pass.
* Runs once per world render pass. Two passes are made when {@link GameSettings#anaglyph} is on.
* <p>
* <b>Note:</b> {@link GameSettings#anaglyph} has been removed in Minecraft 1.13
*
* @param event The event
*/
@@ -80,7 +85,7 @@ public interface IGameEventListener {
* Runs before and after whenever a new world is loaded
*
* @param event The event
* @see Minecraft#loadWorld(ClientWorld, Screen)
* @see Minecraft#loadWorld(WorldClient, String)
*/
void onWorldEvent(WorldEvent event);
@@ -89,6 +94,7 @@ public interface IGameEventListener {
*
* @param event The event
* @see Packet
* @see GenericFutureListener
*/
void onSendPacket(PacketEvent event);
@@ -97,6 +103,7 @@ public interface IGameEventListener {
*
* @param event The event
* @see Packet
* @see GenericFutureListener
*/
void onReceivePacket(PacketEvent event);
@@ -110,10 +117,10 @@ public interface IGameEventListener {
void onPlayerRotationMove(RotationMoveEvent event);
/**
* Called whenever the sprint keybind state is checked in {@link ClientPlayerEntity#livingTick}
* Called whenever the sprint keybind state is checked in {@link EntityPlayerSP#onLivingUpdate}
*
* @param event The event
* @see ClientPlayerEntity#livingTick()
* @see EntityPlayerSP#onLivingUpdate()
*/
void onPlayerSprintState(SprintStateEvent event);
@@ -105,7 +105,7 @@ public interface IPath {
* Returns the estimated number of ticks to complete the path from the given node index.
*
* @param pathPosition The index of the node we're calculating from
* @return The estimated number of ticks remaining frm the given position
* @return The estimated number of ticks remaining from the given position
*/
default double ticksRemainingFrom(int pathPosition) {
double sum = 0;
@@ -117,6 +117,15 @@ public interface IPath {
return sum;
}
/**
* Returns the estimated amount of time needed to complete this path from start to finish
*
* @return The estimated amount of time, in ticks
*/
default double totalTicks() {
return ticksRemainingFrom(0);
}
/**
* Cuts off this path at the loaded chunk border, and returns the resulting path. Default
* implementation just returns this path, without the intended functionality.
@@ -18,7 +18,7 @@
package baritone.api.pathing.goals;
import baritone.api.utils.SettingsUtil;
import net.minecraft.util.Direction;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
/**
@@ -32,7 +32,7 @@ public class GoalStrictDirection implements Goal {
public final int dx;
public final int dz;
public GoalStrictDirection(BlockPos origin, Direction direction) {
public GoalStrictDirection(BlockPos origin, EnumFacing direction) {
x = origin.getX();
y = origin.getY();
z = origin.getZ();
@@ -18,7 +18,7 @@
package baritone.api.process;
import baritone.api.schematic.ISchematic;
import net.minecraft.block.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3i;
@@ -52,7 +52,7 @@ public interface IBuilderProcess extends IBaritoneProcess {
boolean build(String name, File schematic, Vec3i origin);
default boolean build(String schematicFile, BlockPos origin) {
File file = new File(new File(Minecraft.getInstance().gameDir, "schematics"), schematicFile);
File file = new File(new File(Minecraft.getMinecraft().gameDir, "schematics"), schematicFile);
return build(schematicFile, file, origin);
}
@@ -71,5 +71,5 @@ public interface IBuilderProcess extends IBaritoneProcess {
* schematics, for example, to pick a state that the builder process will be happy with, because any variation will
* cause it to give up. This is updated every tick, but only while the builder process is active.
*/
List<BlockState> getApproxPlaceable();
List<IBlockState> getApproxPlaceable();
}
@@ -17,7 +17,7 @@
package baritone.api.schematic;
import net.minecraft.block.BlockState;
import net.minecraft.block.state.IBlockState;
import java.util.ArrayList;
import java.util.List;
@@ -47,7 +47,7 @@ public class CompositeSchematic extends AbstractSchematic {
recalcArr();
}
private CompositeSchematicEntry getSchematic(int x, int y, int z, BlockState currentState) {
private CompositeSchematicEntry getSchematic(int x, int y, int z, IBlockState currentState) {
for (CompositeSchematicEntry entry : schematicArr) {
if (x >= entry.x && y >= entry.y && z >= entry.z &&
entry.schematic.inSchematic(x - entry.x, y - entry.y, z - entry.z, currentState)) {
@@ -58,13 +58,13 @@ public class CompositeSchematic extends AbstractSchematic {
}
@Override
public boolean inSchematic(int x, int y, int z, BlockState currentState) {
public boolean inSchematic(int x, int y, int z, IBlockState currentState) {
CompositeSchematicEntry entry = getSchematic(x, y, z, currentState);
return entry != null && entry.schematic.inSchematic(x - entry.x, y - entry.y, z - entry.z, currentState);
}
@Override
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
public IBlockState desiredState(int x, int y, int z, IBlockState current, List<IBlockState> approxPlaceable) {
CompositeSchematicEntry entry = getSchematic(x, y, z, current);
if (entry == null) {
throw new IllegalStateException("couldn't find schematic for this position");
@@ -18,8 +18,8 @@
package baritone.api.schematic;
import baritone.api.utils.BlockOptionalMeta;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import java.util.List;
@@ -32,8 +32,8 @@ public class FillSchematic extends AbstractSchematic {
this.bom = bom;
}
public FillSchematic(int x, int y, int z, BlockState state) {
this(x, y, z, new BlockOptionalMeta(state.getBlock()));
public FillSchematic(int x, int y, int z, IBlockState state) {
this(x, y, z, new BlockOptionalMeta(state.getBlock(), state.getBlock().getMetaFromState(state)));
}
public BlockOptionalMeta getBom() {
@@ -41,13 +41,13 @@ public class FillSchematic extends AbstractSchematic {
}
@Override
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
public IBlockState desiredState(int x, int y, int z, IBlockState current, List<IBlockState> approxPlaceable) {
if (bom.matches(current)) {
return current;
} else if (current.getBlock() != Blocks.AIR) {
return Blocks.AIR.getDefaultState();
}
for (BlockState placeable : approxPlaceable) {
for (IBlockState placeable : approxPlaceable) {
if (bom.matches(placeable)) {
return placeable;
}
@@ -17,8 +17,8 @@
package baritone.api.schematic;
import net.minecraft.block.BlockState;
import net.minecraft.util.Direction;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.EnumFacing;
import java.util.List;
@@ -44,11 +44,11 @@ public interface ISchematic {
* @param currentState The current state of that block in the world, or null
* @return Whether or not the specified position is within the bounds of this schematic
*/
default boolean inSchematic(int x, int y, int z, BlockState currentState) {
default boolean inSchematic(int x, int y, int z, IBlockState currentState) {
return x >= 0 && x < widthX() && y >= 0 && y < heightY() && z >= 0 && z < lengthZ();
}
default int size(Direction.Axis axis) {
default int size(EnumFacing.Axis axis) {
switch (axis) {
case X:
return widthX();
@@ -71,7 +71,7 @@ public interface ISchematic {
* @param approxPlaceable The list of blockstates estimated to be placeable
* @return The desired block state at the specified position
*/
BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable);
IBlockState desiredState(int x, int y, int z, IBlockState current, List<IBlockState> approxPlaceable);
/**
* @return The width (X axis length) of this schematic
@@ -17,7 +17,7 @@
package baritone.api.schematic;
import net.minecraft.block.BlockState;
import net.minecraft.block.state.IBlockState;
/**
* A static schematic is capable of providing the desired state at a given position without
@@ -31,7 +31,7 @@ import net.minecraft.block.BlockState;
public interface IStaticSchematic extends ISchematic {
/**
* Gets the {@link BlockState} for a given position in this schematic. It should be guaranteed
* Gets the {@link IBlockState} for a given position in this schematic. It should be guaranteed
* that the return value of this method will not change given that the parameters are the same.
*
* @param x The X block position
@@ -39,19 +39,19 @@ public interface IStaticSchematic extends ISchematic {
* @param z The Z block position
* @return The desired state at the specified position.
*/
BlockState getDirect(int x, int y, int z);
IBlockState getDirect(int x, int y, int z);
/**
* Returns an {@link BlockState} array of size {@link #heightY()} which contains all
* desired block states in the specified vertical column. The index of {@link BlockState}s
* Returns an {@link IBlockState} array of size {@link #heightY()} which contains all
* desired block states in the specified vertical column. The index of {@link IBlockState}s
* in the array are equivalent to their Y position in the schematic.
*
* @param x The X column position
* @param z The Z column position
* @return An {@link BlockState} array
* @return An {@link IBlockState} array
*/
default BlockState[] getColumn(int x, int z) {
BlockState[] column = new BlockState[this.heightY()];
default IBlockState[] getColumn(int x, int z) {
IBlockState[] column = new IBlockState[this.heightY()];
for (int i = 0; i < this.heightY(); i++) {
column[i] = getDirect(x, i, z);
}
@@ -17,7 +17,7 @@
package baritone.api.schematic;
import net.minecraft.block.BlockState;
import net.minecraft.block.state.IBlockState;
import java.util.List;
@@ -30,15 +30,15 @@ public abstract class MaskSchematic extends AbstractSchematic {
this.schematic = schematic;
}
protected abstract boolean partOfMask(int x, int y, int z, BlockState currentState);
protected abstract boolean partOfMask(int x, int y, int z, IBlockState currentState);
@Override
public boolean inSchematic(int x, int y, int z, BlockState currentState) {
public boolean inSchematic(int x, int y, int z, IBlockState currentState) {
return schematic.inSchematic(x, y, z, currentState) && partOfMask(x, y, z, currentState);
}
@Override
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
public IBlockState desiredState(int x, int y, int z, IBlockState current, List<IBlockState> approxPlaceable) {
return schematic.desiredState(x, y, z, current, approxPlaceable);
}
}
@@ -18,7 +18,7 @@
package baritone.api.schematic;
import baritone.api.utils.BlockOptionalMetaLookup;
import net.minecraft.block.BlockState;
import net.minecraft.block.state.IBlockState;
public class ReplaceSchematic extends MaskSchematic {
@@ -32,7 +32,7 @@ public class ReplaceSchematic extends MaskSchematic {
}
@Override
protected boolean partOfMask(int x, int y, int z, BlockState currentState) {
protected boolean partOfMask(int x, int y, int z, IBlockState currentState) {
if (cache[x][y][z] == null) {
cache[x][y][z] = filter.has(currentState);
}
@@ -17,7 +17,7 @@
package baritone.api.schematic;
import net.minecraft.block.BlockState;
import net.minecraft.block.state.IBlockState;
public class ShellSchematic extends MaskSchematic {
@@ -26,7 +26,7 @@ public class ShellSchematic extends MaskSchematic {
}
@Override
protected boolean partOfMask(int x, int y, int z, BlockState currentState) {
protected boolean partOfMask(int x, int y, int z, IBlockState currentState) {
return x == 0 || y == 0 || z == 0 || x == widthX() - 1 || y == heightY() - 1 || z == lengthZ() - 1;
}
}
@@ -17,7 +17,7 @@
package baritone.api.schematic;
import net.minecraft.block.BlockState;
import net.minecraft.block.state.IBlockState;
public class WallsSchematic extends MaskSchematic {
@@ -26,7 +26,7 @@ public class WallsSchematic extends MaskSchematic {
}
@Override
protected boolean partOfMask(int x, int y, int z, BlockState currentState) {
protected boolean partOfMask(int x, int y, int z, IBlockState currentState) {
return x == 0 || z == 0 || x == widthX() - 1 || z == lengthZ() - 1;
}
}
@@ -18,7 +18,7 @@
package baritone.api.selection;
import baritone.api.utils.BetterBlockPos;
import net.minecraft.util.Direction;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.Vec3i;
@@ -65,7 +65,7 @@ public interface ISelection {
* @param blocks How many blocks to expand it.
* @return A new selection, expanded as specified.
*/
ISelection expand(Direction direction, int blocks);
ISelection expand(EnumFacing direction, int blocks);
/**
* Returns a new {@link ISelection} contracted in the specified direction by the specified number of blocks.
@@ -77,7 +77,7 @@ public interface ISelection {
* @param blocks How many blocks to contract it.
* @return A new selection, contracted as specified.
*/
ISelection contract(Direction direction, int blocks);
ISelection contract(EnumFacing direction, int blocks);
/**
* Returns a new {@link ISelection} shifted in the specified direction by the specified number of blocks. This moves
@@ -87,5 +87,5 @@ public interface ISelection {
* @param blocks How many blocks to shift it.
* @return A new selection, shifted as specified.
*/
ISelection shift(Direction direction, int blocks);
ISelection shift(EnumFacing direction, int blocks);
}
@@ -18,7 +18,7 @@
package baritone.api.selection;
import baritone.api.utils.BetterBlockPos;
import net.minecraft.util.Direction;
import net.minecraft.util.EnumFacing;
/**
* The selection manager handles setting Baritone's selections. You can set the selection here, as well as retrieving
@@ -87,7 +87,7 @@ public interface ISelectionManager {
* @param blocks How many blocks to expand it.
* @return The new selection, expanded as specified.
*/
ISelection expand(ISelection selection, Direction direction, int blocks);
ISelection expand(ISelection selection, EnumFacing direction, int blocks);
/**
* Replaces the specified {@link ISelection} with one contracted in the specified direction by the specified number
@@ -101,7 +101,7 @@ public interface ISelectionManager {
* @param blocks How many blocks to contract it.
* @return The new selection, contracted as specified.
*/
ISelection contract(ISelection selection, Direction direction, int blocks);
ISelection contract(ISelection selection, EnumFacing direction, int blocks);
/**
* Replaces the specified {@link ISelection} with one shifted in the specified direction by the specified number of
@@ -112,5 +112,5 @@ public interface ISelectionManager {
* @param blocks How many blocks to shift it.
* @return The new selection, shifted as specified.
*/
ISelection shift(ISelection selection, Direction direction, int blocks);
ISelection shift(ISelection selection, EnumFacing direction, int blocks);
}
@@ -17,7 +17,7 @@
package baritone.api.utils;
import net.minecraft.util.Direction;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3i;
@@ -120,10 +120,10 @@ public final class BetterBlockPos extends BlockPos {
// this is unimaginably faster than blockpos.up
// that literally calls
// this.up(1)
// which calls this.offset(Direction.UP, 1)
// which calls this.offset(EnumFacing.UP, 1)
// which does return n == 0 ? this : new BlockPos(this.getX() + facing.getXOffset() * n, this.getY() + facing.getYOffset() * n, this.getZ() + facing.getZOffset() * n);
// how many function calls is that? up(), up(int), offset(Direction, int), new BlockPos, getX, getXOffset, getY, getYOffset, getZ, getZOffset
// how many function calls is that? up(), up(int), offset(EnumFacing, int), new BlockPos, getX, getXOffset, getY, getYOffset, getZ, getZOffset
// that's ten.
// this is one function call.
return new BetterBlockPos(x, y + 1, z);
@@ -148,13 +148,13 @@ public final class BetterBlockPos extends BlockPos {
}
@Override
public BetterBlockPos offset(Direction 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(Direction dir, int dist) {
public BetterBlockPos offset(EnumFacing dir, int dist) {
if (dist == 0) {
return this;
}
@@ -19,20 +19,17 @@ package baritone.api.utils;
import baritone.api.utils.accessor.IItemStack;
import com.google.common.collect.ImmutableSet;
import io.netty.util.concurrent.ThreadPerTaskExecutor;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.Item;
import net.minecraft.block.*;
import net.minecraft.block.properties.IProperty;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.resources.*;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.storage.loot.*;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.function.Consumer;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -41,21 +38,27 @@ import java.util.stream.Collectors;
public final class BlockOptionalMeta {
private final Block block;
private final Set<BlockState> blockstates;
private final int meta;
private final boolean noMeta;
private final Set<IBlockState> blockstates;
private final ImmutableSet<Integer> stateHashes;
private final ImmutableSet<Integer> stackHashes;
private static final Pattern pattern = Pattern.compile("^(.+?)(?::(\\d+))?$");
private static LootTableManager manager;
private static LootPredicateManager predicate = new LootPredicateManager();
private static Map<Block, List<Item>> drops = new HashMap<>();
private static final Map<Object, Object> normalizations;
public BlockOptionalMeta(@Nonnull Block block) {
public BlockOptionalMeta(@Nonnull Block block, @Nullable Integer meta) {
this.block = block;
this.blockstates = getStates(block);
this.noMeta = meta == null;
this.meta = noMeta ? 0 : meta;
this.blockstates = getStates(block, meta);
this.stateHashes = getStateHashes(blockstates);
this.stackHashes = getStackHashes(blockstates);
}
public BlockOptionalMeta(@Nonnull Block block) {
this(block, null);
}
public BlockOptionalMeta(@Nonnull String selector) {
Matcher matcher = pattern.matcher(selector);
@@ -64,33 +67,205 @@ public final class BlockOptionalMeta {
}
MatchResult matchResult = matcher.toMatchResult();
noMeta = matchResult.group(2) == null;
block = BlockUtils.stringToBlockRequired(matchResult.group(1));
blockstates = getStates(block);
ResourceLocation id = new ResourceLocation(matchResult.group(1));
if (!Block.REGISTRY.containsKey(id)) {
throw new IllegalArgumentException("Invalid block ID");
}
block = Block.REGISTRY.getObject(id);
meta = noMeta ? 0 : Integer.parseInt(matchResult.group(2));
blockstates = getStates(block, getMeta());
stateHashes = getStateHashes(blockstates);
stackHashes = getStackHashes(blockstates);
}
private static Set<BlockState> getStates(@Nonnull Block block) {
return new HashSet<>(block.getStateContainer().getValidStates());
static {
Map<Object, Object> _normalizations = new HashMap<>();
Consumer<Enum> put = instance -> _normalizations.put(instance.getClass(), instance);
put.accept(EnumFacing.NORTH);
put.accept(EnumFacing.Axis.Y);
put.accept(BlockLog.EnumAxis.Y);
put.accept(BlockStairs.EnumHalf.BOTTOM);
put.accept(BlockStairs.EnumShape.STRAIGHT);
put.accept(BlockLever.EnumOrientation.DOWN_X);
put.accept(BlockDoublePlant.EnumBlockHalf.LOWER);
put.accept(BlockSlab.EnumBlockHalf.BOTTOM);
put.accept(BlockDoor.EnumDoorHalf.LOWER);
put.accept(BlockDoor.EnumHingePosition.LEFT);
put.accept(BlockBed.EnumPartType.HEAD);
put.accept(BlockRailBase.EnumRailDirection.NORTH_SOUTH);
put.accept(BlockTrapDoor.DoorHalf.BOTTOM);
_normalizations.put(BlockBanner.ROTATION, 0);
_normalizations.put(BlockBed.OCCUPIED, false);
_normalizations.put(BlockBrewingStand.HAS_BOTTLE[0], false);
_normalizations.put(BlockBrewingStand.HAS_BOTTLE[1], false);
_normalizations.put(BlockBrewingStand.HAS_BOTTLE[2], false);
_normalizations.put(BlockButton.POWERED, false);
// _normalizations.put(BlockCactus.AGE, 0);
// _normalizations.put(BlockCauldron.LEVEL, 0);
// _normalizations.put(BlockChorusFlower.AGE, 0);
_normalizations.put(BlockChorusPlant.NORTH, false);
_normalizations.put(BlockChorusPlant.EAST, false);
_normalizations.put(BlockChorusPlant.SOUTH, false);
_normalizations.put(BlockChorusPlant.WEST, false);
_normalizations.put(BlockChorusPlant.UP, false);
_normalizations.put(BlockChorusPlant.DOWN, false);
// _normalizations.put(BlockCocoa.AGE, 0);
// _normalizations.put(BlockCrops.AGE, 0);
_normalizations.put(BlockDirt.SNOWY, false);
_normalizations.put(BlockDoor.OPEN, false);
_normalizations.put(BlockDoor.POWERED, false);
// _normalizations.put(BlockFarmland.MOISTURE, 0);
_normalizations.put(BlockFence.NORTH, false);
_normalizations.put(BlockFence.EAST, false);
_normalizations.put(BlockFence.WEST, false);
_normalizations.put(BlockFence.SOUTH, false);
// _normalizations.put(BlockFenceGate.POWERED, false);
// _normalizations.put(BlockFenceGate.IN_WALL, false);
_normalizations.put(BlockFire.AGE, 0);
_normalizations.put(BlockFire.NORTH, false);
_normalizations.put(BlockFire.EAST, false);
_normalizations.put(BlockFire.SOUTH, false);
_normalizations.put(BlockFire.WEST, false);
_normalizations.put(BlockFire.UPPER, false);
// _normalizations.put(BlockFrostedIce.AGE, 0);
_normalizations.put(BlockGrass.SNOWY, false);
// _normalizations.put(BlockHopper.ENABLED, true);
// _normalizations.put(BlockLever.POWERED, false);
// _normalizations.put(BlockLiquid.LEVEL, 0);
// _normalizations.put(BlockMycelium.SNOWY, false);
// _normalizations.put(BlockNetherWart.AGE, false);
_normalizations.put(BlockLeaves.CHECK_DECAY, false);
// _normalizations.put(BlockLeaves.DECAYABLE, false);
// _normalizations.put(BlockObserver.POWERED, false);
_normalizations.put(BlockPane.NORTH, false);
_normalizations.put(BlockPane.EAST, false);
_normalizations.put(BlockPane.WEST, false);
_normalizations.put(BlockPane.SOUTH, false);
// _normalizations.put(BlockPistonBase.EXTENDED, false);
// _normalizations.put(BlockPressurePlate.POWERED, false);
// _normalizations.put(BlockPressurePlateWeighted.POWER, false);
_normalizations.put(BlockQuartz.EnumType.LINES_X, BlockQuartz.EnumType.LINES_Y);
_normalizations.put(BlockQuartz.EnumType.LINES_Z, BlockQuartz.EnumType.LINES_Y);
// _normalizations.put(BlockRailDetector.POWERED, false);
// _normalizations.put(BlockRailPowered.POWERED, false);
_normalizations.put(BlockRedstoneWire.NORTH, false);
_normalizations.put(BlockRedstoneWire.EAST, false);
_normalizations.put(BlockRedstoneWire.SOUTH, false);
_normalizations.put(BlockRedstoneWire.WEST, false);
// _normalizations.put(BlockReed.AGE, false);
_normalizations.put(BlockSapling.STAGE, 0);
_normalizations.put(BlockSkull.NODROP, false);
_normalizations.put(BlockStandingSign.ROTATION, 0);
_normalizations.put(BlockStem.AGE, 0);
_normalizations.put(BlockTripWire.NORTH, false);
_normalizations.put(BlockTripWire.EAST, false);
_normalizations.put(BlockTripWire.WEST, false);
_normalizations.put(BlockTripWire.SOUTH, false);
_normalizations.put(BlockVine.NORTH, false);
_normalizations.put(BlockVine.EAST, false);
_normalizations.put(BlockVine.SOUTH, false);
_normalizations.put(BlockVine.WEST, false);
_normalizations.put(BlockVine.UP, false);
_normalizations.put(BlockWall.UP, false);
_normalizations.put(BlockWall.NORTH, false);
_normalizations.put(BlockWall.EAST, false);
_normalizations.put(BlockWall.WEST, false);
_normalizations.put(BlockWall.SOUTH, false);
normalizations = Collections.unmodifiableMap(_normalizations);
}
private static ImmutableSet<Integer> getStateHashes(Set<BlockState> blockstates) {
public static <C extends Comparable<C>, P extends IProperty<C>> P castToIProperty(Object value) {
//noinspection unchecked
return (P) value;
}
public static <C extends Comparable<C>, P extends IProperty<C>> C castToIPropertyValue(P iproperty, Object value) {
//noinspection unchecked
return (C) value;
}
/**
* Normalizes the specified blockstate by setting meta-affecting properties which
* are not being targeted by the meta parameter to their default values.
* <p>
* For example, block variant/color is the primary target for the meta value, so properties
* such as rotation/facing direction will be set to default values in order to nullify
* the effect that they have on the state's meta value.
*
* @param state The state to normalize
* @return The normalized block state
*/
public static IBlockState normalize(IBlockState state) {
IBlockState newState = state;
for (IProperty<?> property : state.getProperties().keySet()) {
Class<?> valueClass = property.getValueClass();
if (normalizations.containsKey(property)) {
try {
newState = newState.withProperty(
castToIProperty(property),
castToIPropertyValue(property, normalizations.get(property))
);
} catch (IllegalArgumentException ignored) {}
} else if (normalizations.containsKey(state.getValue(property))) {
try {
newState = newState.withProperty(
castToIProperty(property),
castToIPropertyValue(property, normalizations.get(state.getValue(property)))
);
} catch (IllegalArgumentException ignored) {}
} else if (normalizations.containsKey(valueClass)) {
try {
newState = newState.withProperty(
castToIProperty(property),
castToIPropertyValue(property, normalizations.get(valueClass))
);
} catch (IllegalArgumentException ignored) {}
}
}
return newState;
}
/**
* Evaluate the target meta value for the specified state. The target meta value is
* most often that which is influenced by the variant/color property of the block state.
*
* @see #normalize(IBlockState)
*
* @param state The state to check
* @return The target meta of the state
*/
public static int stateMeta(IBlockState state) {
return state.getBlock().getMetaFromState(normalize(state));
}
private static Set<IBlockState> getStates(@Nonnull Block block, @Nullable Integer meta) {
return block.getBlockState().getValidStates().stream()
.filter(blockstate -> meta == null || stateMeta(blockstate) == meta)
.collect(Collectors.toSet());
}
private static ImmutableSet<Integer> getStateHashes(Set<IBlockState> blockstates) {
return ImmutableSet.copyOf(
blockstates.stream()
.map(BlockState::hashCode)
.map(IBlockState::hashCode)
.toArray(Integer[]::new)
);
}
private static ImmutableSet<Integer> getStackHashes(Set<BlockState> blockstates) {
private static ImmutableSet<Integer> getStackHashes(Set<IBlockState> blockstates) {
//noinspection ConstantConditions
return ImmutableSet.copyOf(
blockstates.stream()
.flatMap(state -> drops(state.getBlock())
.stream()
.map(item -> new ItemStack(item, 1))
)
.map(state -> new ItemStack(
state.getBlock().getItemDropped(state, new Random(), 0),
state.getBlock().damageDropped(state)
))
.map(stack -> ((IItemStack) (Object) stack).getBaritoneHash())
.toArray(Integer[]::new)
);
@@ -100,11 +275,15 @@ public final class BlockOptionalMeta {
return block;
}
public Integer getMeta() {
return noMeta ? null : meta;
}
public boolean matches(@Nonnull Block block) {
return block == this.block;
}
public boolean matches(@Nonnull BlockState blockstate) {
public boolean matches(@Nonnull IBlockState blockstate) {
Block block = blockstate.getBlock();
return block == this.block && stateHashes.contains(blockstate.hashCode());
}
@@ -113,54 +292,28 @@ public final class BlockOptionalMeta {
//noinspection ConstantConditions
int hash = ((IItemStack) (Object) stack).getBaritoneHash();
hash -= stack.getDamage();
if (noMeta) {
hash -= stack.getItemDamage();
}
return stackHashes.contains(hash);
}
@Override
public String toString() {
return String.format("BlockOptionalMeta{block=%s}", block);
return String.format("BlockOptionalMeta{block=%s,meta=%s}", block, getMeta());
}
public BlockState getAnyBlockState() {
public static IBlockState blockStateFromStack(ItemStack stack) {
//noinspection deprecation
return Block.getBlockFromItem(stack.getItem()).getStateFromMeta(stack.getMetadata());
}
public IBlockState getAnyBlockState() {
if (blockstates.size() > 0) {
return blockstates.iterator().next();
}
return null;
}
public static LootTableManager getManager() {
if (manager == null) {
ResourcePackList rpl = new ResourcePackList<>(ResourcePackInfo::new);
rpl.addPackFinder(new ServerPackFinder());
rpl.reloadPacksFromFinders();
IResourcePack thePack = ((ResourcePackInfo) rpl.getAllPacks().iterator().next()).getResourcePack();
IReloadableResourceManager resourceManager = new SimpleReloadableResourceManager(ResourcePackType.SERVER_DATA, null);
manager = new LootTableManager(predicate);
resourceManager.addReloadListener(manager);
try {
resourceManager.reloadResourcesAndThen(new ThreadPerTaskExecutor(Thread::new), new ThreadPerTaskExecutor(Thread::new), Collections.singletonList(thePack), CompletableFuture.completedFuture(Unit.INSTANCE)).get();
} catch (Exception exception) {
throw new RuntimeException(exception);
}
}
return manager;
}
public static LootPredicateManager getPredicateManager() {
return predicate;
}
private static synchronized List<Item> drops(Block b) {
return drops.computeIfAbsent(b, block -> {
ResourceLocation lootTableLocation = block.getLootTable();
if (lootTableLocation == LootTables.EMPTY) {
return Collections.emptyList();
} else {
return getManager().getLootTableFromLocation(lootTableLocation).generate(new LootContext.Builder(null).withRandom(new Random()).withParameter(LootParameters.POSITION, BlockPos.ZERO).withParameter(LootParameters.TOOL, ItemStack.EMPTY).withNullableParameter(LootParameters.BLOCK_ENTITY, null).withParameter(LootParameters.BLOCK_STATE, block.getDefaultState()).build(LootParameterSets.BLOCK)).stream().map(ItemStack::getItem).collect(Collectors.toList());
}
});
}
}
@@ -18,7 +18,7 @@
package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import java.util.Arrays;
@@ -61,7 +61,7 @@ public class BlockOptionalMetaLookup {
return false;
}
public boolean has(BlockState state) {
public boolean has(IBlockState state) {
for (BlockOptionalMeta bom : boms) {
if (bom.matches(state)) {
return true;
@@ -19,7 +19,6 @@ package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import java.util.HashMap;
import java.util.Map;
@@ -29,7 +28,7 @@ public class BlockUtils {
private static transient Map<String, Block> resourceCache = new HashMap<>();
public static String blockToString(Block block) {
ResourceLocation loc = Registry.BLOCK.getKey(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?
@@ -57,7 +56,7 @@ public class BlockUtils {
if (resourceCache.containsKey(name)) {
return null; // cached as null
}
block = Registry.BLOCK.getValue(ResourceLocation.tryCreate(name.contains(":") ? name : "minecraft:" + name)).orElse(null);
block = Block.getBlockFromName(name.contains(":") ? name : "minecraft:" + name);
Map<String, Block> copy = new HashMap<>(resourceCache); // read only copy is safe, wont throw concurrentmodification
copy.put(name, block);
resourceCache = copy;
+8 -8
View File
@@ -20,7 +20,7 @@ package baritone.api.utils;
import baritone.api.BaritoneAPI;
import net.minecraft.client.Minecraft;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import java.util.Arrays;
@@ -43,15 +43,15 @@ public interface Helper {
/**
* Instance of the game
*/
Minecraft mc = Minecraft.getInstance();
Minecraft mc = Minecraft.getMinecraft();
static ITextComponent getPrefix() {
// Inner text component
ITextComponent baritone = new StringTextComponent(BaritoneAPI.getSettings().shortBaritonePrefix.value ? "B" : "Baritone");
ITextComponent baritone = new TextComponentString(BaritoneAPI.getSettings().shortBaritonePrefix.value ? "B" : "Baritone");
baritone.getStyle().setColor(TextFormatting.LIGHT_PURPLE);
// Outer brackets
ITextComponent prefix = new StringTextComponent("");
ITextComponent prefix = new TextComponentString("");
prefix.getStyle().setColor(TextFormatting.DARK_PURPLE);
prefix.appendText("[");
prefix.appendSibling(baritone);
@@ -80,11 +80,11 @@ public interface Helper {
* @param components The components to send
*/
default void logDirect(ITextComponent... components) {
ITextComponent component = new StringTextComponent("");
ITextComponent component = new TextComponentString("");
component.appendSibling(getPrefix());
component.appendSibling(new StringTextComponent(" "));
component.appendSibling(new TextComponentString(" "));
Arrays.asList(components).forEach(component::appendSibling);
mc.execute(() -> BaritoneAPI.getSettings().logger.value.accept(component));
Minecraft.getMinecraft().addScheduledTask(() -> BaritoneAPI.getSettings().logger.value.accept(component));
}
/**
@@ -96,7 +96,7 @@ public interface Helper {
*/
default void logDirect(String message, TextFormatting color) {
Stream.of(message.split("\n")).forEach(line -> {
ITextComponent component = new StringTextComponent(line.replace("\t", " "));
ITextComponent component = new TextComponentString(line.replace("\t", " "));
component.getStyle().setColor(color);
logDirect(component);
});
@@ -18,16 +18,15 @@
package baritone.api.utils;
import baritone.api.cache.IWorldData;
import net.minecraft.block.SlabBlock;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.block.BlockSlab;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World;
import java.util.Optional;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* @author Brady
@@ -35,28 +34,19 @@ import java.util.stream.StreamSupport;
*/
public interface IPlayerContext {
ClientPlayerEntity player();
EntityPlayerSP player();
IPlayerController playerController();
World world();
default Iterable<Entity> entities() {
return ((ClientWorld) world()).getAllEntities();
}
default Stream<Entity> entitiesStream() {
return StreamSupport.stream(entities().spliterator(), false);
}
IWorldData worldData();
RayTraceResult objectMouseOver();
default BetterBlockPos playerFeet() {
// TODO find a better way to deal with soul sand!!!!!
BetterBlockPos feet = new BetterBlockPos(player().getPositionVec().x, player().getPositionVec().y + 0.1251, player().getPositionVec().z);
BetterBlockPos feet = new BetterBlockPos(player().posX, player().posY + 0.1251, player().posZ);
// sometimes when calling this from another thread or while world is null, it'll throw a NullPointerException
// that causes the game to immediately crash
@@ -67,7 +57,7 @@ public interface IPlayerContext {
// this does not impact performance at all since we're not null checking constantly
// if there is an exception, the only overhead is Java generating the exception object... so we can ignore it
try {
if (world().getBlockState(feet).getBlock() instanceof SlabBlock) {
if (world().getBlockState(feet).getBlock() instanceof BlockSlab) {
return feet.up();
}
} catch (NullPointerException ignored) {}
@@ -76,11 +66,11 @@ public interface IPlayerContext {
}
default Vec3d playerFeetAsVec() {
return new Vec3d(player().getPositionVec().x, player().getPositionVec().y, player().getPositionVec().z);
return new Vec3d(player().posX, player().posY, player().posZ);
}
default Vec3d playerHead() {
return new Vec3d(player().getPositionVec().x, player().getPositionVec().y + player().getEyeHeight(), player().getPositionVec().z);
return new Vec3d(player().posX, player().posY + player().getEyeHeight(), player().posZ);
}
default Rotation playerRotations() {
@@ -94,8 +84,8 @@ public interface IPlayerContext {
*/
default Optional<BlockPos> getSelectedBlock() {
RayTraceResult result = objectMouseOver();
if (result != null && result.getType() == RayTraceResult.Type.BLOCK) {
return Optional.of(((BlockRayTraceResult) result).getPos());
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
return Optional.of(result.getBlockPos());
}
return Optional.empty();
}
@@ -111,8 +101,8 @@ public interface IPlayerContext {
*/
default Optional<Entity> getSelectedEntity() {
RayTraceResult result = objectMouseOver();
if (result != null && result.getType() == RayTraceResult.Type.ENTITY) {
return Optional.of(((EntityRayTraceResult) result).getEntity());
if (result != null && result.typeOfHit == RayTraceResult.Type.ENTITY) {
return Optional.of(result.entityHit);
}
return Optional.empty();
}
@@ -17,16 +17,16 @@
package baritone.api.utils;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.container.ClickType;
import baritone.api.BaritoneAPI;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameType;
import net.minecraft.world.World;
@@ -40,19 +40,21 @@ public interface IPlayerController {
boolean hasBrokenBlock();
boolean onPlayerDamageBlock(BlockPos pos, Direction side);
boolean onPlayerDamageBlock(BlockPos pos, EnumFacing side);
void resetBlockRemoving();
ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, PlayerEntity player);
ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player);
void setGameType(GameType type);
GameType getGameType();
ActionResultType processRightClickBlock(ClientPlayerEntity player, World world, Hand hand, BlockRayTraceResult result);
EnumActionResult processRightClickBlock(EntityPlayerSP player, World world, BlockPos pos, EnumFacing direction, Vec3d vec, EnumHand hand);
ActionResultType processRightClick(ClientPlayerEntity player, World world, Hand hand);
EnumActionResult processRightClick(EntityPlayerSP player, World world, EnumHand hand);
boolean clickBlock(BlockPos loc, Direction face);
boolean clickBlock(BlockPos loc, EnumFacing face);
void setHittingBlock(boolean hittingBlock);
@@ -18,7 +18,6 @@
package baritone.api.utils;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.RayTraceContext;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
@@ -41,13 +40,13 @@ public final class RayTraceUtils {
* @return The calculated raytrace result
*/
public static RayTraceResult rayTraceTowards(Entity entity, Rotation rotation, double blockReachDistance) {
Vec3d start = entity.getEyePosition(1.0F);
Vec3d start = entity.getPositionEyes(1.0F);
Vec3d direction = RotationUtils.calcVec3dFromRotation(rotation);
Vec3d end = start.add(
direction.x * blockReachDistance,
direction.y * blockReachDistance,
direction.z * blockReachDistance
);
return entity.world.rayTraceBlocks(new RayTraceContext(start, end, RayTraceContext.BlockMode.OUTLINE, RayTraceContext.FluidMode.NONE, entity));
return entity.world.rayTraceBlocks(start, end, false, false, true);
}
}
@@ -36,9 +36,6 @@ public class Rotation {
public Rotation(float yaw, float pitch) {
this.yaw = yaw;
this.pitch = pitch;
if (Float.isInfinite(yaw) || Float.isNaN(yaw) || Float.isInfinite(pitch) || Float.isNaN(pitch)) {
throw new IllegalStateException(yaw + " " + pitch);
}
}
/**
@@ -19,14 +19,11 @@ package baritone.api.utils;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import net.minecraft.block.BlockState;
import net.minecraft.block.FireBlock;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.block.BlockFire;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.*;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import java.util.Optional;
@@ -137,7 +134,7 @@ public final class RotationUtils {
* @param ctx Context for the viewing entity
* @param pos The target block position
* @return The optional rotation
* @see #reachable(ClientPlayerEntity, BlockPos, double)
* @see #reachable(EntityPlayerSP, BlockPos, double)
*/
public static Optional<Rotation> reachable(IPlayerContext ctx, BlockPos pos) {
return reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
@@ -155,7 +152,7 @@ public final class RotationUtils {
* @param blockReachDistance The block reach distance of the entity
* @return The optional rotation
*/
public static Optional<Rotation> reachable(ClientPlayerEntity entity, BlockPos pos, double blockReachDistance) {
public static Optional<Rotation> reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(entity);
if (baritone.getPlayerContext().isLookingAt(pos)) {
/*
@@ -176,15 +173,12 @@ public final class RotationUtils {
return possibleRotation;
}
BlockState state = entity.world.getBlockState(pos);
VoxelShape shape = state.getShape(entity.world, pos);
if (shape.isEmpty()) {
shape = VoxelShapes.fullCube();
}
IBlockState state = entity.world.getBlockState(pos);
AxisAlignedBB aabb = state.getBoundingBox(entity.world, pos);
for (Vec3d sideOffset : BLOCK_SIDE_MULTIPLIERS) {
double xDiff = shape.getStart(Direction.Axis.X) * sideOffset.x + shape.getEnd(Direction.Axis.X) * (1 - sideOffset.x);
double yDiff = shape.getStart(Direction.Axis.Y) * sideOffset.y + shape.getEnd(Direction.Axis.Y) * (1 - sideOffset.y);
double zDiff = shape.getStart(Direction.Axis.Z) * sideOffset.z + shape.getEnd(Direction.Axis.Z) * (1 - sideOffset.z);
double xDiff = aabb.minX * sideOffset.x + aabb.maxX * (1 - sideOffset.x);
double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y);
double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z);
possibleRotation = reachableOffset(entity, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff), blockReachDistance);
if (possibleRotation.isPresent()) {
return possibleRotation;
@@ -205,14 +199,14 @@ public final class RotationUtils {
* @return The optional rotation
*/
public static Optional<Rotation> reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos, double blockReachDistance) {
Rotation rotation = calcRotationFromVec3d(entity.getEyePosition(1.0F), offsetPos, new Rotation(entity.rotationYaw, entity.rotationPitch));
Rotation rotation = calcRotationFromVec3d(entity.getPositionEyes(1.0F), offsetPos, new Rotation(entity.rotationYaw, entity.rotationPitch));
RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, rotation, blockReachDistance);
//System.out.println(result);
if (result != null && result.getType() == RayTraceResult.Type.BLOCK) {
if (((BlockRayTraceResult) result).getPos().equals(pos)) {
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
if (result.getBlockPos().equals(pos)) {
return Optional.of(rotation);
}
if (entity.world.getBlockState(pos).getBlock() instanceof FireBlock && ((BlockRayTraceResult) result).getPos().equals(pos.down())) {
if (entity.world.getBlockState(pos).getBlock() instanceof BlockFire && result.getBlockPos().equals(pos.down())) {
return Optional.of(rotation);
}
}
@@ -20,12 +20,9 @@ package baritone.api.utils;
import baritone.api.BaritoneAPI;
import baritone.api.Settings;
import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.item.Item;
import net.minecraft.util.Direction;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.Vec3i;
import net.minecraft.util.registry.Registry;
import java.awt.*;
import java.io.BufferedReader;
@@ -46,13 +43,13 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static net.minecraft.client.Minecraft.getMinecraft;
public class SettingsUtil {
private static final Path SETTINGS_PATH = Minecraft.getInstance().gameDir.toPath().resolve("baritone").resolve("settings.txt");
private static final Path SETTINGS_PATH = getMinecraft().gameDir.toPath().resolve("baritone").resolve("settings.txt");
private static final Pattern SETTING_PATTERN = Pattern.compile("^(?<setting>[^ ]+) +(?<value>.+)"); // key and value split by the first space
private static boolean isComment(String line) {
return line.startsWith("#") || line.startsWith("//");
}
@@ -218,7 +215,7 @@ public class SettingsUtil {
FLOAT(Float.class, Float::parseFloat),
LONG(Long.class, Long::parseLong),
STRING(String.class, String::new),
DIRECTION(Direction.class, Direction::byName),
ENUMFACING(EnumFacing.class, EnumFacing::byName),
COLOR(
Color.class,
str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])),
@@ -236,14 +233,15 @@ public class SettingsUtil {
),
ITEM(
Item.class,
str -> Registry.ITEM.getOrDefault(new ResourceLocation(str.trim())), // TODO this now returns AIR on failure instead of null, is that an issue?
item -> Registry.ITEM.getKey(item).toString()
str -> Item.getByNameOrId(str.trim()),
item -> Item.REGISTRY.getNameForObject(item).toString()
),
LIST() {
@Override
public Object parse(ParserContext context, String raw) {
Type type = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[0];
Parser parser = Parser.getParser(type);
return Stream.of(raw.split(","))
.map(s -> parser.parse(context, s))
.collect(Collectors.toList());
+11 -18
View File
@@ -17,13 +17,12 @@
package baritone.api.utils;
import net.minecraft.block.BlockState;
import net.minecraft.block.FireBlock;
import net.minecraft.block.BlockFire;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity;
import net.minecraft.util.Direction;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.World;
/**
@@ -43,18 +42,12 @@ public final class VecUtils {
* @see #getBlockPosCenter(BlockPos)
*/
public static Vec3d calculateBlockCenter(World world, BlockPos pos) {
BlockState b = world.getBlockState(pos);
VoxelShape shape = b.getCollisionShape(world, pos);
if (shape.isEmpty()) {
return getBlockPosCenter(pos);
}
double xDiff = (shape.getStart(Direction.Axis.X) + shape.getEnd(Direction.Axis.X)) / 2;
double yDiff = (shape.getStart(Direction.Axis.Y) + shape.getEnd(Direction.Axis.Y)) / 2;
double zDiff = (shape.getStart(Direction.Axis.Z) + shape.getEnd(Direction.Axis.Z)) / 2;
if (Double.isNaN(xDiff) || Double.isNaN(yDiff) || Double.isNaN(zDiff)) {
throw new IllegalStateException(b + " " + pos + " " + shape);
}
if (b.getBlock() instanceof FireBlock) {//look at bottom of fire when putting it out
IBlockState b = world.getBlockState(pos);
AxisAlignedBB bbox = b.getBoundingBox(world, pos);
double xDiff = (bbox.minX + bbox.maxX) / 2;
double yDiff = (bbox.minY + bbox.maxY) / 2;
double zDiff = (bbox.minZ + bbox.maxZ) / 2;
if (b.getBlock() instanceof BlockFire) {//look at bottom of fire when putting it out
yDiff = 0;
}
return new Vec3d(
@@ -105,7 +98,7 @@ public final class VecUtils {
* @see #getBlockPosCenter(BlockPos)
*/
public static double entityDistanceToCenter(Entity entity, BlockPos pos) {
return distanceToCenter(pos, entity.getPositionVec().x, entity.getPositionVec().y, entity.getPositionVec().z);
return distanceToCenter(pos, entity.posX, entity.posY, entity.posZ);
}
/**
@@ -118,6 +111,6 @@ public final class VecUtils {
* @see #getBlockPosCenter(BlockPos)
*/
public static double entityFlatDistanceToCenter(Entity entity, BlockPos pos) {
return distanceToCenter(pos, entity.getPositionVec().x, pos.getY() + 0.5, entity.getPositionVec().z);
return distanceToCenter(pos, entity.posX, pos.getY() + 0.5, entity.posZ);
}
}
@@ -1,105 +0,0 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch;
import com.google.common.base.Strings;
import com.google.gson.GsonBuilder;
import com.mojang.authlib.Agent;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.properties.PropertyMap;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
import net.minecraft.launchwrapper.Launch;
import java.io.File;
import java.lang.reflect.Field;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Based on GradleStart from ForgeGradle 2.3
*
* @author Brady
* @since 3/11/2019
*/
public class LaunchTesting {
public static void main(String[] args) {
Map<String, String> arguments = new HashMap<>();
hackNatives();
arguments.put("version", "BaritownedDeveloperEnvironment");
arguments.put("assetIndex", System.getenv("assetIndex"));
arguments.put("assetsDir", System.getenv().getOrDefault("assetDirectory", "assets"));
arguments.put("accessToken", "FML");
arguments.put("userProperties", "{}");
arguments.put("tweakClass", System.getenv("tweakClass"));
String password = System.getenv("password");
if (password != null && !password.isEmpty()) {
attemptLogin(arguments, System.getenv("username"), System.getenv("password"));
}
List<String> argsArray = new ArrayList<>();
arguments.forEach((k, v) -> {
argsArray.add("--" + k);
argsArray.add(v);
});
Launch.main(argsArray.toArray(new String[0]));
}
private static void hackNatives() {
String paths = System.getProperty("java.library.path");
String nativesDir = System.getenv().get("nativesDirectory");
if (Strings.isNullOrEmpty(paths))
paths = nativesDir;
else
paths += File.pathSeparator + nativesDir;
System.setProperty("java.library.path", paths);
// hack the classloader now.
try {
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
} catch (Throwable ignored) {}
}
private static void attemptLogin(Map<String, String> argMap, String username, String password) {
YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication) (new YggdrasilAuthenticationService(Proxy.NO_PROXY, "1")).createUserAuthentication(Agent.MINECRAFT);
auth.setUsername(username);
auth.setPassword(password);
try {
auth.logIn();
} catch (AuthenticationException var4) {
throw new RuntimeException(var4);
}
argMap.put("accessToken", auth.getAuthenticatedToken());
argMap.put("uuid", auth.getSelectedProfile().getId().toString().replace("-", ""));
argMap.put("username", auth.getSelectedProfile().getName());
argMap.put("userType", auth.getUserType().getName());
argMap.put("userProperties", (new GsonBuilder()).registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create().toJson(auth.getUserProperties()));
}
}
@@ -17,26 +17,27 @@
package baritone.launch.mixins;
import baritone.utils.accessor.IEntityRenderManager;
import net.minecraft.client.renderer.entity.EntityRendererManager;
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;
@Mixin(EntityRendererManager.class)
public class MixinEntityRenderManager implements IEntityRenderManager {
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 double renderPosX() {
return ((EntityRendererManager) (Object) this).info.getProjectedView().x;
}
@Override
public double renderPosY() {
return ((EntityRendererManager) (Object) this).info.getProjectedView().y;
}
@Override
public double renderPosZ() {
return ((EntityRendererManager) (Object) this).info.getProjectedView().z;
public File getChunkSaveLocation() {
return this.chunkSaveLocation;
}
}
@@ -18,26 +18,26 @@
package baritone.launch.mixins;
import baritone.utils.accessor.IBitArray;
import baritone.utils.accessor.IPalettedContainer;
import net.minecraft.block.BlockState;
import baritone.utils.accessor.IBlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.BitArray;
import net.minecraft.util.palette.IPalette;
import net.minecraft.util.palette.PalettedContainer;
import net.minecraft.world.chunk.BlockStateContainer;
import net.minecraft.world.chunk.IBlockStatePalette;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(PalettedContainer.class)
public abstract class MixinPalettedContainer implements IPalettedContainer {
@Mixin(BlockStateContainer.class)
public abstract class MixinBlockStateContainer implements IBlockStateContainer {
@Shadow
protected BitArray storage;
@Shadow
protected IPalette<BlockState> palette;
protected IBlockStatePalette palette;
@Override
public BlockState getAtPalette(int index) {
return palette.get(index);
public IBlockState getAtPalette(int index) {
return palette.getBlockState(index);
}
@Override
@@ -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 <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import net.minecraft.client.gui.GuiChat;
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;
@Mixin(GuiChat.ChatTabCompleter.class)
public abstract class MixinChatTabCompleter extends MixinTabCompleter {
@Inject(
method = "complete",
at = @At("HEAD"),
cancellable = true
)
private void onComplete(CallbackInfo ci) {
if (dontComplete) {
ci.cancel();
}
}
}
@@ -1,92 +0,0 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.utils.accessor.IChunkArray;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.Chunk;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.util.concurrent.atomic.AtomicReferenceArray;
@Mixin(targets = "net.minecraft.client.multiplayer.ClientChunkProvider$ChunkArray")
public abstract class MixinChunkArray implements IChunkArray {
@Shadow
private AtomicReferenceArray<Chunk> chunks;
@Shadow
private int viewDistance;
@Shadow
private int sideLength;
@Shadow
private int centerX;
@Shadow
private int centerZ;
@Shadow
private int loaded;
@Shadow
protected abstract boolean inView(int x, int z);
@Shadow
protected abstract int getIndex(int x, int z);
@Shadow
protected abstract void replace(int index, Chunk chunk);
@Override
public int centerX() {
return centerX;
}
@Override
public int centerZ() {
return centerZ;
}
@Override
public int viewDistance() {
return viewDistance;
}
@Override
public AtomicReferenceArray<Chunk> getChunks() {
return chunks;
}
@Override
public void copyFrom(IChunkArray other) {
centerX = other.centerX();
centerZ = other.centerZ();
AtomicReferenceArray<Chunk> copyingFrom = other.getChunks();
for (int k = 0; k < copyingFrom.length(); ++k) {
Chunk chunk = copyingFrom.get(k);
if (chunk != null) {
ChunkPos chunkpos = chunk.getPos();
if (inView(chunkpos.x, chunkpos.z)) {
int index = getIndex(chunkpos.x, chunkpos.z);
if (chunks.get(index) != null) {
throw new IllegalStateException("Doing this would mutate the client's REAL loaded chunks?!");
}
replace(index, chunk);
}
}
}
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.utils.accessor.IChunkProviderClient;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import net.minecraft.client.multiplayer.ChunkProviderClient;
import net.minecraft.world.chunk.Chunk;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(ChunkProviderClient.class)
public class MixinChunkProviderClient implements IChunkProviderClient {
@Shadow
@Final
private Long2ObjectMap<Chunk> loadedChunks;
@Override
public Long2ObjectMap<Chunk> loadedChunks() {
return this.loadedChunks;
}
}
@@ -0,0 +1,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 Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.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;
}
}
@@ -0,0 +1,52 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ChunkRenderContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.util.math.BlockPos;
import org.lwjgl.opengl.GL14;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import static org.lwjgl.opengl.GL11.*;
@Mixin(ChunkRenderContainer.class)
public class MixinChunkRenderContainer {
@Redirect( // avoid creating CallbackInfo at all costs; this is called 40k times per second
method = "preRenderChunk",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/chunk/RenderChunk.getPosition()Lnet/minecraft/util/math/BlockPos;"
)
)
private BlockPos getPosition(RenderChunk renderChunkIn) {
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer() && Minecraft.getMinecraft().world.getChunk(renderChunkIn.getPosition()).isEmpty()) {
GlStateManager.enableAlpha();
GlStateManager.enableBlend();
GL14.glBlendColor(0, 0, 0, Baritone.settings().cachedChunksOpacity.value);
GlStateManager.tryBlendFuncSeparate(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_ONE, GL_ZERO);
}
return renderChunkIn.getPosition();
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.utils.IPlayerContext;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.chunk.ChunkRenderWorker;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
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.Redirect;
@Mixin(ChunkRenderWorker.class)
public abstract class MixinChunkRenderWorker {
@Shadow
protected abstract boolean isChunkExisting(BlockPos pos, World worldIn);
@Redirect(
method = "processTask",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/chunk/ChunkRenderWorker.isChunkExisting(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/World;)Z"
)
)
private boolean isChunkExisting(ChunkRenderWorker worker, BlockPos pos, World world) {
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer()) {
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
IPlayerContext ctx = baritone.getPlayerContext();
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
return baritone.bsi.isLoaded(pos.getX(), pos.getZ()) || this.isChunkExisting(pos, world);
}
}
return this.isChunkExisting(pos, world);
}
}
@@ -1,61 +0,0 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.utils.accessor.IChunkArray;
import baritone.utils.accessor.IClientChunkProvider;
import net.minecraft.client.multiplayer.ClientChunkProvider;
import net.minecraft.client.world.ClientWorld;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.lang.reflect.Field;
import java.util.Arrays;
@Mixin(ClientChunkProvider.class)
public class MixinClientChunkProvider implements IClientChunkProvider {
@Shadow
private ClientWorld world;
@Override
public ClientChunkProvider createThreadSafeCopy() {
IChunkArray arr = extractReferenceArray();
ClientChunkProvider result = new ClientChunkProvider(world, arr.viewDistance() - 3); // -3 because its adds 3 for no reason lmao
IChunkArray copyArr = ((IClientChunkProvider) result).extractReferenceArray();
copyArr.copyFrom(arr);
if (copyArr.viewDistance() != arr.viewDistance()) {
throw new IllegalStateException(copyArr.viewDistance() + " " + arr.viewDistance());
}
return result;
}
@Override
public IChunkArray extractReferenceArray() {
for (Field f : ClientChunkProvider.class.getDeclaredFields()) {
if (IChunkArray.class.isAssignableFrom(f.getType())) {
try {
return (IChunkArray) f.get(this);
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
throw new RuntimeException(Arrays.toString(ClientChunkProvider.class.getDeclaredFields()));
}
}
@@ -1,100 +0,0 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.event.events.TabCompleteEvent;
import com.mojang.brigadier.context.StringRange;
import com.mojang.brigadier.suggestion.Suggestion;
import com.mojang.brigadier.suggestion.Suggestions;
import net.minecraft.client.gui.CommandSuggestionHelper;
import net.minecraft.client.gui.widget.TextFieldWidget;
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;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* @author Brady
* @since 10/9/2019
*/
@Mixin(CommandSuggestionHelper.class)
public class MixinCommandSuggestionHelper {
@Shadow
@Final
private TextFieldWidget field_228095_d_;
@Shadow
@Final
private List<String> field_228103_l_;
@Shadow
private CompletableFuture<Suggestions> field_228107_p_;
@Inject(
method = "func_228111_a_",
at = @At("HEAD"),
cancellable = true
)
private void preUpdateSuggestion(CallbackInfo ci) {
// Anything that is present in the input text before the cursor position
String prefix = this.field_228095_d_.getText().substring(0, Math.min(this.field_228095_d_.getText().length(), this.field_228095_d_.getCursorPosition()));
TabCompleteEvent event = new TabCompleteEvent(prefix);
BaritoneAPI.getProvider().getPrimaryBaritone().getGameEventHandler().onPreTabComplete(event);
if (event.isCancelled()) {
ci.cancel();
return;
}
if (event.completions != null) {
ci.cancel();
// TODO: Support populating the command usage
this.field_228103_l_.clear();
if (event.completions.length == 0) {
this.field_228107_p_ = Suggestions.empty();
} else {
int offset = this.field_228095_d_.getText().endsWith(" ")
? this.field_228095_d_.getCursorPosition()
: this.field_228095_d_.getText().lastIndexOf(" ") + 1; // If there is no space this is still 0 haha yes
List<Suggestion> suggestionList = Stream.of(event.completions)
.map(s -> new Suggestion(StringRange.between(offset, offset + s.length()), s))
.collect(Collectors.toList());
Suggestions suggestions = new Suggestions(
StringRange.between(offset, offset + suggestionList.stream().mapToInt(s -> s.getText().length()).max().orElse(0)),
suggestionList);
this.field_228107_p_ = new CompletableFuture<>();
this.field_228107_p_.complete(suggestions);
}
}
}
}
@@ -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 Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.event.events.RotationMoveEvent;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.entity.Entity;
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.callback.CallbackInfo;
@Mixin(Entity.class)
public class MixinEntity {
@Shadow
private float rotationYaw;
float yawRestore;
@Inject(
method = "moveRelative",
at = @At("HEAD")
)
private void moveRelativeHead(CallbackInfo info) {
this.yawRestore = this.rotationYaw;
// noinspection ConstantConditions
if (!ClientPlayerEntity.class.isInstance(this) || BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this) == null) {
return;
}
RotationMoveEvent motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this).getGameEventHandler().onPlayerRotationMove(motionUpdateRotationEvent);
this.rotationYaw = motionUpdateRotationEvent.getYaw();
}
@Inject(
method = "moveRelative",
at = @At("RETURN")
)
private void moveRelativeReturn(CallbackInfo info) {
this.rotationYaw = this.yawRestore;
}
}
@@ -20,11 +20,9 @@ package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.event.events.RotationMoveEvent;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.math.Vec3d;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -38,16 +36,17 @@ import static org.spongepowered.asm.lib.Opcodes.GETFIELD;
* @author Brady
* @since 9/10/2018
*/
@Mixin(LivingEntity.class)
public abstract class MixinLivingEntity extends Entity {
@Mixin(EntityLivingBase.class)
public abstract class MixinEntityLivingBase extends Entity {
/**
* Event called to override the movement direction when jumping
*/
private RotationMoveEvent jumpRotationEvent;
public MixinLivingEntity(EntityType<?> entityTypeIn, World worldIn) {
super(entityTypeIn, worldIn);
public MixinEntityLivingBase(World worldIn, RotationMoveEvent jumpRotationEvent) {
super(worldIn);
this.jumpRotationEvent = jumpRotationEvent;
}
@Inject(
@@ -56,8 +55,8 @@ public abstract class MixinLivingEntity extends Entity {
)
private void preMoveRelative(CallbackInfo ci) {
// noinspection ConstantConditions
if (ClientPlayerEntity.class.isInstance(this)) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this);
if (EntityPlayerSP.class.isInstance(this)) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone != null) {
this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw);
baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent);
@@ -70,15 +69,34 @@ public abstract class MixinLivingEntity extends Entity {
at = @At(
value = "FIELD",
opcode = GETFIELD,
target = "net/minecraft/entity/LivingEntity.rotationYaw:F"
target = "net/minecraft/entity/EntityLivingBase.rotationYaw:F"
)
)
private float overrideYaw(LivingEntity self) {
if (self instanceof ClientPlayerEntity && BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this) != null) {
private float overrideYaw(EntityLivingBase self) {
if (self instanceof EntityPlayerSP && BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this) != null) {
return this.jumpRotationEvent.getYaw();
}
return self.rotationYaw;
}
@Redirect(
method = "travel",
at = @At(
value = "INVOKE",
target = "net/minecraft/entity/EntityLivingBase.moveRelative(FFFF)V"
)
)
private void travel(EntityLivingBase self, float strafe, float up, float forward, float friction) {
// noinspection ConstantConditions
if (!EntityPlayerSP.class.isInstance(this) || BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this) == null) {
moveRelative(strafe, up, forward, friction);
return;
}
RotationMoveEvent motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(motionUpdateRotationEvent);
float originalYaw = this.rotationYaw;
this.rotationYaw = motionUpdateRotationEvent.getYaw();
this.moveRelative(strafe, up, forward, friction);
this.rotationYaw = originalYaw;
}
}
@@ -24,9 +24,9 @@ import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.SprintStateEvent;
import baritone.api.event.events.type.EventState;
import baritone.behavior.LookBehavior;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.player.PlayerAbilities;
import net.minecraft.entity.player.PlayerCapabilities;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -37,8 +37,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
* @author Brady
* @since 8/1/2018
*/
@Mixin(ClientPlayerEntity.class)
public class MixinClientPlayerEntity {
@Mixin(EntityPlayerSP.class)
public class MixinEntityPlayerSP {
@Inject(
method = "sendChatMessage",
@@ -47,7 +47,7 @@ public class MixinClientPlayerEntity {
)
private void sendChatMessage(String msg, CallbackInfo ci) {
ChatEvent event = new ChatEvent(msg);
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this);
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone == null) {
return;
}
@@ -58,46 +58,46 @@ public class MixinClientPlayerEntity {
}
@Inject(
method = "tick",
method = "onUpdate",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/entity/player/ClientPlayerEntity.isPassenger()Z",
target = "net/minecraft/client/entity/EntityPlayerSP.isRiding()Z",
shift = At.Shift.BY,
by = -3
)
)
private void onPreUpdate(CallbackInfo ci) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this);
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone != null) {
baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.PRE));
}
}
@Inject(
method = "tick",
method = "onUpdate",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/entity/player/ClientPlayerEntity.onUpdateWalkingPlayer()V",
target = "net/minecraft/client/entity/EntityPlayerSP.onUpdateWalkingPlayer()V",
shift = At.Shift.BY,
by = 2
)
)
private void onPostUpdate(CallbackInfo ci) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this);
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone != null) {
baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
}
}
@Redirect(
method = "livingTick",
method = "onLivingUpdate",
at = @At(
value = "FIELD",
target = "net/minecraft/entity/player/PlayerAbilities.allowFlying:Z"
target = "net/minecraft/entity/player/PlayerCapabilities.allowFlying:Z"
)
)
private boolean isAllowFlying(PlayerAbilities capabilities) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this);
private boolean isAllowFlying(PlayerCapabilities capabilities) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone == null) {
return capabilities.allowFlying;
}
@@ -105,14 +105,14 @@ public class MixinClientPlayerEntity {
}
@Redirect(
method = "livingTick",
method = "onLivingUpdate",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/settings/KeyBinding.isKeyDown()Z"
)
)
private boolean isKeyDown(KeyBinding keyBinding) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this);
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone == null) {
return keyBinding.isKeyDown();
}
@@ -135,7 +135,7 @@ public class MixinClientPlayerEntity {
)
)
private void updateRidden(CallbackInfo cb) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this);
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone != null) {
((LookBehavior) baritone.getLookBehavior()).pig();
}
@@ -20,29 +20,26 @@ package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.event.events.RenderEvent;
import com.mojang.blaze3d.matrix.MatrixStack;
import net.minecraft.client.renderer.*;
import net.minecraft.client.renderer.EntityRenderer;
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;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
/**
* @author Brady
* @since 2/13/2020
*/
@Mixin(WorldRenderer.class)
public class MixinWorldRenderer {
@Mixin(EntityRenderer.class)
public class MixinEntityRenderer {
@Inject(
method = "updateCameraAndRender",
at = @At("RETURN"),
locals = LocalCapture.CAPTURE_FAILSOFT
method = "renderWorldPass",
at = @At(
value = "INVOKE_STRING",
target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V",
args = {"ldc=hand"}
)
)
private void onStartHand(MatrixStack matrixStackIn, float partialTicks, long finishTimeNano, boolean drawBlockOutline, ActiveRenderInfo activeRenderInfoIn, GameRenderer gameRendererIn, LightTexture lightmapIn, Matrix4f projectionIn, CallbackInfo ci) {
private void renderWorldPass(int pass, float partialTicks, long finishTimeNano, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
ibaritone.getGameEventHandler().onRenderPass(new RenderEvent(partialTicks, matrixStackIn, projectionIn));
ibaritone.getGameEventHandler().onRenderPass(new RenderEvent(partialTicks));
}
}
}
}
@@ -18,16 +18,16 @@
package baritone.launch.mixins;
import baritone.utils.accessor.IGuiScreen;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.gui.GuiScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.net.URI;
@Mixin(Screen.class)
public abstract class MixinScreen implements IGuiScreen {
@Mixin(GuiScreen.class)
public abstract class MixinGuiScreen implements IGuiScreen {
@Override
@Invoker("openLink")
public abstract void openLinkInvoker(URI url);
@Invoker("openWebLink")
public abstract void openLink(URI url);
}
@@ -35,14 +35,14 @@ public abstract class MixinItemStack implements IItemStack {
@Final
private Item item;
@Shadow
private int itemDamage;
@Unique
private int baritoneHash;
@Shadow
protected abstract int getDamage();
private void recalculateHash() {
baritoneHash = item == null ? -1 : item.hashCode() + getDamage();
baritoneHash = item == null ? -1 : item.hashCode() + itemDamage;
}
@Inject(
@@ -54,7 +54,7 @@ public abstract class MixinItemStack implements IItemStack {
}
@Inject(
method = "setDamage",
method = "setItemDamage",
at = @At("TAIL")
)
private void onItemDamageSet(CallbackInfo ci) {
@@ -1,74 +0,0 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.api.utils.BlockOptionalMeta;
import net.minecraft.server.MinecraftServer;
import net.minecraft.world.server.ServerWorld;
import net.minecraft.world.storage.loot.LootContext;
import net.minecraft.world.storage.loot.LootPredicateManager;
import net.minecraft.world.storage.loot.LootTableManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(LootContext.Builder.class)
public class MixinLootContext {
@Redirect(
method = "build",
at = @At(
value = "INVOKE",
target = "net/minecraft/world/server/ServerWorld.getServer()Lnet/minecraft/server/MinecraftServer;"
)
)
private MinecraftServer getServer(ServerWorld world) {
if (world == null) {
return null;
}
return world.getServer();
}
@Redirect(
method = "build",
at = @At(
value = "INVOKE",
target = "net/minecraft/server/MinecraftServer.getLootTableManager()Lnet/minecraft/world/storage/loot/LootTableManager;"
)
)
private LootTableManager getLootTableManager(MinecraftServer server) {
if (server == null) {
return BlockOptionalMeta.getManager();
}
return server.getLootTableManager();
}
@Redirect(
method = "build",
at = @At(
value = "INVOKE",
target = "net/minecraft/server/MinecraftServer.func_229736_aP_()Lnet/minecraft/world/storage/loot/LootPredicateManager;"
)
)
private LootPredicateManager getLootPredicateManager(MinecraftServer server) {
if (server == null) {
return BlockOptionalMeta.getPredicateManager();
}
return server.func_229736_aP_();
}
}
@@ -19,14 +19,19 @@ package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
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.utils.BaritoneAutoTest;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.client.world.ClientWorld;
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;
@@ -34,6 +39,7 @@ 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;
import java.util.function.BiFunction;
@@ -45,12 +51,12 @@ import java.util.function.BiFunction;
public class MixinMinecraft {
@Shadow
public ClientPlayerEntity player;
public EntityPlayerSP player;
@Shadow
public ClientWorld world;
public WorldClient world;
@Inject(
method = "<init>",
method = "init",
at = @At("RETURN")
)
private void postInit(CallbackInfo ci) {
@@ -58,8 +64,11 @@ public class MixinMinecraft {
}
@Inject(
method = "startTimerHackThread",
at = @At("HEAD")
method = "init",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/Minecraft.startTimerHackThread()V"
)
)
private void preInit(CallbackInfo ci) {
BaritoneAutoTest.INSTANCE.onPreInit();
@@ -70,7 +79,7 @@ public class MixinMinecraft {
at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "net/minecraft/client/Minecraft.currentScreen:Lnet/minecraft/client/gui/screen/Screen;",
target = "net/minecraft/client/Minecraft.currentScreen:Lnet/minecraft/client/gui/GuiScreen;",
ordinal = 5,
shift = At.Shift.BY,
by = -3
@@ -91,10 +100,10 @@ public class MixinMinecraft {
}
@Inject(
method = "loadWorld(Lnet/minecraft/client/world/ClientWorld;)V",
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
at = @At("HEAD")
)
private void preLoadWorld(ClientWorld world, CallbackInfo ci) {
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;
@@ -111,10 +120,10 @@ public class MixinMinecraft {
}
@Inject(
method = "loadWorld(Lnet/minecraft/client/world/ClientWorld;)V",
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
at = @At("RETURN")
)
private void postLoadWorld(ClientWorld world, CallbackInfo ci) {
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
// mc.world changing is only the primary baritone
@@ -131,32 +140,37 @@ public class MixinMinecraft {
at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "net/minecraft/client/gui/screen/Screen.passEvents:Z"
target = "net/minecraft/client/gui/GuiScreen.allowUserInput:Z"
)
)
private boolean passEvents(Screen screen) {
private boolean isAllowUserInput(GuiScreen screen) {
// allow user input is only the primary baritone
return (BaritoneAPI.getProvider().getPrimaryBaritone().getPathingBehavior().getCurrent() != null && player != null) || screen.passEvents;
return (BaritoneAPI.getProvider().getPrimaryBaritone().getPathingBehavior().getCurrent() != null && player != null) || screen.allowUserInput;
}
// TODO
// FIXME
// bradyfix
// i cant mixin
// lol
// https://discordapp.com/channels/208753003996512258/503692253881958400/674760939681349652
// https://discordapp.com/channels/208753003996512258/503692253881958400/674756457966862376
/*@Inject(
method = "rightClickMouse",
@Inject(
method = "clickMouse",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/entity/player/ClientPlayerEntity.swingArm(Lnet/minecraft/util/Hand;)V",
ordinal = 1
target = "net/minecraft/client/multiplayer/PlayerControllerMP.clickBlock(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)Z"
),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void onBlockUse(CallbackInfo ci, Hand var1[], int var2, int var3, Hand enumhand, ItemStack itemstack, EntityRayTraceResult rt, Entity ent, ActionResultType art, BlockRayTraceResult raytrace, int i, ActionResultType enumactionresult) {
private void onBlockBreak(CallbackInfo ci, BlockPos pos) {
// clickMouse is only for the main player
BaritoneAPI.getProvider().getPrimaryBaritone().getGameEventHandler().onBlockInteract(new BlockInteractEvent(pos, BlockInteractEvent.Type.START_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) {
// rightClickMouse is only for the main player
BaritoneAPI.getProvider().getPrimaryBaritone().getGameEventHandler().onBlockInteract(new BlockInteractEvent(raytrace.getPos(), BlockInteractEvent.Type.USE));
}*/
BaritoneAPI.getProvider().getPrimaryBaritone().getGameEventHandler().onBlockInteract(new BlockInteractEvent(blockpos, BlockInteractEvent.Type.USE));
}
}
@@ -21,10 +21,9 @@ import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.event.events.ChunkEvent;
import baritone.api.event.events.type.EventState;
import net.minecraft.client.network.play.ClientPlayNetHandler;
import net.minecraft.network.play.server.SChunkDataPacket;
import net.minecraft.network.play.server.SCombatPacket;
import net.minecraft.network.play.server.SUnloadChunkPacket;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.network.play.server.SPacketChunkData;
import net.minecraft.network.play.server.SPacketCombatEvent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
@@ -34,15 +33,14 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
* @author Brady
* @since 8/3/2018
*/
@Mixin(ClientPlayNetHandler.class)
public class MixinClientPlayNetHandler {
@Mixin(NetHandlerPlayClient.class)
public class MixinNetHandlerPlayClient {
// unused lol
/*@Inject(
@Inject(
method = "handleChunkData",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/multiplayer/ChunkProviderClient.func_212474_a(IILnet/minecraft/network/PacketBuffer;IZ)Lnet/minecraft/world/chunk/Chunk;"
target = "net/minecraft/world/chunk/Chunk.read(Lnet/minecraft/network/PacketBuffer;IZ)V"
)
)
private void preRead(SPacketChunkData packetIn, CallbackInfo ci) {
@@ -58,15 +56,15 @@ public class MixinClientPlayNetHandler {
);
}
}
}*/
}
@Inject(
method = "handleChunkData",
at = @At("RETURN")
)
private void postHandleChunkData(SChunkDataPacket packetIn, CallbackInfo ci) {
private void postHandleChunkData(SPacketChunkData packetIn, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
if (ibaritone.getPlayerContext().player().connection == (ClientPlayNetHandler) (Object) this) {
if (ibaritone.getPlayerContext().player().connection == (NetHandlerPlayClient) (Object) this) {
ibaritone.getGameEventHandler().onChunkEvent(
new ChunkEvent(
EventState.POST,
@@ -79,44 +77,16 @@ public class MixinClientPlayNetHandler {
}
}
@Inject(
method = "processChunkUnload",
at = @At("HEAD")
)
private void preChunkUnload(SUnloadChunkPacket packet, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
if (ibaritone.getPlayerContext().player().connection == (ClientPlayNetHandler) (Object) this) {
ibaritone.getGameEventHandler().onChunkEvent(
new ChunkEvent(EventState.PRE, ChunkEvent.Type.UNLOAD, packet.getX(), packet.getZ())
);
}
}
}
@Inject(
method = "processChunkUnload",
at = @At("RETURN")
)
private void postChunkUnload(SUnloadChunkPacket packet, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
if (ibaritone.getPlayerContext().player().connection == (ClientPlayNetHandler) (Object) this) {
ibaritone.getGameEventHandler().onChunkEvent(
new ChunkEvent(EventState.POST, ChunkEvent.Type.UNLOAD, packet.getX(), packet.getZ())
);
}
}
}
@Inject(
method = "handleCombatEvent",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/Minecraft.displayGuiScreen(Lnet/minecraft/client/gui/screen/Screen;)V"
target = "net/minecraft/client/Minecraft.displayGuiScreen(Lnet/minecraft/client/gui/GuiScreen;)V"
)
)
private void onPlayerDeath(SCombatPacket packetIn, CallbackInfo ci) {
private void onPlayerDeath(SPacketCombatEvent packetIn, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
if (ibaritone.getPlayerContext().player().connection == (ClientPlayNetHandler) (Object) this) {
if (ibaritone.getPlayerContext().player().connection == (NetHandlerPlayClient) (Object) this) {
ibaritone.getGameEventHandler().onPlayerDeath();
}
}
@@ -25,9 +25,9 @@ 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.IPacket;
import net.minecraft.network.EnumPacketDirection;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.PacketDirection;
import net.minecraft.network.Packet;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@@ -47,14 +47,14 @@ public class MixinNetworkManager {
@Shadow
@Final
private PacketDirection direction;
private EnumPacketDirection direction;
@Inject(
method = "dispatchPacket",
at = @At("HEAD")
)
private void preDispatchPacket(IPacket<?> inPacket, final GenericFutureListener<? extends Future<? super Void>> futureListeners, CallbackInfo ci) {
if (this.direction != PacketDirection.CLIENTBOUND) {
private void preDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>>[] futureListeners, CallbackInfo ci) {
if (this.direction != EnumPacketDirection.CLIENTBOUND) {
return;
}
@@ -69,8 +69,8 @@ public class MixinNetworkManager {
method = "dispatchPacket",
at = @At("RETURN")
)
private void postDispatchPacket(IPacket<?> inPacket, final GenericFutureListener<? extends Future<? super Void>> futureListeners, CallbackInfo ci) {
if (this.direction != PacketDirection.CLIENTBOUND) {
private void postDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>>[] futureListeners, CallbackInfo ci) {
if (this.direction != EnumPacketDirection.CLIENTBOUND) {
return;
}
@@ -85,11 +85,11 @@ public class MixinNetworkManager {
method = "channelRead0",
at = @At(
value = "INVOKE",
target = "net/minecraft/network/NetworkManager.processPacket(Lnet/minecraft/network/IPacket;Lnet/minecraft/network/INetHandler;)V"
target = "net/minecraft/network/Packet.processPacket(Lnet/minecraft/network/INetHandler;)V"
)
)
private void preProcessPacket(ChannelHandlerContext context, IPacket<?> packet, CallbackInfo ci) {
if (this.direction != PacketDirection.CLIENTBOUND) {
private void preProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
if (this.direction != EnumPacketDirection.CLIENTBOUND) {
return;
}
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
@@ -103,8 +103,8 @@ public class MixinNetworkManager {
method = "channelRead0",
at = @At("RETURN")
)
private void postProcessPacket(ChannelHandlerContext context, IPacket<?> packet, CallbackInfo ci) {
if (!this.channel.isOpen() || this.direction != PacketDirection.CLIENTBOUND) {
private void postProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
if (!this.channel.isOpen() || this.direction != EnumPacketDirection.CLIENTBOUND) {
return;
}
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
@@ -18,14 +18,14 @@
package baritone.launch.mixins;
import baritone.utils.accessor.IPlayerControllerMP;
import net.minecraft.client.multiplayer.PlayerController;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.gen.Invoker;
@Mixin(PlayerController.class)
public abstract class MixinPlayerController implements IPlayerControllerMP {
@Mixin(PlayerControllerMP.class)
public abstract class MixinPlayerControllerMP implements IPlayerControllerMP {
@Accessor
@Override
@@ -0,0 +1,89 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.utils.IPlayerContext;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ChunkCache;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* @author Brady
* @since 1/29/2019
*/
@Mixin(RenderChunk.class)
public class MixinRenderChunk {
@Redirect(
method = "rebuildChunk",
at = @At(
value = "INVOKE",
target = "net/minecraft/world/ChunkCache.isEmpty()Z"
)
)
private boolean isEmpty(ChunkCache chunkCache) {
if (!chunkCache.isEmpty()) {
return false;
}
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer()) {
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
IPlayerContext ctx = baritone.getPlayerContext();
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
BlockPos position = ((RenderChunk) (Object) this).getPosition();
// RenderChunk extends from -1,-1,-1 to +16,+16,+16
// then the constructor of ChunkCache extends it one more (presumably to get things like the connected status of fences? idk)
// so if ANY of the adjacent chunks are loaded, we are unempty
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
if (baritone.bsi.isLoaded(16 * dx + position.getX(), 16 * dz + position.getZ())) {
return false;
}
}
}
}
}
return true;
}
@Redirect(
method = "rebuildChunk",
at = @At(
value = "INVOKE",
target = "net/minecraft/world/ChunkCache.getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;"
)
)
private IBlockState getBlockState(ChunkCache chunkCache, BlockPos pos) {
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer()) {
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
IPlayerContext ctx = baritone.getPlayerContext();
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
return baritone.bsi.get0(pos);
}
}
return chunkCache.getBlockState(pos);
}
}
@@ -0,0 +1,47 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import static org.lwjgl.opengl.GL11.*;
@Mixin(RenderList.class)
public class MixinRenderList {
@Redirect( // avoid creating CallbackInfo at all costs; this is called 40k times per second
method = "renderChunkLayer",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V"
)
)
private void popMatrix() {
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer()) {
// reset the blend func to normal (not dependent on constant alpha)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
}
GlStateManager.popMatrix();
}
}
@@ -0,0 +1,60 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import com.google.common.collect.ImmutableMap;
import net.minecraft.block.properties.IProperty;
import org.spongepowered.asm.mixin.*;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(targets = "net.minecraft.block.state.BlockStateContainer$StateImplementation")
public abstract class MixinStateImplementation {
@Shadow
@Final
private ImmutableMap<IProperty<?>, Comparable<?>> properties;
/**
* Block states are fucking immutable
*/
@Unique
private int hashCode;
@Inject(
method = "<init>*",
at = @At("RETURN")
)
private void onInit(CallbackInfo ci) {
hashCode = properties.hashCode();
}
/**
* Cache this instead of using the fucking map every time
*
* @author LoganDark
* @reason Regular IBlockState generates a new hash every fucking time. This is not needed when scanning millions
* per second
*/
@Override
@Overwrite
public int hashCode() {
return hashCode;
}
}
@@ -0,0 +1,83 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.event.events.TabCompleteEvent;
import net.minecraft.client.gui.GuiChat;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.util.TabCompleter;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(TabCompleter.class)
public abstract class MixinTabCompleter {
@Shadow
@Final
protected GuiTextField textField;
@Shadow
protected boolean requestedCompletions;
@Shadow
public abstract void setCompletions(String... newCompl);
@Unique
protected boolean dontComplete = false;
@Inject(
method = "requestCompletions",
at = @At("HEAD"),
cancellable = true
)
private void onRequestCompletions(String prefix, CallbackInfo ci) {
if (!((Object) this instanceof GuiChat.ChatTabCompleter)) {
return;
}
IBaritone baritone = BaritoneAPI.getProvider().getPrimaryBaritone();
TabCompleteEvent event = new TabCompleteEvent(prefix);
baritone.getGameEventHandler().onPreTabComplete(event);
if (event.isCancelled()) {
ci.cancel();
return;
}
if (event.completions != null) {
ci.cancel();
this.dontComplete = true;
try {
this.requestedCompletions = true;
setCompletions(event.completions);
} finally {
this.dontComplete = false;
}
}
}
}
@@ -0,0 +1,47 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.VboRenderList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import static org.lwjgl.opengl.GL11.*;
@Mixin(VboRenderList.class)
public class MixinVboRenderList {
@Redirect( // avoid creating CallbackInfo at all costs; this is called 40k times per second
method = "renderChunkLayer",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V"
)
)
private void popMatrix() {
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer()) {
// reset the blend func to normal (not dependent on constant alpha)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
}
GlStateManager.popMatrix();
}
}
@@ -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 <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.event.events.ChunkEvent;
import baritone.api.event.events.type.EventState;
import net.minecraft.client.multiplayer.WorldClient;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* @author Brady
* @since 8/2/2018
*/
@Mixin(WorldClient.class)
public class MixinWorldClient {
@Inject(
method = "doPreChunk",
at = @At("HEAD")
)
private void preDoPreChunk(int chunkX, int chunkZ, boolean loadChunk, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
if (ibaritone.getPlayerContext().world() == (WorldClient) (Object) this) {
ibaritone.getGameEventHandler().onChunkEvent(
new ChunkEvent(
EventState.PRE,
loadChunk ? ChunkEvent.Type.LOAD : ChunkEvent.Type.UNLOAD,
chunkX,
chunkZ
)
);
}
}
}
@Inject(
method = "doPreChunk",
at = @At("RETURN")
)
private void postDoPreChunk(int chunkX, int chunkZ, boolean loadChunk, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
if (ibaritone.getPlayerContext().world() == (WorldClient) (Object) this) {
ibaritone.getGameEventHandler().onChunkEvent(
new ChunkEvent(
EventState.POST,
loadChunk ? ChunkEvent.Type.LOAD : ChunkEvent.Type.UNLOAD,
chunkX,
chunkZ
)
);
}
}
}
}
+19 -13
View File
@@ -8,22 +8,28 @@
"maxShiftBy": 2
},
"client": [
"MixinAnvilChunkLoader",
"MixinBitArray",
"MixinChunkArray",
"MixinClientChunkProvider",
"MixinClientPlayerEntity",
"MixinClientPlayNetHandler",
"MixinCommandSuggestionHelper",
"MixinEntity",
"MixinEntityRenderManager",
"MixinBlockStateContainer",
"MixinChatTabCompleter",
"MixinChunkProviderClient",
"MixinChunkProviderServer",
"MixinChunkRenderContainer",
"MixinChunkRenderWorker",
"MixinEntityLivingBase",
"MixinEntityPlayerSP",
"MixinEntityRenderer",
"MixinGuiScreen",
"MixinItemStack",
"MixinLivingEntity",
"MixinLootContext",
"MixinMinecraft",
"MixinNetHandlerPlayClient",
"MixinNetworkManager",
"MixinPalettedContainer",
"MixinPlayerController",
"MixinScreen",
"MixinWorldRenderer"
"MixinPlayerControllerMP",
"MixinRenderChunk",
"MixinRenderList",
"MixinStateImplementation",
"MixinTabCompleter",
"MixinVboRenderList",
"MixinWorldClient"
]
}
+6 -7
View File
@@ -25,12 +25,11 @@ import baritone.api.utils.Helper;
import baritone.api.utils.IPlayerContext;
import baritone.behavior.*;
import baritone.cache.WorldProvider;
import baritone.command.manager.CommandManager;
import baritone.event.GameEventHandler;
import baritone.process.*;
import baritone.selection.SelectionManager;
import baritone.utils.*;
import baritone.command.manager.CommandManager;
import baritone.utils.player.PrimaryPlayerContext;
import net.minecraft.client.Minecraft;
import java.io.File;
@@ -53,7 +52,7 @@ public class Baritone implements IBaritone {
static {
threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
dir = new File(Minecraft.getInstance().gameDir, "baritone");
dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
if (!Files.exists(dir.toPath())) {
try {
Files.createDirectories(dir.toPath());
@@ -87,11 +86,11 @@ public class Baritone implements IBaritone {
public BlockStateInterface bsi;
Baritone() {
public Baritone(IPlayerContext playerContext) {
this.gameEventHandler = new GameEventHandler(this);
// Define this before behaviors try and get it, or else it will be null and the builds will fail!
this.playerContext = PrimaryPlayerContext.INSTANCE;
this.playerContext = playerContext;
{
// the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist
@@ -218,7 +217,7 @@ public class Baritone implements IBaritone {
new Thread(() -> {
try {
Thread.sleep(100);
Helper.mc.execute(() -> Helper.mc.displayGuiScreen(new GuiClick()));
Helper.mc.addScheduledTask(() -> Helper.mc.displayGuiScreen(new GuiClick()));
} catch (Exception ignored) {}
}).start();
}
@@ -234,4 +233,4 @@ public class Baritone implements IBaritone {
public static Executor getExecutor() {
return threadPool;
}
}
}
+17 -5
View File
@@ -19,15 +19,19 @@ package baritone;
import baritone.api.IBaritone;
import baritone.api.IBaritoneProvider;
import baritone.api.bot.IBaritoneUser;
import baritone.api.bot.IUserManager;
import baritone.api.cache.IWorldScanner;
import baritone.api.command.ICommandSystem;
import baritone.bot.UserManager;
import baritone.api.schematic.ISchematicSystem;
import baritone.command.BaritoneChatControl;
import baritone.cache.WorldScanner;
import baritone.command.CommandSystem;
import baritone.utils.player.PrimaryPlayerContext;
import baritone.utils.schematic.SchematicSystem;
import java.util.Collections;
import java.util.ArrayList;
import java.util.List;
/**
@@ -37,11 +41,9 @@ import java.util.List;
public final class BaritoneProvider implements IBaritoneProvider {
private final Baritone primary;
private final List<IBaritone> all;
{
this.primary = new Baritone();
this.all = Collections.singletonList(this.primary);
this.primary = new Baritone(PrimaryPlayerContext.INSTANCE);
// Setup chat control, just for the primary instance
new BaritoneChatControl(this.primary);
@@ -54,7 +56,12 @@ public final class BaritoneProvider implements IBaritoneProvider {
@Override
public List<IBaritone> getAllBaritones() {
return all;
List<IBaritone> baritones = new ArrayList<>();
baritones.add(getPrimaryBaritone());
for (IBaritoneUser ibu : UserManager.INSTANCE.users()) {
baritones.add(ibu.getBaritone());
}
return baritones;
}
@Override
@@ -62,6 +69,11 @@ public final class BaritoneProvider implements IBaritoneProvider {
return WorldScanner.INSTANCE;
}
@Override
public IUserManager getUserManager() {
return UserManager.INSTANCE;
}
@Override
public ICommandSystem getCommandSystem() {
return CommandSystem.INSTANCE;
@@ -21,16 +21,13 @@ import baritone.Baritone;
import baritone.api.event.events.TickEvent;
import baritone.utils.ToolSet;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.inventory.container.ClickType;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.*;
import net.minecraft.util.Direction;
import net.minecraft.util.Hand;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.Vec3d;
import java.util.ArrayList;
import java.util.OptionalInt;
@@ -51,14 +48,14 @@ public final class InventoryBehavior extends Behavior {
if (event.getType() == TickEvent.Type.OUT) {
return;
}
if (ctx.player().openContainer != ctx.player().container) {
if (ctx.player().openContainer != ctx.player().inventoryContainer) {
// we have a crafting table or a chest or something open
return;
}
if (firstValidThrowaway() >= 9) { // aka there are none on the hotbar, but there are some in main inventory
swapWithHotBar(firstValidThrowaway(), 8);
}
int pick = bestToolAgainst(Blocks.STONE, PickaxeItem.class);
int pick = bestToolAgainst(Blocks.STONE, ItemPickaxe.class);
if (pick >= 9) {
swapWithHotBar(pick, 0);
}
@@ -93,7 +90,7 @@ public final class InventoryBehavior extends Behavior {
}
private void swapWithHotBar(int inInventory, int inHotbar) {
ctx.playerController().windowClick(ctx.player().container.windowId, inInventory < 9 ? inInventory + 36 : inInventory, inHotbar, ClickType.SWAP, ctx.player());
ctx.playerController().windowClick(ctx.player().inventoryContainer.windowId, inInventory < 9 ? inInventory + 36 : inInventory, inHotbar, ClickType.SWAP, ctx.player());
}
private int firstValidThrowaway() { // TODO offhand idk
@@ -106,7 +103,7 @@ public final class InventoryBehavior extends Behavior {
return -1;
}
private int bestToolAgainst(Block against, Class<? extends ToolItem> cla$$) {
private int bestToolAgainst(Block against, Class<? extends ItemTool> cla$$) {
NonNullList<ItemStack> invy = ctx.player().inventory.mainInventory;
int bestInd = -1;
double bestSpeed = -1;
@@ -136,11 +133,11 @@ public final class InventoryBehavior extends Behavior {
}
public boolean selectThrowawayForLocation(boolean select, int x, int y, int z) {
BlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z, baritone.bsi.get0(x, y, z));
if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof BlockItem && maybe.equals(((BlockItem) stack.getItem()).getBlock().getStateForPlacement(new BlockItemUseContext(new ItemUseContext(ctx.world(), ctx.player(), Hand.MAIN_HAND, stack, new BlockRayTraceResult(new Vec3d(ctx.player().getPositionVec().x, ctx.player().getPositionVec().y, ctx.player().getPositionVec().z), Direction.UP, ctx.playerFeet(), false)) {}))))) {
IBlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z, baritone.bsi.get0(x, y, z));
if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof ItemBlock && maybe.equals(((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(ctx.world(), ctx.playerFeet(), EnumFacing.UP, (float) ctx.player().posX, (float) ctx.player().posY, (float) ctx.player().posZ, stack.getItem().getMetadata(stack.getMetadata()), ctx.player())))) {
return true; // gotem
}
if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof BlockItem && ((BlockItem) stack.getItem()).getBlock().equals(maybe.getBlock()))) {
if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof ItemBlock && ((ItemBlock) stack.getItem()).getBlock().equals(maybe.getBlock()))) {
return true;
}
for (Item item : Baritone.settings().acceptableThrowawayItems.value) {
@@ -152,7 +149,7 @@ public final class InventoryBehavior extends Behavior {
}
public boolean throwaway(boolean select, Predicate<? super ItemStack> desired) {
ClientPlayerEntity p = ctx.player();
EntityPlayerSP p = ctx.player();
NonNullList<ItemStack> inv = p.inventory.mainInventory;
for (int i = 0; i < 9; i++) {
ItemStack item = inv.get(i);
@@ -176,7 +173,7 @@ public final class InventoryBehavior extends Behavior {
// so not a shovel, not a hoe, not a block, etc
for (int i = 0; i < 9; i++) {
ItemStack item = inv.get(i);
if (item.isEmpty() || item.getItem() instanceof PickaxeItem) {
if (item.isEmpty() || item.getItem() instanceof ItemPickaxe) {
if (select) {
p.inventory.currentItem = i;
}
@@ -28,6 +28,9 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
/**
* Target's values are as follows:
* <p>
* getFirst() -> yaw
* getSecond() -> pitch
*/
private Rotation target;
@@ -50,13 +53,6 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
@Override
public void updateTarget(Rotation target, boolean force) {
this.target = target;
if (!force) {
double rand = Math.random() - 0.5;
if (Math.abs(rand) < 0.1) {
rand *= 4;
}
this.target = new Rotation(this.target.getYaw() + (float) (rand * Baritone.settings().randomLooking113.value), this.target.getPitch());
}
this.force = force || !Baritone.settings().freeLook.value;
}
@@ -20,20 +20,33 @@ package baritone.behavior;
import baritone.Baritone;
import baritone.api.cache.Waypoint;
import baritone.api.event.events.BlockInteractEvent;
import baritone.api.event.events.PacketEvent;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.TickEvent;
import baritone.api.event.events.type.EventState;
import baritone.api.utils.BetterBlockPos;
import baritone.cache.ContainerMemory;
import baritone.utils.BlockStateInterface;
import net.minecraft.block.BedBlock;
import net.minecraft.block.Block;
import net.minecraft.block.BlockBed;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet;
import net.minecraft.network.play.client.CPacketClickWindow;
import net.minecraft.network.play.client.CPacketCloseWindow;
import net.minecraft.network.play.client.CPacketPlayerTryUseItemOnBlock;
import net.minecraft.network.play.server.SPacketCloseWindow;
import net.minecraft.network.play.server.SPacketOpenWindow;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityLockable;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentTranslation;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.*;
/**
* doesn't work for horse inventories :^)
@@ -43,13 +56,128 @@ import java.util.UUID;
*/
public final class MemoryBehavior extends Behavior {
private final List<FutureInventory> futureInventories = new ArrayList<>(); // this is per-bot
private Integer enderChestWindowId; // nae nae
public MemoryBehavior(Baritone baritone) {
super(baritone);
}
@Override
public synchronized void onTick(TickEvent event) {
if (!Baritone.settings().containerMemory.value) {
return;
}
if (event.getType() == TickEvent.Type.OUT) {
enderChestWindowId = null;
futureInventories.clear();
}
}
@Override
public synchronized void onPlayerUpdate(PlayerUpdateEvent event) {
if (event.getState() == EventState.PRE) {
updateInventory();
}
}
@Override
public synchronized void onSendPacket(PacketEvent event) {
if (!Baritone.settings().containerMemory.value) {
return;
}
Packet p = event.getPacket();
if (event.getState() == EventState.PRE) {
if (p instanceof CPacketPlayerTryUseItemOnBlock) {
CPacketPlayerTryUseItemOnBlock packet = event.cast();
TileEntity tileEntity = ctx.world().getTileEntity(packet.getPos());
// if tileEntity is an ender chest, we don't need to do anything. ender chests are treated the same regardless of what coordinate right clicked
// Ensure the TileEntity is a container of some sort
if (tileEntity instanceof TileEntityLockable) {
TileEntityLockable lockable = (TileEntityLockable) tileEntity;
int size = lockable.getSizeInventory();
BetterBlockPos position = BetterBlockPos.from(tileEntity.getPos());
BetterBlockPos adj = BetterBlockPos.from(neighboringConnectedBlock(position));
System.out.println(position + " " + adj);
if (adj != null) {
size *= 2; // double chest or double trapped chest
if (adj.getX() < position.getX() || adj.getZ() < position.getZ()) {
position = adj; // standardize on the lower coordinate, regardless of which side of the large chest we right clicked
}
}
this.futureInventories.add(new FutureInventory(System.nanoTime() / 1000000L, size, lockable.getGuiID(), position));
}
}
if (p instanceof CPacketCloseWindow) {
getCurrent().save();
}
if (p instanceof CPacketClickWindow) {
CPacketClickWindow c = event.cast();
System.out.println("CLICK " + c.getWindowId() + " " + c.getSlotId() + " " + c.getUsedButton() + " " + c.getClickType());
}
}
}
@Override
public synchronized void onReceivePacket(PacketEvent event) {
if (!Baritone.settings().containerMemory.value) {
return;
}
Packet p = event.getPacket();
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
futureInventories.removeIf(i -> System.nanoTime() / 1000000L - i.time > 1000);
System.out.println("Received packet " + packet.getGuiId() + " " + packet.getEntityId() + " " + packet.getSlotCount() + " " + packet.getWindowId());
System.out.println(packet.getWindowTitle());
if (packet.getWindowTitle() instanceof TextComponentTranslation && ((TextComponentTranslation) packet.getWindowTitle()).getKey().equals("container.enderchest")) {
// title is not customized (i.e. this isn't just a renamed shulker)
enderChestWindowId = packet.getWindowId();
return;
}
futureInventories.stream()
.filter(i -> i.type.equals(packet.getGuiId()) && i.slots == packet.getSlotCount())
.findFirst().ifPresent(matched -> {
// Remove the future inventory
futureInventories.remove(matched);
// Setup the remembered inventory
getCurrentContainer().setup(matched.pos, packet.getWindowId(), packet.getSlotCount());
});
}
if (p instanceof SPacketCloseWindow) {
getCurrent().save();
}
// apparently doesn't happen
/*if (p instanceof SPacketWindowItems) {
SPacketWindowItems meme = (SPacketWindowItems) p;
if (meme.getWindowId() == ctx.player().openContainer.windowId && enderChestWindowId != null && meme.getWindowId() == enderChestWindowId) {
System.out.println("RECEIVED GUARANTEED ECHEST CONTENTS" + meme.getItemStacks());
}
}*/
}
}
public boolean eChestOpen() {
return enderChestWindowId != null && ctx.player().openContainer.windowId == enderChestWindowId;
}
@Override
public void onBlockInteract(BlockInteractEvent event) {
if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(ctx, event.getPos()) instanceof BedBlock) {
if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(ctx, event.getPos()) instanceof BlockBed) {
baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, BetterBlockPos.from(event.getPos())));
}
}
@@ -59,6 +187,86 @@ public final class MemoryBehavior extends Behavior {
baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, ctx.playerFeet()));
}
private void updateInventory() {
if (!Baritone.settings().containerMemory.value) {
return;
}
int windowId = ctx.player().openContainer.windowId;
if (enderChestWindowId != null) {
if (windowId == enderChestWindowId) {
getCurrent().contents = ctx.player().openContainer.getInventory().subList(0, 27);
} else {
getCurrent().save();
enderChestWindowId = null;
}
}
if (getCurrentContainer() != null) {
getCurrentContainer().getInventoryFromWindow(windowId).ifPresent(inventory -> inventory.updateFromOpenWindow(ctx));
}
}
private ContainerMemory getCurrentContainer() {
if (baritone.getWorldProvider().getCurrentWorld() == null) {
return null;
}
return (ContainerMemory) baritone.getWorldProvider().getCurrentWorld().getContainerMemory();
}
private BlockPos neighboringConnectedBlock(BlockPos in) {
BlockStateInterface bsi = baritone.bsi;
Block block = bsi.get0(in).getBlock();
if (block != Blocks.TRAPPED_CHEST && block != Blocks.CHEST) {
return null; // other things that have contents, but can be placed adjacent without combining
}
for (int i = 0; i < 4; i++) {
BlockPos adj = in.offset(EnumFacing.byHorizontalIndex(i));
if (bsi.get0(adj).getBlock() == block) {
return adj;
}
}
return null;
}
/**
* An inventory that we are not yet fully aware of, but are expecting to exist at some point in the future.
*/
private static final class FutureInventory {
/**
* The time that we initially expected the inventory to be provided, in milliseconds
*/
private final long time;
/**
* The amount of slots in the inventory
*/
private final int slots;
/**
* The type of inventory
*/
private final String type;
/**
* The position of the inventory container
*/
private final BlockPos pos;
private FutureInventory(long time, int slots, String type, BlockPos pos) {
this.time = time;
this.slots = slots;
this.type = type;
this.pos = pos;
// betterblockpos has censoring
System.out.println("Future inventory created " + time + " " + slots + " " + type + " " + BetterBlockPos.from(pos));
}
}
public Optional<List<ItemStack>> echest() {
return Optional.ofNullable(getCurrent().contents).map(Collections::unmodifiableList);
}
public EnderChestMemory getCurrent() {
Path path = baritone.getWorldProvider().getCurrentWorld().directory;
return EnderChestMemory.getByServerAndPlayer(path.getParent(), ctx.player().getUniqueID());
@@ -381,8 +381,8 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
BetterBlockPos feet = ctx.playerFeet();
if (!MovementHelper.canWalkOn(ctx, feet.down())) {
if (ctx.player().onGround) {
double playerX = ctx.player().getPositionVec().x;
double playerZ = ctx.player().getPositionVec().z;
double playerX = ctx.player().posX;
double playerZ = ctx.player().posZ;
ArrayList<BetterBlockPos> closest = new ArrayList<>();
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
@@ -0,0 +1,110 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot;
import baritone.Baritone;
import baritone.api.IBaritone;
import baritone.api.bot.IBaritoneUser;
import baritone.api.bot.IUserManager;
import baritone.api.utils.IPlayerController;
import baritone.bot.spec.BotWorld;
import baritone.bot.spec.EntityBot;
import com.mojang.authlib.GameProfile;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.play.INetHandlerPlayClient;
import net.minecraft.util.Session;
/**
* Implementation of {@link IBaritoneUser}
*
* @author Brady
* @since 11/6/2018
*/
public class BaritoneUser implements IBaritoneUser {
private final UserManager manager;
private final NetworkManager networkManager;
private final Session session;
private GameProfile profile;
private INetHandlerPlayClient netHandlerPlayClient;
private BotWorld world;
private EntityBot player;
private IPlayerController playerController;
private final Baritone baritone;
BaritoneUser(UserManager manager, NetworkManager networkManager, Session session) {
this.manager = manager;
this.networkManager = networkManager;
this.session = session;
this.baritone = new Baritone(new BotPlayerContext(this));
}
public void onLoginSuccess(GameProfile profile, INetHandlerPlayClient netHandlerPlayClient) {
this.profile = profile;
this.netHandlerPlayClient = netHandlerPlayClient;
}
public void onWorldLoad(BotWorld world, EntityBot player, IPlayerController playerController) {
this.world = world;
this.player = player;
this.playerController = playerController;
}
@Override
public NetworkManager getNetworkManager() {
return this.networkManager;
}
@Override
public INetHandlerPlayClient getConnection() {
return this.netHandlerPlayClient;
}
@Override
public EntityBot getEntity() {
return this.player;
}
@Override
public IPlayerController getPlayerController() {
return this.playerController;
}
@Override
public Session getSession() {
return this.session;
}
@Override
public GameProfile getProfile() {
return this.profile;
}
@Override
public UserManager getManager() {
return this.manager;
}
@Override
public IBaritone getBaritone() {
return baritone;
}
}
@@ -0,0 +1,80 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot;
import baritone.api.bot.IBaritoneUser;
import baritone.api.cache.IWorldData;
import baritone.api.utils.IPlayerContext;
import baritone.api.utils.IPlayerController;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
public class BotPlayerContext implements IPlayerContext {
/**
* The backing {@link IBaritoneUser}
*/
private final IBaritoneUser bot;
public BotPlayerContext(IBaritoneUser bot) {
this.bot = bot;
}
@Override
public EntityPlayerSP player() {
if (bot.getEntity() == null) {
return null;
}
return bot.getEntity();
}
@Override
public IPlayerController playerController() {
if (bot.getEntity() == null) {
return null;
}
return bot.getPlayerController();
}
@Override
public World world() {
if (bot.getEntity() == null) {
return null;
}
return bot.getEntity().world;
}
@Override
public IWorldData worldData() {
return bot.getBaritone().getWorldProvider().getCurrentWorld();
}
@Override
public RayTraceResult objectMouseOver() {
Entity entity = this.bot.getEntity();
if (entity != null) {
double blockReachDistance = this.bot.getPlayerController().getBlockReachDistance();
return entity.rayTrace(blockReachDistance, 1.0F);
}
return null;
}
}
@@ -0,0 +1,66 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot;
import baritone.bot.spec.BotWorld;
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import net.minecraft.world.GameType;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldType;
/**
* @author Brady
* @since 11/7/2018
*/
public class BotWorldProvider {
/**
* Generic world settings for a typical survival world.
*/
private static final WorldSettings GENERIC_WORLD_SETTINGS = new WorldSettings(0L, GameType.SURVIVAL, true, false, WorldType.DEFAULT);
/**
* All of the dimensions mapped to their respective worlds.
*/
private final Int2ObjectMap<BotWorld> worlds = new Int2ObjectArrayMap<>();
/**
* Gets or creates the {@link BotWorld} for the specified dimension
*
* @param dimension The dimension id
* @return The world
*/
public BotWorld getWorld(int dimension) {
return worlds.computeIfAbsent(dimension, this::createWorldForDim);
}
/**
* Creates a new {@link BotWorld} for the given dimension id.
*
* @param dimension The dimension id
* @return The new world
*/
private BotWorld createWorldForDim(int dimension) {
return new BotWorld(GENERIC_WORLD_SETTINGS, dimension);
}
public void tick() {
this.worlds.forEach((dim, world) -> world.updateEntities());
}
}
+164
View File
@@ -0,0 +1,164 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot;
import baritone.api.BaritoneAPI;
import baritone.api.bot.IBaritoneUser;
import baritone.api.bot.IUserManager;
import baritone.api.bot.connect.IConnectionResult;
import baritone.api.event.events.TickEvent;
import baritone.api.event.events.type.EventState;
import baritone.api.event.listener.AbstractGameEventListener;
import baritone.api.utils.Helper;
import baritone.bot.connect.ConnectionResult;
import baritone.bot.handler.BotNetHandlerLoginClient;
import net.minecraft.client.multiplayer.ServerAddress;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.handshake.client.C00Handshake;
import net.minecraft.network.login.client.CPacketLoginStart;
import net.minecraft.util.Session;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import static baritone.api.bot.connect.ConnectionStatus.*;
/**
* @author Brady
* @since 11/6/2018
*/
public final class UserManager implements IUserManager, Helper {
public static final UserManager INSTANCE = new UserManager();
private final List<IBaritoneUser> users = new CopyOnWriteArrayList<>();
private final BotWorldProvider worldProvider;
private UserManager() {
// Setup an event listener that automatically disconnects bots when we're not in-game
BaritoneAPI.getProvider().getPrimaryBaritone().getGameEventHandler().registerEventListener(new AbstractGameEventListener() {
@Override
public final void onTick(TickEvent event) {
if (event.getState() == EventState.PRE) {
if (event.getType() == TickEvent.Type.OUT)
UserManager.this.users.forEach(UserManager.this::disconnect);
UserManager.this.worldProvider.tick();
}
}
});
this.worldProvider = new BotWorldProvider();
}
/**
* Connects a new user with the specified {@link Session} to the current server.
*
* @param session The user session
* @return The result of the attempted connection
*/
@Override
public final IConnectionResult connect(Session session) {
ServerData data = mc.getCurrentServerData();
if (data == null) {
return ConnectionResult.failed(NO_CURRENT_CONNECTION);
}
// Connect to the server from the parsed server data
return connect0(session, ServerAddress.fromString(data.serverIP));
}
/**
* Connects a new user with the specified {@link Session} to the specified server.
* <p>
* Hi Mickey :)
*
* @param session The user session
* @param address The address of the server to connect to
* @return The result of the attempted connection
*/
private IConnectionResult connect0(Session session, ServerAddress address) {
InetAddress inetAddress;
try {
inetAddress = InetAddress.getByName(address.getIP());
} catch (UnknownHostException e) {
return ConnectionResult.failed(CANT_RESOLVE_HOST);
}
try {
// Initialize Connection
NetworkManager networkManager = NetworkManager.createNetworkManagerAndConnect(
inetAddress,
address.getPort(),
mc.gameSettings.isUsingNativeTransport()
);
// Create User
BaritoneUser user = new BaritoneUser(this, networkManager, session);
this.users.add(user);
// Setup login handler and send connection packets
networkManager.setNetHandler(new BotNetHandlerLoginClient(networkManager, user));
networkManager.sendPacket(new C00Handshake(address.getIP(), address.getPort(), EnumConnectionState.LOGIN));
networkManager.sendPacket(new CPacketLoginStart(session.getProfile()));
return ConnectionResult.success(user);
} catch (Exception e) {
return ConnectionResult.failed(CONNECTION_FAILED);
}
}
/**
* Notifies the manager of an {@link IBaritoneUser} disconnect, and
* removes the {@link IBaritoneUser} from the list of users.
*
* @param user The user that disconnected
* @param state The connection state at the time of disconnect
*/
public final void notifyDisconnect(IBaritoneUser user, EnumConnectionState state) {
this.users.remove(user);
}
/**
* @return The bot world provider
*/
public final BotWorldProvider getWorldProvider() {
return this.worldProvider;
}
@Override
public final void disconnect(IBaritoneUser user) {
// It's probably fine to pass null to this, because the handlers aren't doing anything with it
// noinspection ConstantConditions
user.getNetworkManager().closeChannel(null);
this.users.remove(user);
}
@Override
public final List<IBaritoneUser> users() {
return Collections.unmodifiableList(this.users);
}
}
@@ -0,0 +1,87 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot.connect;
import baritone.api.bot.IBaritoneUser;
import baritone.api.bot.connect.ConnectionStatus;
import baritone.api.bot.connect.IConnectionResult;
import java.util.Objects;
import java.util.Optional;
import static baritone.api.bot.connect.ConnectionStatus.SUCCESS;
/**
* @author Brady
* @since 11/6/2018
*/
public final class ConnectionResult implements IConnectionResult {
/**
* The result status
*/
private final ConnectionStatus status;
/**
* The user created, if the status is {@link ConnectionStatus#SUCCESS}
*/
private final IBaritoneUser user;
private ConnectionResult(ConnectionStatus status, IBaritoneUser user) {
this.status = status;
this.user = user;
}
@Override
public ConnectionStatus getStatus() {
return this.status;
}
@Override
public Optional<IBaritoneUser> getUser() {
return Optional.ofNullable(user);
}
/**
* Creates a new failed {@link ConnectionResult}.
*
* @param status The failed connection status
* @return The connection result
* @throws IllegalArgumentException if {@code status} is {@link ConnectionStatus#SUCCESS}
*/
public static ConnectionResult failed(ConnectionStatus status) {
if (status == SUCCESS) {
throw new IllegalArgumentException("Status must be a failure type");
}
return new ConnectionResult(status, null);
}
/**
* Creates a new success {@link ConnectionResult}.
*
* @param user The user created
* @return The connection result
* @throws IllegalArgumentException if {@code user} is {@code null}
*/
public static ConnectionResult success(IBaritoneUser user) {
Objects.requireNonNull(user);
return new ConnectionResult(SUCCESS, user);
}
}
@@ -0,0 +1,118 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot.handler;
import baritone.bot.BaritoneUser;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.exceptions.AuthenticationUnavailableException;
import com.mojang.authlib.exceptions.InvalidCredentialsException;
import net.minecraft.client.Minecraft;
import net.minecraft.client.network.NetHandlerLoginClient;
import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.login.client.CPacketEncryptionResponse;
import net.minecraft.network.login.server.SPacketEncryptionRequest;
import net.minecraft.network.login.server.SPacketLoginSuccess;
import net.minecraft.util.CryptManager;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentTranslation;
import javax.annotation.Nonnull;
import javax.crypto.SecretKey;
import java.math.BigInteger;
import java.security.PublicKey;
/**
* Handles the login stage when connecting to a server.
*
* @author Brady
* @since 10/29/2018
*/
public class BotNetHandlerLoginClient extends NetHandlerLoginClient {
/**
* The {@link NetworkManager} that is managing the connection with the server.
*/
private final NetworkManager networkManager;
/**
* The {@link Minecraft} game instance
*/
private final Minecraft mc;
/**
* The bot of this connection
*/
private final BaritoneUser user;
public BotNetHandlerLoginClient(NetworkManager networkManager, BaritoneUser user) {
super(networkManager, Minecraft.getMinecraft(), null);
this.networkManager = networkManager;
this.mc = Minecraft.getMinecraft();
this.user = user;
}
@Override
public void handleEncryptionRequest(SPacketEncryptionRequest packetIn) {
SecretKey secretkey = CryptManager.createNewSharedKey();
PublicKey publicKey = packetIn.getPublicKey();
// Setup joinServer payload info
GameProfile profile = this.user.getSession().getProfile();
String authenticationToken = this.user.getSession().getToken();
String serverId = new BigInteger(CryptManager.getServerIdHash(packetIn.getServerId(), publicKey, secretkey)).toString(16);
if (this.mc.getCurrentServerData() != null && this.mc.getCurrentServerData().isOnLAN()) {
try {
this.mc.getSessionService().joinServer(profile, authenticationToken, serverId);
} catch (AuthenticationException e) {
// Couldn't connect to auth servers but will continue to join LAN
}
} else {
try {
this.mc.getSessionService().joinServer(profile, authenticationToken, serverId);
} catch (AuthenticationUnavailableException e) {
this.networkManager.closeChannel(new TextComponentTranslation("disconnect.loginFailedInfo", new TextComponentTranslation("disconnect.loginFailedInfo.serversUnavailable")));
return;
} catch (InvalidCredentialsException e) {
this.networkManager.closeChannel(new TextComponentTranslation("disconnect.loginFailedInfo", new TextComponentTranslation("disconnect.loginFailedInfo.invalidSession")));
return;
} catch (AuthenticationException e) {
this.networkManager.closeChannel(new TextComponentTranslation("disconnect.loginFailedInfo", e.getMessage()));
return;
}
}
// noinspection unchecked
this.networkManager.sendPacket(new CPacketEncryptionResponse(secretkey, publicKey, packetIn.getVerifyToken()),
future -> BotNetHandlerLoginClient.this.networkManager.enableEncryption(secretkey));
}
@Override
public void handleLoginSuccess(SPacketLoginSuccess packetIn) {
this.networkManager.setConnectionState(EnumConnectionState.PLAY);
this.networkManager.setNetHandler(new BotNetHandlerPlayClient(this.networkManager, this.user, Minecraft.getMinecraft(), packetIn.getProfile()));
}
@Override
public void onDisconnect(@Nonnull ITextComponent reason) {
// It's important that we don't call the superclass method because that would mess up GUIs and make us upset
this.user.getManager().notifyDisconnect(this.user, EnumConnectionState.LOGIN);
}
}
@@ -0,0 +1,706 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot.handler;
import baritone.api.utils.Helper;
import baritone.bot.BaritoneUser;
import baritone.bot.spec.BotPlayerController;
import baritone.bot.spec.BotWorld;
import baritone.bot.spec.EntityBot;
import com.mojang.authlib.GameProfile;
import io.netty.buffer.Unpooled;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.ClientAdvancementManager;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.client.util.RecipeBookClient;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.entity.player.PlayerCapabilities;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.network.EnumConnectionState;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.PacketBuffer;
import net.minecraft.network.PacketThreadUtil;
import net.minecraft.network.play.INetHandlerPlayClient;
import net.minecraft.network.play.client.*;
import net.minecraft.network.play.server.*;
import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.stats.StatisticsManager;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumHand;
import net.minecraft.util.EnumHandSide;
import net.minecraft.util.IThreadListener;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.world.Explosion;
import net.minecraft.world.chunk.Chunk;
import javax.annotation.Nonnull;
// Notes
// - Make some sort of system that prevents repetition of entity info updating
// - For some packets, such as ones that modify position, we can check if the existing server state matches the packet proposed state
// - For other things, we'll actually need the system
/**
* This class would effectively operate the same if we directly implemented {@link INetHandlerPlayClient},
* however, the {@link EntityPlayerSP} constructor requires an actual implementation of
* {@link NetHandlerPlayClient} in order to access the {@link GameProfile}.
*
* @author Brady
* @since 10/22/2018
*/
public class BotNetHandlerPlayClient extends NetHandlerPlayClient {
/**
* The {@link NetworkManager} that is managing the connection with the server.
*/
private final NetworkManager networkManager;
/**
* This is the {@link Minecraft} game instance, however, to prevent unwanted references
* to the game instance fields, we refer to it as a {@link IThreadListener}.
*/
private final IThreadListener client;
/**
* The bot of this connection
*/
private final BaritoneUser user;
/**
* The bot entity
*/
private EntityBot player;
/**
* The current world.
*/
private BotWorld world;
/**
* The current player controller
*/
private BotPlayerController playerController;
public BotNetHandlerPlayClient(NetworkManager networkManager, BaritoneUser user, Minecraft client, GameProfile profile) {
// noinspection ConstantConditions
super(client, null, networkManager, profile);
this.networkManager = networkManager;
this.client = client;
this.user = user;
// Notify the user that we're ingame
this.user.onLoginSuccess(profile, this);
}
@Override
public void handleSpawnObject(@Nonnull SPacketSpawnObject packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleSpawnExperienceOrb(@Nonnull SPacketSpawnExperienceOrb packetIn) { /* We will want to know this if we want Tenor to collect XP */ }
@Override
public void handleSpawnGlobalEntity(@Nonnull SPacketSpawnGlobalEntity packetIn) { /* Only lightning bolts, this may change in the future */ }
@Override
public void handleSpawnMob(@Nonnull SPacketSpawnMob packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleScoreboardObjective(@Nonnull SPacketScoreboardObjective packetIn) {}
@Override
public void handleSpawnPainting(@Nonnull SPacketSpawnPainting packetIn) {}
@Override
public void handleSpawnPlayer(@Nonnull SPacketSpawnPlayer packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleAnimation(@Nonnull SPacketAnimation packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = this.world.getEntityByID(packetIn.getEntityID());
if (entity != null) {
switch (packetIn.getAnimationType()) {
case 0: {
((EntityLivingBase) entity).swingArm(EnumHand.MAIN_HAND);
break;
}
case 1: {
entity.performHurtAnimation();
break;
}
case 2: {
((EntityPlayer) entity).wakeUpPlayer(false, false, false);
break;
}
case 3: {
((EntityLivingBase) entity).swingArm(EnumHand.OFF_HAND);
break;
}
}
}
}
@Override
public void handleStatistics(@Nonnull SPacketStatistics packetIn) { /* Lol global bot stats when?? */ }
@Override
public void handleRecipeBook(@Nonnull SPacketRecipeBook packetIn) {}
@Override
public void handleBlockBreakAnim(@Nonnull SPacketBlockBreakAnim packetIn) {}
@Override
public void handleSignEditorOpen(@Nonnull SPacketSignEditorOpen packetIn) {}
@Override
public void handleUpdateTileEntity(@Nonnull SPacketUpdateTileEntity packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleBlockAction(@Nonnull SPacketBlockAction packetIn) {}
@Override
public void handleBlockChange(@Nonnull SPacketBlockChange packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.world.setBlockState(packetIn.getBlockPosition(), packetIn.getBlockState());
}
@Override
public void handleChat(@Nonnull SPacketChat packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleTabComplete(@Nonnull SPacketTabComplete packetIn) {}
@Override
public void handleMultiBlockChange(@Nonnull SPacketMultiBlockChange packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
for (SPacketMultiBlockChange.BlockUpdateData data : packetIn.getChangedBlocks()) {
this.world.setBlockState(data.getPos(), data.getBlockState());
}
}
@Override
public void handleMaps(@Nonnull SPacketMaps packetIn) {}
@Override
public void handleConfirmTransaction(@Nonnull SPacketConfirmTransaction packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleCloseWindow(@Nonnull SPacketCloseWindow packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.player.closeScreenAndDropStack();
}
@Override
public void handleWindowItems(@Nonnull SPacketWindowItems packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
(packetIn.getWindowId() == 0 ? this.player.inventoryContainer : this.player.openContainer).setAll(packetIn.getItemStacks());
}
@Override
public void handleOpenWindow(@Nonnull SPacketOpenWindow packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleWindowProperty(@Nonnull SPacketWindowProperty packetIn) {}
@Override
public void handleSetSlot(@Nonnull SPacketSetSlot packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
ItemStack stack = packetIn.getStack();
int slot = packetIn.getSlot();
switch (packetIn.getWindowId()) {
case -1: {
this.player.inventory.setItemStack(stack);
break;
}
case -2: {
this.player.inventory.setInventorySlotContents(slot, stack);
break;
}
default: {
if (packetIn.getWindowId() == 0 && packetIn.getSlot() >= 36 && slot < 45) {
this.player.inventoryContainer.putStackInSlot(slot, stack);
} else if (packetIn.getWindowId() == this.player.openContainer.windowId && packetIn.getWindowId() != 0) {
this.player.openContainer.putStackInSlot(slot, stack);
}
}
}
}
@Override
public void handleCustomPayload(@Nonnull SPacketCustomPayload packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleDisconnect(@Nonnull SPacketDisconnect packetIn) {
this.networkManager.closeChannel(packetIn.getReason());
}
@Override
public void handleUseBed(@Nonnull SPacketUseBed packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityStatus(@Nonnull SPacketEntityStatus packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityAttach(@Nonnull SPacketEntityAttach packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleSetPassengers(@Nonnull SPacketSetPassengers packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleExplosion(@Nonnull SPacketExplosion packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
// noinspection ConstantConditions
new Explosion(this.world, null, packetIn.getX(), packetIn.getY(), packetIn.getZ(), packetIn.getStrength(), packetIn.getAffectedBlockPositions()).doExplosionB(true);
this.player.motionX += (double) packetIn.getMotionX();
this.player.motionY += (double) packetIn.getMotionY();
this.player.motionZ += (double) packetIn.getMotionZ();
}
@Override
public void handleChangeGameState(@Nonnull SPacketChangeGameState packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleKeepAlive(@Nonnull SPacketKeepAlive packetIn) {
this.networkManager.sendPacket(new CPacketKeepAlive(packetIn.getId()));
}
@Override
public void handleChunkData(@Nonnull SPacketChunkData packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (packetIn.isFullChunk()) {
this.world.doPreChunk(packetIn.getChunkX(), packetIn.getChunkZ(), true);
}
Chunk chunk = this.world.getChunk(packetIn.getChunkX(), packetIn.getChunkZ());
chunk.read(packetIn.getReadBuffer(), packetIn.getExtractedSize(), packetIn.isFullChunk());
for (NBTTagCompound tag : packetIn.getTileEntityTags()) {
BlockPos pos = new BlockPos(tag.getInteger("x"), tag.getInteger("y"), tag.getInteger("z"));
TileEntity tileEntity = this.world.getTileEntity(pos);
if (tileEntity != null) {
tileEntity.readFromNBT(tag);
}
}
}
@Override
public void processChunkUnload(@Nonnull SPacketUnloadChunk packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
// TODO Unload chunks
}
@Override
public void handleEffect(@Nonnull SPacketEffect packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleJoinGame(@Nonnull SPacketJoinGame packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.playerController = new BotPlayerController(this.user);
this.world = this.user.getManager().getWorldProvider().getWorld(packetIn.getDimension());
this.player = new EntityBot(this.user, (Minecraft) this.client, this.world, this, new StatisticsManager(), new RecipeBookClient());
this.user.onWorldLoad(this.world, this.player, this.playerController);
this.player.preparePlayerToSpawn();
this.world.spawnEntity(this.player);
this.player.setEntityId(packetIn.getPlayerId());
this.player.dimension = packetIn.getDimension();
this.playerController.setGameType(packetIn.getGameType());
packetIn.getGameType().configurePlayerCapabilities(this.player.capabilities);
this.networkManager.sendPacket(new CPacketClientSettings("en_us", 8, EntityPlayer.EnumChatVisibility.FULL, true, 0, EnumHandSide.RIGHT));
this.networkManager.sendPacket(new CPacketCustomPayload("MC|Brand", new PacketBuffer(Unpooled.buffer()).writeString("vanilla")));
this.world.registerBot(packetIn.getPlayerId(), this.player);
Helper.HELPER.logDirect("Initialized Player and World");
}
@Override
public void handleEntityMovement(@Nonnull SPacketEntity packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handlePlayerPosLook(@Nonnull SPacketPlayerPosLook packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
EntityPlayer player = this.player;
double d0 = packetIn.getX();
double d1 = packetIn.getY();
double d2 = packetIn.getZ();
float f = packetIn.getYaw();
float f1 = packetIn.getPitch();
if (packetIn.getFlags().contains(SPacketPlayerPosLook.EnumFlags.X)) {
d0 += player.posX;
} else {
player.motionX = 0.0D;
}
if (packetIn.getFlags().contains(SPacketPlayerPosLook.EnumFlags.Y)) {
d1 += player.posY;
} else {
player.motionY = 0.0D;
}
if (packetIn.getFlags().contains(SPacketPlayerPosLook.EnumFlags.Z)) {
d2 += player.posZ;
} else {
player.motionZ = 0.0D;
}
if (packetIn.getFlags().contains(SPacketPlayerPosLook.EnumFlags.X_ROT)) {
f1 += player.rotationPitch;
}
if (packetIn.getFlags().contains(SPacketPlayerPosLook.EnumFlags.Y_ROT)) {
f += player.rotationYaw;
}
player.setPositionAndRotation(d0, d1, d2, f, f1);
this.networkManager.sendPacket(new CPacketConfirmTeleport(packetIn.getTeleportId()));
this.networkManager.sendPacket(new CPacketPlayer.PositionRotation(player.posX, player.getEntityBoundingBox().minY, player.posZ, player.rotationYaw, player.rotationPitch, false));
this.player.prevPosX = this.player.posX;
this.player.prevPosY = this.player.posY;
this.player.prevPosZ = this.player.posZ;
}
@Override
public void handleParticles(@Nonnull SPacketParticles packetIn) {}
@Override
public void handlePlayerAbilities(@Nonnull SPacketPlayerAbilities packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
PlayerCapabilities c = this.player.capabilities;
c.disableDamage = packetIn.isInvulnerable();
c.isFlying = packetIn.isFlying();
c.allowFlying = packetIn.isAllowFlying();
c.isCreativeMode = packetIn.isCreativeMode();
c.setFlySpeed(packetIn.getFlySpeed());
c.setPlayerWalkSpeed(packetIn.getWalkSpeed());
}
@Override
public void handlePlayerListItem(@Nonnull SPacketPlayerListItem packetIn) {
// okay now this is awesome
super.handlePlayerListItem(packetIn);
}
@Override
public void handleDestroyEntities(@Nonnull SPacketDestroyEntities packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
for (int i = 0; i < packetIn.getEntityIDs().length; ++i) {
this.world.removeEntityFromWorld(packetIn.getEntityIDs()[i]);
}
}
@Override
public void handleRemoveEntityEffect(@Nonnull SPacketRemoveEntityEffect packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = packetIn.getEntity(this.world);
if (entity instanceof EntityLivingBase) {
((EntityLivingBase) entity).removeActivePotionEffect(packetIn.getPotion());
}
}
@Override
public void handleRespawn(@Nonnull SPacketRespawn packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (packetIn.getDimensionID() != this.player.dimension) {
this.world.removeEntity(this.player);
this.world = this.user.getManager().getWorldProvider().getWorld(packetIn.getDimensionID());
}
EntityBot prev = this.player;
this.player = new EntityBot(this.user, (Minecraft) this.client, this.world, this, prev.getStatFileWriter(), prev.getRecipeBook());
this.user.onWorldLoad(this.world, this.player, this.playerController);
// noinspection ConstantConditions
this.player.getDataManager().setEntryValues(prev.getDataManager().getAll());
this.player.preparePlayerToSpawn();
this.world.spawnEntity(this.player);
this.player.setEntityId(prev.getEntityId());
this.player.dimension = packetIn.getDimensionID();
this.player.setServerBrand(prev.getServerBrand());
this.playerController.setGameType(packetIn.getGameType());
}
@Override
public void handleEntityHeadLook(@Nonnull SPacketEntityHeadLook packetIn) {}
@Override
public void handleHeldItemChange(@Nonnull SPacketHeldItemChange packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (InventoryPlayer.isHotbar(packetIn.getHeldItemHotbarIndex())) {
this.player.inventory.currentItem = packetIn.getHeldItemHotbarIndex();
}
}
@Override
public void handleDisplayObjective(@Nonnull SPacketDisplayObjective packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityMetadata(@Nonnull SPacketEntityMetadata packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = this.world.getEntityByID(packetIn.getEntityId());
if (entity != null && packetIn.getDataManagerEntries() != null) {
entity.getDataManager().setEntryValues(packetIn.getDataManagerEntries());
}
}
@Override
public void handleEntityVelocity(@Nonnull SPacketEntityVelocity packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = this.world.getEntityByID(packetIn.getEntityID());
if (entity != null) {
entity.setVelocity(
(double) packetIn.getMotionX() / 8000.0D,
(double) packetIn.getMotionY() / 8000.0D,
(double) packetIn.getMotionZ() / 8000.0D
);
}
}
@Override
public void handleEntityEquipment(@Nonnull SPacketEntityEquipment packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = this.world.getEntityByID(packetIn.getEntityID());
if (entity != null) {
entity.setItemStackToSlot(packetIn.getEquipmentSlot(), packetIn.getItemStack());
}
}
@Override
public void handleSetExperience(@Nonnull SPacketSetExperience packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.player.setXPStats(packetIn.getExperienceBar(), packetIn.getTotalExperience(), packetIn.getLevel());
}
@Override
public void handleUpdateHealth(@Nonnull SPacketUpdateHealth packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.player.setPlayerSPHealth(packetIn.getHealth());
this.player.getFoodStats().setFoodLevel(packetIn.getFoodLevel());
this.player.getFoodStats().setFoodSaturationLevel(packetIn.getSaturationLevel());
}
@Override
public void handleTeams(@Nonnull SPacketTeams packetIn) {}
@Override
public void handleUpdateScore(@Nonnull SPacketUpdateScore packetIn) {}
@Override
public void handleSpawnPosition(@Nonnull SPacketSpawnPosition packetIn) { /* We probably don't need to know this, the server handles everything related to spawn psoition? */ }
@Override
public void handleTimeUpdate(@Nonnull SPacketTimeUpdate packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
this.world.setTotalWorldTime(packetIn.getTotalWorldTime());
this.world.setWorldTime(packetIn.getWorldTime());
// TODO: Calculate World TPS
}
@Override
public void handleSoundEffect(@Nonnull SPacketSoundEffect packetIn) {}
@Override
public void handleCustomSound(@Nonnull SPacketCustomSound packetIn) {}
@Override
public void handleCollectItem(@Nonnull SPacketCollectItem packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityTeleport(@Nonnull SPacketEntityTeleport packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityProperties(@Nonnull SPacketEntityProperties packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
}
@Override
public void handleEntityEffect(@Nonnull SPacketEntityEffect packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
Entity entity = this.world.getEntityByID(packetIn.getEntityId());
if (entity instanceof EntityLivingBase) {
Potion potion = Potion.getPotionById(packetIn.getEffectId());
if (potion != null) {
PotionEffect effect = new PotionEffect(potion, packetIn.getDuration(), packetIn.getAmplifier(), packetIn.getIsAmbient(), packetIn.doesShowParticles());
effect.setPotionDurationMax(packetIn.isMaxDuration());
((EntityLivingBase) entity).addPotionEffect(effect);
}
}
}
@Override
public void handleCombatEvent(@Nonnull SPacketCombatEvent packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
// We only care if we died
if (packetIn.eventType == SPacketCombatEvent.Event.ENTITY_DIED) {
if (packetIn.playerId == this.player.getEntityId()) {
// Perform an instantaneous respawn
this.networkManager.sendPacket(new CPacketClientStatus(CPacketClientStatus.State.PERFORM_RESPAWN));
}
}
}
@Override
public void handleServerDifficulty(@Nonnull SPacketServerDifficulty packetIn) {}
@Override
public void handleCamera(SPacketCamera packetIn) {}
@Override
public void handleWorldBorder(@Nonnull SPacketWorldBorder packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
packetIn.apply(this.world.getWorldBorder());
}
@Override
public void handleTitle(@Nonnull SPacketTitle packetIn) {}
@Override
public void handlePlayerListHeaderFooter(@Nonnull SPacketPlayerListHeaderFooter packetIn) {}
@Override
public void handleResourcePack(@Nonnull SPacketResourcePackSend packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
// Lie to the server and tell them we accepted it in response
this.networkManager.sendPacket(new CPacketResourcePackStatus(CPacketResourcePackStatus.Action.ACCEPTED));
this.networkManager.sendPacket(new CPacketResourcePackStatus(CPacketResourcePackStatus.Action.SUCCESSFULLY_LOADED));
}
@Override
public void handleUpdateBossInfo(@Nonnull SPacketUpdateBossInfo packetIn) {}
@Override
public void handleCooldown(@Nonnull SPacketCooldown packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
if (packetIn.getTicks() == 0) { // There is no cooldown
this.player.getCooldownTracker().removeCooldown(packetIn.getItem());
} else {
this.player.getCooldownTracker().setCooldown(packetIn.getItem(), packetIn.getTicks());
}
}
@Override
public void handleMoveVehicle(@Nonnull SPacketMoveVehicle packetIn) {
PacketThreadUtil.checkThreadAndEnqueue(packetIn, this, this.client);
/* Atm Baritone doesn't even work on vehicles that well at all, so this is a major TODO */
}
@Override
public void handleAdvancementInfo(@Nonnull SPacketAdvancementInfo packetIn) {}
@Override
public void handleSelectAdvancementsTab(@Nonnull SPacketSelectAdvancementsTab packetIn) { /* Lol global bot achievements when? */ }
@Override
public void func_194307_a(@Nonnull SPacketPlaceGhostRecipe p_194307_1_) {}
@Override
public void onDisconnect(@Nonnull ITextComponent reason) {
// TODO Maybe more world unloadinde
this.world.removeEntity(this.player);
this.user.getManager().notifyDisconnect(this.user, EnumConnectionState.PLAY);
}
@Nonnull
@Override
public ClientAdvancementManager getAdvancementManager() {
throw new UnsupportedOperationException("This method shouldn't have been called; That is unepic!");
}
public EntityBot player() {
return player;
}
public BotWorld world() {
return world;
}
}
@@ -0,0 +1,260 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.bot.spec;
import baritone.api.bot.IBaritoneUser;
import baritone.api.utils.IPlayerController;
import net.minecraft.block.Block;
import net.minecraft.block.BlockCommandBlock;
import net.minecraft.block.BlockStructure;
import net.minecraft.block.material.Material;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.ItemStack;
import net.minecraft.network.play.client.CPacketClickWindow;
import net.minecraft.network.play.client.CPacketHeldItemChange;
import net.minecraft.network.play.client.CPacketPlayerDigging;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameType;
import net.minecraft.world.World;
/**
* @author Brady
* @since 11/14/2018
*/
public class BotPlayerController implements IPlayerController {
private final IBaritoneUser user;
private GameType gameType;
private BlockPos currentBlock;
private ItemStack currentHittingItem;
private boolean hittingBlock;
private float blockDamage;
private int blockHitDelay;
private int heldItemServer;
public BotPlayerController(IBaritoneUser user) {
this.user = user;
this.currentHittingItem = ItemStack.EMPTY;
}
@Override
public boolean onPlayerDamageBlock(BlockPos pos, EnumFacing side) {
this.syncHeldItem();
EntityPlayerSP player = this.user.getEntity();
World world = player.world;
if (this.blockHitDelay > 0) {
this.blockHitDelay--;
return true;
}
if (!this.isHittingPosition(pos)) {
return this.clickBlock(pos, side);
}
IBlockState state = world.getBlockState(pos);
if (state.getMaterial() == Material.AIR) {
this.hittingBlock = false;
return false;
}
this.blockDamage += state.getPlayerRelativeBlockHardness(player, world, pos);
if (this.blockDamage >= 1.0F) {
this.hittingBlock = false;
this.blockDamage = 0.0F;
this.blockHitDelay = 5;
player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.STOP_DESTROY_BLOCK, pos, side));
this.handleBreak(pos);
}
world.sendBlockBreakProgress(player.getEntityId(), this.currentBlock, (int) (this.blockDamage * 10.0F) - 1);
return true;
}
@Override
public void resetBlockRemoving() {
if (this.hittingBlock) {
this.hittingBlock = false;
this.blockDamage = 0.0F;
this.user.getEntity().resetCooldown();
this.user.getEntity().connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.ABORT_DESTROY_BLOCK, this.currentBlock, EnumFacing.DOWN));
}
}
@Override
public ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player) {
short transactionID = player.openContainer.getNextTransactionID(player.inventory);
ItemStack stack = player.openContainer.slotClick(slotId, mouseButton, type, player);
this.user.getEntity().connection.sendPacket(new CPacketClickWindow(windowId, slotId, mouseButton, type, stack, transactionID));
return stack;
}
@Override
public void setGameType(GameType type) {
this.gameType = type;
this.gameType.configurePlayerCapabilities(this.user.getEntity().capabilities);
}
@Override
public GameType getGameType() {
return this.gameType;
}
@Override
public boolean clickBlock(BlockPos pos, EnumFacing side) {
EntityPlayerSP player = this.user.getEntity();
World world = player.world;
if (!canBreak(player, pos)) {
return false;
}
if (!this.hittingBlock || !this.isHittingPosition(pos)) {
if (this.hittingBlock) {
player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.ABORT_DESTROY_BLOCK, this.currentBlock, side));
}
IBlockState state = world.getBlockState(pos);
player.connection.sendPacket(new CPacketPlayerDigging(CPacketPlayerDigging.Action.START_DESTROY_BLOCK, pos, side));
if (state.getMaterial() != Material.AIR) {
if (this.blockDamage == 0.0F) {
state.getBlock().onBlockClicked(world, pos, player);
}
if (state.getPlayerRelativeBlockHardness(player, player.world, pos) >= 1.0F) {
this.handleBreak(pos);
}
} else {
this.hittingBlock = true;
this.currentBlock = pos;
this.blockDamage = 0.0F;
this.currentHittingItem = player.getHeldItemMainhand();
world.sendBlockBreakProgress(player.getEntityId(), this.currentBlock, (int) (this.blockDamage * 10.0F) - 1);
}
}
return true;
}
private void handleBreak(BlockPos pos) {
EntityPlayerSP player = this.user.getEntity();
World world = player.world;
IBlockState state = world.getBlockState(pos);
Block block = state.getBlock();
if ((block instanceof BlockCommandBlock || block instanceof BlockStructure) && !player.canUseCommandBlock()) {
return;
}
if (state.getMaterial() == Material.AIR) {
return;
}
block.onBlockHarvested(world, pos, state, player);
if (world.setBlockState(pos, Blocks.AIR.getDefaultState(), 11)) {
block.onPlayerDestroy(world, pos, state);
}
this.currentBlock = new BlockPos(this.currentBlock.getX(), -1, this.currentBlock.getZ());
ItemStack stack = player.getHeldItemMainhand();
if (!stack.isEmpty()) {
stack.onBlockDestroyed(world, state, pos, player);
if (stack.isEmpty()) {
player.setHeldItem(EnumHand.MAIN_HAND, ItemStack.EMPTY);
}
}
}
private boolean canBreak(EntityPlayer player, BlockPos pos) {
if (this.gameType.isCreative() || this.gameType == GameType.SPECTATOR) {
return false;
}
if (!player.world.getWorldBorder().contains(pos)) {
return false;
}
if (this.gameType.hasLimitedInteractions() && !player.isAllowEdit()) {
ItemStack stack = player.getHeldItemMainhand();
return !stack.isEmpty() && stack.canDestroy(player.world.getBlockState(pos).getBlock());
}
return true;
}
private boolean isHittingPosition(BlockPos pos) {
ItemStack stack = this.user.getEntity().getHeldItemMainhand();
boolean itemUnchanged = this.currentHittingItem.isEmpty() && stack.isEmpty();
if (!this.currentHittingItem.isEmpty() && !stack.isEmpty()) {
itemUnchanged = stack.getItem() == this.currentHittingItem.getItem()
&& ItemStack.areItemStackTagsEqual(stack, this.currentHittingItem)
&& (stack.isItemStackDamageable() || stack.getMetadata() == this.currentHittingItem.getMetadata());
}
return pos.equals(this.currentBlock) && itemUnchanged;
}
@Override
public void syncHeldItem() {
int heldItemClient = this.user.getEntity().inventory.currentItem;
if (heldItemClient != this.heldItemServer) {
this.heldItemServer = heldItemClient;
this.user.getEntity().connection.sendPacket(new CPacketHeldItemChange(this.heldItemServer));
}
}
@Override
public boolean hasBrokenBlock() {
return this.currentBlock.getY() == -1;
}
@Override
public EnumActionResult processRightClickBlock(EntityPlayerSP player, World world, BlockPos pos, EnumFacing direction, Vec3d vec, EnumHand hand) {
throw new AbstractMethodError("Lol");
}
@Override
public EnumActionResult processRightClick(EntityPlayerSP player, World world, EnumHand hand) {
throw new AbstractMethodError("Lol");
}
@Override
public void setHittingBlock(boolean hittingBlock) {
this.hittingBlock = hittingBlock;
}
}

Some files were not shown because too many files have changed in this diff Show More