Merge branch 'master' into movement-duplicate-switch
This commit is contained in:
142
src/main/java/baritone/launch/BaritoneTweaker.java → src/launch/java/baritone/launch/BaritoneTweaker.java
Executable file → Normal file
142
src/main/java/baritone/launch/BaritoneTweaker.java → src/launch/java/baritone/launch/BaritoneTweaker.java
Executable file → Normal file
@@ -1,71 +1,71 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import net.minecraft.launchwrapper.ITweaker;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.spongepowered.asm.launch.MixinBootstrap;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.asm.mixin.Mixins;
|
||||
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 9:59 PM
|
||||
*/
|
||||
public class BaritoneTweaker implements ITweaker {
|
||||
|
||||
List<String> args;
|
||||
|
||||
@Override
|
||||
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>(args);
|
||||
if (gameDir != null) addArg("gameDir", gameDir.getAbsolutePath());
|
||||
if (assetsDir != null) addArg("assetsDir", assetsDir.getAbsolutePath());
|
||||
if (profile != null) addArg("version", profile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
|
||||
MixinBootstrap.init();
|
||||
MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT);
|
||||
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.NOTCH);
|
||||
Mixins.addConfiguration("mixins.baritone.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getLaunchTarget() {
|
||||
return "net.minecraft.client.main.Main";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String[] getLaunchArguments() {
|
||||
return this.args.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private void addArg(String label, String value) {
|
||||
if (!args.contains("--" + label) && value != null) {
|
||||
this.args.add("--" + label);
|
||||
this.args.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import net.minecraft.launchwrapper.ITweaker;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.spongepowered.asm.launch.MixinBootstrap;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.asm.mixin.Mixins;
|
||||
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 9:59 PM
|
||||
*/
|
||||
public class BaritoneTweaker implements ITweaker {
|
||||
|
||||
List<String> args;
|
||||
|
||||
@Override
|
||||
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>(args);
|
||||
if (gameDir != null) addArg("gameDir", gameDir.getAbsolutePath());
|
||||
if (assetsDir != null) addArg("assetsDir", assetsDir.getAbsolutePath());
|
||||
if (profile != null) addArg("version", profile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
|
||||
MixinBootstrap.init();
|
||||
MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT);
|
||||
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.NOTCH);
|
||||
Mixins.addConfiguration("mixins.baritone.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getLaunchTarget() {
|
||||
return "net.minecraft.client.main.Main";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String[] getLaunchArguments() {
|
||||
return this.args.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private void addArg(String label, String value) {
|
||||
if (!args.contains("--" + label) && value != null) {
|
||||
this.args.add("--" + label);
|
||||
this.args.add(value);
|
||||
}
|
||||
}
|
||||
}
|
88
src/main/java/baritone/launch/BaritoneTweakerForge.java → src/launch/java/baritone/launch/BaritoneTweakerForge.java
Executable file → Normal file
88
src/main/java/baritone/launch/BaritoneTweakerForge.java → src/launch/java/baritone/launch/BaritoneTweakerForge.java
Executable file → Normal file
@@ -1,44 +1,44 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:09 PM
|
||||
*/
|
||||
public class BaritoneTweakerForge extends BaritoneTweaker {
|
||||
|
||||
@Override
|
||||
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void injectIntoClassLoader(LaunchClassLoader classLoader) {
|
||||
super.injectIntoClassLoader(classLoader);
|
||||
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.SEARGE);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:09 PM
|
||||
*/
|
||||
public class BaritoneTweakerForge extends BaritoneTweaker {
|
||||
|
||||
@Override
|
||||
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void injectIntoClassLoader(LaunchClassLoader classLoader) {
|
||||
super.injectIntoClassLoader(classLoader);
|
||||
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.SEARGE);
|
||||
}
|
||||
}
|
68
src/main/java/baritone/launch/BaritoneTweakerOptifine.java → src/launch/java/baritone/launch/BaritoneTweakerOptifine.java
Executable file → Normal file
68
src/main/java/baritone/launch/BaritoneTweakerOptifine.java → src/launch/java/baritone/launch/BaritoneTweakerOptifine.java
Executable file → Normal file
@@ -1,34 +1,34 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:10 PM
|
||||
*/
|
||||
public class BaritoneTweakerOptifine extends BaritoneTweaker {
|
||||
|
||||
@Override
|
||||
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:10 PM
|
||||
*/
|
||||
public class BaritoneTweakerOptifine extends BaritoneTweaker {
|
||||
|
||||
@Override
|
||||
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>();
|
||||
}
|
||||
}
|
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.utils.accessor.IAnvilChunkLoader;
|
||||
import net.minecraft.world.chunk.storage.AnvilChunkLoader;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/4/2018
|
||||
*/
|
||||
@Mixin(AnvilChunkLoader.class)
|
||||
public class MixinAnvilChunkLoader implements IAnvilChunkLoader {
|
||||
|
||||
@Shadow @Final private File chunkSaveLocation;
|
||||
|
||||
@Override
|
||||
public File getChunkSaveLocation() {
|
||||
return this.chunkSaveLocation;
|
||||
}
|
||||
}
|
@@ -29,7 +29,7 @@ import javax.annotation.Nonnull;
|
||||
* @since 8/25/2018
|
||||
*/
|
||||
@Mixin(BlockPos.class)
|
||||
public abstract class MixinBlockPos extends Vec3i {
|
||||
public class MixinBlockPos extends Vec3i {
|
||||
|
||||
public MixinBlockPos(int xIn, int yIn, int zIn) {
|
||||
super(xIn, yIn, zIn);
|
@@ -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 General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <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;
|
||||
}
|
||||
}
|
@@ -18,8 +18,8 @@
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.RelativeMoveEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.RelativeMoveEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
@@ -18,9 +18,9 @@
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.ChatEvent;
|
||||
import baritone.event.events.PlayerUpdateEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.ChatEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
@@ -18,7 +18,7 @@
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.RenderEvent;
|
||||
import baritone.api.event.events.RenderEvent;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
88
src/main/java/baritone/launch/mixins/MixinGameSettings.java → src/launch/java/baritone/launch/mixins/MixinGameSettings.java
Executable file → Normal file
88
src/main/java/baritone/launch/mixins/MixinGameSettings.java → src/launch/java/baritone/launch/mixins/MixinGameSettings.java
Executable file → Normal file
@@ -1,44 +1,44 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/1/2018 12:28 AM
|
||||
*/
|
||||
@Mixin(GameSettings.class)
|
||||
public class MixinGameSettings {
|
||||
|
||||
@Redirect(
|
||||
method = "isKeyDown",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private static boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/1/2018 12:28 AM
|
||||
*/
|
||||
@Mixin(GameSettings.class)
|
||||
public class MixinGameSettings {
|
||||
|
||||
@Redirect(
|
||||
method = "isKeyDown",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private static boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
94
src/main/java/baritone/launch/mixins/MixinGuiContainer.java → src/launch/java/baritone/launch/mixins/MixinGuiContainer.java
Executable file → Normal file
94
src/main/java/baritone/launch/mixins/MixinGuiContainer.java → src/launch/java/baritone/launch/mixins/MixinGuiContainer.java
Executable file → Normal file
@@ -1,47 +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 General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:47 PM
|
||||
*/
|
||||
@Mixin(GuiContainer.class)
|
||||
public class MixinGuiContainer {
|
||||
|
||||
@Redirect(
|
||||
method = {
|
||||
"mouseClicked",
|
||||
"mouseReleased"
|
||||
},
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:47 PM
|
||||
*/
|
||||
@Mixin(GuiContainer.class)
|
||||
public class MixinGuiContainer {
|
||||
|
||||
@Redirect(
|
||||
method = {
|
||||
"mouseClicked",
|
||||
"mouseReleased"
|
||||
},
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
96
src/main/java/baritone/launch/mixins/MixinGuiScreen.java → src/launch/java/baritone/launch/mixins/MixinGuiScreen.java
Executable file → Normal file
96
src/main/java/baritone/launch/mixins/MixinGuiScreen.java → src/launch/java/baritone/launch/mixins/MixinGuiScreen.java
Executable file → Normal file
@@ -1,48 +1,48 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:38 PM
|
||||
*/
|
||||
@Mixin(GuiScreen.class)
|
||||
public class MixinGuiScreen {
|
||||
|
||||
@Redirect(
|
||||
method = {
|
||||
"isCtrlKeyDown",
|
||||
"isShiftKeyDown",
|
||||
"isAltKeyDown"
|
||||
},
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private static boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:38 PM
|
||||
*/
|
||||
@Mixin(GuiScreen.class)
|
||||
public class MixinGuiScreen {
|
||||
|
||||
@Redirect(
|
||||
method = {
|
||||
"isCtrlKeyDown",
|
||||
"isShiftKeyDown",
|
||||
"isAltKeyDown"
|
||||
},
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private static boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
86
src/main/java/baritone/launch/mixins/MixinKeyBinding.java → src/launch/java/baritone/launch/mixins/MixinKeyBinding.java
Executable file → Normal file
86
src/main/java/baritone/launch/mixins/MixinKeyBinding.java → src/launch/java/baritone/launch/mixins/MixinKeyBinding.java
Executable file → Normal file
@@ -1,43 +1,43 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 11:44 PM
|
||||
*/
|
||||
@Mixin(KeyBinding.class)
|
||||
public abstract class MixinKeyBinding {
|
||||
|
||||
@Inject(
|
||||
method = "isKeyDown",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void isKeyDown(CallbackInfoReturnable<Boolean> cir) {
|
||||
if (Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this))
|
||||
cir.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 11:44 PM
|
||||
*/
|
||||
@Mixin(KeyBinding.class)
|
||||
public class MixinKeyBinding {
|
||||
|
||||
@Inject(
|
||||
method = "isKeyDown",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void isKeyDown(CallbackInfoReturnable<Boolean> cir) {
|
||||
if (Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this))
|
||||
cir.setReturnValue(true);
|
||||
}
|
||||
}
|
350
src/main/java/baritone/launch/mixins/MixinMinecraft.java → src/launch/java/baritone/launch/mixins/MixinMinecraft.java
Executable file → Normal file
350
src/main/java/baritone/launch/mixins/MixinMinecraft.java → src/launch/java/baritone/launch/mixins/MixinMinecraft.java
Executable file → Normal file
@@ -1,174 +1,176 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.behavior.impl.PathingBehavior;
|
||||
import baritone.event.events.BlockInteractEvent;
|
||||
import baritone.event.events.TickEvent;
|
||||
import baritone.event.events.WorldEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.utils.ExampleBaritoneControl;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:51 PM
|
||||
*/
|
||||
@Mixin(Minecraft.class)
|
||||
public class MixinMinecraft {
|
||||
|
||||
@Shadow private int leftClickCounter;
|
||||
@Shadow public EntityPlayerSP player;
|
||||
@Shadow public WorldClient world;
|
||||
|
||||
@Inject(
|
||||
method = "init",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void init(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.init();
|
||||
ExampleBaritoneControl.INSTANCE.initAndRegister();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "runTick",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/client/Minecraft.currentScreen:Lnet/minecraft/client/gui/GuiScreen;",
|
||||
ordinal = 5,
|
||||
shift = At.Shift.BY,
|
||||
by = -3
|
||||
)
|
||||
)
|
||||
private void runTick(CallbackInfo ci) {
|
||||
Minecraft mc = (Minecraft) (Object) this;
|
||||
Baritone.INSTANCE.getGameEventHandler().onTick(new TickEvent(
|
||||
EventState.PRE,
|
||||
(mc.player != null && mc.world != null)
|
||||
? TickEvent.Type.IN
|
||||
: TickEvent.Type.OUT
|
||||
));
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "runTickKeyboard",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private boolean Keyboard$isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "processKeyBinds",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void runTickKeyboard(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onProcessKeyBinds();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
|
||||
// If we're unloading the world but one doesn't exist, ignore it
|
||||
if (this.world == null && world == null)
|
||||
return;
|
||||
|
||||
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
|
||||
new WorldEvent(
|
||||
world,
|
||||
EventState.PRE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
|
||||
// If we're unloading the world but one doesn't exist, ignore it
|
||||
if (this.world == null && world == null)
|
||||
return;
|
||||
|
||||
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
|
||||
new WorldEvent(
|
||||
world,
|
||||
EventState.POST
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "runTick",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/client/gui/GuiScreen.allowUserInput:Z"
|
||||
)
|
||||
)
|
||||
private boolean isAllowUserInput(GuiScreen screen) {
|
||||
return (PathingBehavior.INSTANCE.getCurrent() != null && player != null) || screen.allowUserInput;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "clickMouse",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/multiplayer/PlayerControllerMP.clickBlock(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)Z"
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void onBlockBreak(CallbackInfo ci, BlockPos pos) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(pos, BlockInteractEvent.Type.BREAK));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "rightClickMouse",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/entity/EntityPlayerSP.swingArm(Lnet/minecraft/util/EnumHand;)V"
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void onBlockUse(CallbackInfo ci, EnumHand var1[], int var2, int var3, EnumHand enumhand, ItemStack itemstack, BlockPos blockpos, int i, EnumActionResult enumactionresult) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(blockpos, BlockInteractEvent.Type.USE));
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.BlockInteractEvent;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.event.events.WorldEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.behavior.impl.PathingBehavior;
|
||||
import baritone.utils.ExampleBaritoneControl;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:51 PM
|
||||
*/
|
||||
@Mixin(Minecraft.class)
|
||||
public class MixinMinecraft {
|
||||
|
||||
@Shadow
|
||||
private int leftClickCounter;
|
||||
@Shadow
|
||||
public EntityPlayerSP player;
|
||||
@Shadow
|
||||
public WorldClient world;
|
||||
|
||||
@Inject(
|
||||
method = "init",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void init(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.init();
|
||||
ExampleBaritoneControl.INSTANCE.initAndRegister();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "runTick",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/client/Minecraft.currentScreen:Lnet/minecraft/client/gui/GuiScreen;",
|
||||
ordinal = 5,
|
||||
shift = At.Shift.BY,
|
||||
by = -3
|
||||
)
|
||||
)
|
||||
private void runTick(CallbackInfo ci) {
|
||||
Minecraft mc = (Minecraft) (Object) this;
|
||||
Baritone.INSTANCE.getGameEventHandler().onTick(new TickEvent(
|
||||
EventState.PRE,
|
||||
(mc.player != null && mc.world != null)
|
||||
? TickEvent.Type.IN
|
||||
: TickEvent.Type.OUT
|
||||
));
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "runTickKeyboard",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private boolean Keyboard$isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "processKeyBinds",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void runTickKeyboard(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onProcessKeyBinds();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
|
||||
// If we're unloading the world but one doesn't exist, ignore it
|
||||
if (this.world == null && world == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
|
||||
new WorldEvent(
|
||||
world,
|
||||
EventState.PRE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
|
||||
// still fire event for both null, as that means we've just finished exiting a world
|
||||
|
||||
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
|
||||
new WorldEvent(
|
||||
world,
|
||||
EventState.POST
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "runTick",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/client/gui/GuiScreen.allowUserInput:Z"
|
||||
)
|
||||
)
|
||||
private boolean isAllowUserInput(GuiScreen screen) {
|
||||
return (PathingBehavior.INSTANCE.getCurrent() != null && player != null) || screen.allowUserInput;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "clickMouse",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/multiplayer/PlayerControllerMP.clickBlock(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)Z"
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void onBlockBreak(CallbackInfo ci, BlockPos pos) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(pos, BlockInteractEvent.Type.BREAK));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "rightClickMouse",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/entity/EntityPlayerSP.swingArm(Lnet/minecraft/util/EnumHand;)V"
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void onBlockUse(CallbackInfo ci, EnumHand var1[], int var2, int var3, EnumHand enumhand, ItemStack itemstack, BlockPos blockpos, int i, EnumActionResult enumactionresult) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(blockpos, BlockInteractEvent.Type.USE));
|
||||
}
|
||||
}
|
@@ -18,8 +18,8 @@
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.ChunkEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.ChunkEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.network.NetHandlerPlayClient;
|
||||
import net.minecraft.network.play.server.SPacketChunkData;
|
||||
import net.minecraft.network.play.server.SPacketCombatEvent;
|
@@ -18,8 +18,8 @@
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.PacketEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.PacketEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.util.concurrent.Future;
|
||||
@@ -37,12 +37,10 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
* @since 8/6/2018 9:30 PM
|
||||
*/
|
||||
@Mixin(NetworkManager.class)
|
||||
public abstract class MixinNetworkManager {
|
||||
public class MixinNetworkManager {
|
||||
|
||||
@Shadow private Channel channel;
|
||||
|
||||
@Shadow protected abstract void channelRead0(ChannelHandlerContext p_channelRead0_1_, Packet<?> p_channelRead0_2_) throws Exception;
|
||||
|
||||
@Inject(
|
||||
method = "dispatchPacket",
|
||||
at = @At("HEAD")
|
@@ -18,8 +18,8 @@
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.ChunkEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
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;
|
52
src/main/resources/mixins.baritone.json → src/launch/resources/mixins.baritone.json
Executable file → Normal file
52
src/main/resources/mixins.baritone.json → src/launch/resources/mixins.baritone.json
Executable file → Normal file
@@ -1,28 +1,26 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "baritone.launch.mixins",
|
||||
"refmap": "mixins.baritone.refmap.json",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"verbose": false,
|
||||
"injectors": {
|
||||
"maxShiftBy": 2
|
||||
},
|
||||
"client": [
|
||||
"MixinBlockPos",
|
||||
"MixinEntity",
|
||||
"MixinEntityPlayerSP",
|
||||
"MixinEntityRenderer",
|
||||
"MixinGameSettings",
|
||||
"MixinGuiContainer",
|
||||
"MixinGuiScreen",
|
||||
"MixinInventoryPlayer",
|
||||
"MixinKeyBinding",
|
||||
"MixinMinecraft",
|
||||
"MixinNetHandlerPlayClient",
|
||||
"MixinNetworkManager",
|
||||
"MixinWorldClient",
|
||||
|
||||
"accessor.IAnvilChunkLoader",
|
||||
"accessor.IChunkProviderServer"
|
||||
]
|
||||
{
|
||||
"required": true,
|
||||
"package": "baritone.launch.mixins",
|
||||
"refmap": "mixins.baritone.refmap.json",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"verbose": false,
|
||||
"injectors": {
|
||||
"maxShiftBy": 2
|
||||
},
|
||||
"client": [
|
||||
"MixinAnvilChunkLoader",
|
||||
"MixinBlockPos",
|
||||
"MixinChunkProviderServer",
|
||||
"MixinEntity",
|
||||
"MixinEntityPlayerSP",
|
||||
"MixinEntityRenderer",
|
||||
"MixinGameSettings",
|
||||
"MixinGuiContainer",
|
||||
"MixinGuiScreen",
|
||||
"MixinKeyBinding",
|
||||
"MixinMinecraft",
|
||||
"MixinNetHandlerPlayClient",
|
||||
"MixinNetworkManager",
|
||||
"MixinWorldClient"
|
||||
]
|
||||
}
|
@@ -17,12 +17,9 @@
|
||||
|
||||
package baritone;
|
||||
|
||||
import baritone.api.event.GameEventHandler;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.behavior.impl.LookBehavior;
|
||||
import baritone.behavior.impl.MemoryBehavior;
|
||||
import baritone.behavior.impl.PathingBehavior;
|
||||
import baritone.behavior.impl.LocationTrackingBehavior;
|
||||
import baritone.event.GameEventHandler;
|
||||
import baritone.behavior.impl.*;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
@@ -31,6 +28,7 @@ import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -54,11 +52,20 @@ public enum Baritone {
|
||||
private List<Behavior> behaviors;
|
||||
private File dir;
|
||||
|
||||
/**
|
||||
* List of consumers to be called after Baritone has initialized
|
||||
*/
|
||||
private List<Consumer<Baritone>> onInitConsumers;
|
||||
|
||||
/**
|
||||
* Whether or not Baritone is active
|
||||
*/
|
||||
private boolean active;
|
||||
|
||||
Baritone() {
|
||||
this.onInitConsumers = new ArrayList<>();
|
||||
}
|
||||
|
||||
public synchronized void init() {
|
||||
if (initialized) {
|
||||
return;
|
||||
@@ -72,6 +79,8 @@ public enum Baritone {
|
||||
registerBehavior(LookBehavior.INSTANCE);
|
||||
registerBehavior(MemoryBehavior.INSTANCE);
|
||||
registerBehavior(LocationTrackingBehavior.INSTANCE);
|
||||
registerBehavior(FollowBehavior.INSTANCE);
|
||||
registerBehavior(MineBehavior.INSTANCE);
|
||||
}
|
||||
this.dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
|
||||
if (!Files.exists(dir.toPath())) {
|
||||
@@ -82,6 +91,8 @@ public enum Baritone {
|
||||
|
||||
this.active = true;
|
||||
this.initialized = true;
|
||||
|
||||
this.onInitConsumers.forEach(consumer -> consumer.accept(this));
|
||||
}
|
||||
|
||||
public final boolean isInitialized() {
|
||||
@@ -120,4 +131,8 @@ public enum Baritone {
|
||||
public final File getDir() {
|
||||
return this.dir;
|
||||
}
|
||||
|
||||
public final void registerInitListener(Consumer<Baritone> runnable) {
|
||||
this.onInitConsumers.add(runnable);
|
||||
}
|
||||
}
|
||||
|
@@ -56,14 +56,20 @@ public class Settings {
|
||||
*/
|
||||
public Setting<Boolean> allowWaterBucketFall = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow Baritone to assume it can walk on still water just like any other block.
|
||||
* This functionality is assumed to be provided by a separate library that might have imported Baritone.
|
||||
*/
|
||||
public Setting<Boolean> assumeWalkOnWater = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.)
|
||||
*/
|
||||
public Setting<List<Item>> acceptableThrowawayItems = new Setting<>(Arrays.asList(
|
||||
public Setting<List<Item>> acceptableThrowawayItems = new Setting<>(new ArrayList<>(Arrays.asList(
|
||||
Item.getItemFromBlock(Blocks.DIRT),
|
||||
Item.getItemFromBlock(Blocks.COBBLESTONE),
|
||||
Item.getItemFromBlock(Blocks.NETHERRACK)
|
||||
));
|
||||
)));
|
||||
|
||||
/**
|
||||
* Enables some more advanced vine features. They're honestly just gimmicks and won't ever be needed in real
|
||||
@@ -71,6 +77,17 @@ public class Settings {
|
||||
*/
|
||||
public Setting<Boolean> allowVines = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Slab behavior is complicated, disable this for higher path reliability. Leave enabled if you have bottom slabs
|
||||
* everywhere in your base.
|
||||
*/
|
||||
public Setting<Boolean> allowWalkOnBottomSlab = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* For example, if you have Mining Fatigue or Haste, adjust the costs of breaking blocks accordingly.
|
||||
*/
|
||||
public Setting<Boolean> considerPotionEffects = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* This is the big A* setting.
|
||||
* As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path.
|
||||
@@ -116,8 +133,16 @@ public class Settings {
|
||||
/**
|
||||
* After calculating a path (potentially through cached chunks), artificially cut it off to just the part that is
|
||||
* entirely within currently loaded chunks. Improves path safety because cached chunks are heavily simplified.
|
||||
* See issue #114 for why this is disabled.
|
||||
*/
|
||||
public Setting<Boolean> cutoffAtLoadBoundary = new Setting<>(true);
|
||||
public Setting<Boolean> cutoffAtLoadBoundary = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Stop 5 movements before anything that made the path COST_INF.
|
||||
* For example, if lava has spread across the path, don't walk right up to it then recalculate, it might
|
||||
* still be spreading lol
|
||||
*/
|
||||
public Setting<Integer> costVerificationLookahead = new Setting<>(5);
|
||||
|
||||
/**
|
||||
* Static cutoff factor. 0.9 means cut off the last 10% of all paths, regardless of chunk load state
|
||||
@@ -147,6 +172,13 @@ public class Settings {
|
||||
*/
|
||||
public Setting<Integer> maxFallHeightBucket = new Setting<>(20);
|
||||
|
||||
/**
|
||||
* Is it okay to sprint through a descend followed by a diagonal?
|
||||
* The player overshoots the landing, but not enough to fall off. And the diagonal ensures that there isn't
|
||||
* lava or anything that's !canWalkInto in that space, so it's technically safe, just a little sketchy.
|
||||
*/
|
||||
public Setting<Boolean> allowOvershootDiagonalDescend = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* If your goal is a GoalBlock in an unloaded chunk, assume it's far enough away that the Y coord
|
||||
* doesn't matter yet, and replace it with a GoalXZ to the same place before calculating a path.
|
||||
@@ -164,7 +196,12 @@ public class Settings {
|
||||
/**
|
||||
* Pathing can never take longer than this
|
||||
*/
|
||||
public Setting<Number> pathTimeoutMS = new Setting<>(4000L);
|
||||
public Setting<Number> pathTimeoutMS = new Setting<>(2000L);
|
||||
|
||||
/**
|
||||
* Planning ahead while executing a segment can never take longer than this
|
||||
*/
|
||||
public Setting<Number> planAheadTimeoutMS = new Setting<>(4000L);
|
||||
|
||||
/**
|
||||
* For debugging, consider nodes much much slower
|
||||
@@ -197,6 +234,11 @@ public class Settings {
|
||||
*/
|
||||
public Setting<Boolean> chatControl = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* A second override over chatControl to force it on
|
||||
*/
|
||||
public Setting<Boolean> removePrefix = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Render the path
|
||||
*/
|
||||
@@ -309,10 +351,10 @@ public class Settings {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<Setting<T>> getByValueType(Class<T> klass) {
|
||||
public <T> List<Setting<T>> getAllValuesByType(Class<T> klass) {
|
||||
List<Setting<T>> result = new ArrayList<>();
|
||||
for (Setting<?> setting : allSettings) {
|
||||
if (setting.klass.equals(klass)) {
|
||||
if (setting.getValueClass().equals(klass)) {
|
||||
result.add((Setting<T>) setting);
|
||||
}
|
||||
}
|
||||
|
@@ -32,13 +32,14 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event;
|
||||
package baritone.api.event;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.*;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.event.events.*;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.event.listener.IGameEventListener;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.interfaces.Toggleable;
|
||||
@@ -133,9 +134,10 @@ public final class GameEventHandler implements IGameEventListener, Helper {
|
||||
public final void onWorldEvent(WorldEvent event) {
|
||||
WorldProvider cache = WorldProvider.INSTANCE;
|
||||
|
||||
BlockStateInterface.clearCachedChunk();
|
||||
|
||||
switch (event.getState()) {
|
||||
case PRE:
|
||||
cache.closeWorld();
|
||||
break;
|
||||
case POST:
|
||||
cache.closeWorld();
|
||||
@@ -157,11 +159,6 @@ public final class GameEventHandler implements IGameEventListener, Helper {
|
||||
dispatch(listener -> listener.onReceivePacket(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onQueryItemSlotForBlocks(ItemSlotEvent event) {
|
||||
dispatch(listener -> listener.onQueryItemSlotForBlocks(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerRelativeMove(RelativeMoveEvent event) {
|
||||
dispatch(listener -> listener.onPlayerRelativeMove(event));
|
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.event.events.type.Cancellable;
|
||||
import baritone.api.event.events.type.Cancellable;
|
||||
|
||||
/**
|
||||
* @author Brady
|
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
|
||||
/**
|
||||
* @author Brady
|
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.event.listener.IGameEventListener;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
|
||||
/**
|
||||
* Called in some cases where a player's inventory has it's current slot queried.
|
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.network.Packet;
|
||||
|
||||
/**
|
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
public enum PathEvent {
|
||||
CALC_STARTED,
|
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
|
||||
/**
|
||||
* @author Brady
|
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
|
||||
/**
|
||||
* @author Brady
|
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
/**
|
||||
* @author Brady
|
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
|
||||
public final class TickEvent {
|
||||
|
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
|
||||
/**
|
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events.type;
|
||||
package baritone.api.event.events.type;
|
||||
|
||||
/**
|
||||
* @author Brady
|
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.events.type;
|
||||
package baritone.api.event.events.type;
|
||||
|
||||
/**
|
||||
* @author Brady
|
@@ -32,9 +32,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.listener;
|
||||
package baritone.api.event.listener;
|
||||
|
||||
import baritone.event.events.*;
|
||||
import baritone.api.event.events.*;
|
||||
|
||||
/**
|
||||
* An implementation of {@link IGameEventListener} that has all methods
|
||||
@@ -74,9 +74,6 @@ public interface AbstractGameEventListener extends IGameEventListener {
|
||||
@Override
|
||||
default void onReceivePacket(PacketEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onQueryItemSlotForBlocks(ItemSlotEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onPlayerRelativeMove(RelativeMoveEvent event) {}
|
||||
|
@@ -32,11 +32,10 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.event.listener;
|
||||
package baritone.api.event.listener;
|
||||
|
||||
import baritone.event.events.*;
|
||||
import baritone.api.event.events.*;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.GuiGameOver;
|
||||
@@ -44,7 +43,6 @@ import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
@@ -120,14 +118,6 @@ public interface IGameEventListener {
|
||||
*/
|
||||
void onReceivePacket(PacketEvent event);
|
||||
|
||||
/**
|
||||
* Run when a query is made for a player's inventory current slot in the context of blocks
|
||||
*
|
||||
* @see InventoryPlayer#getDestroySpeed(IBlockState)
|
||||
* @see InventoryPlayer#canHarvestBlock(IBlockState)
|
||||
*/
|
||||
void onQueryItemSlotForBlocks(ItemSlotEvent event);
|
||||
|
||||
/**
|
||||
* Run once per game tick from before and after the player's moveRelative method is called
|
||||
*
|
@@ -17,7 +17,7 @@
|
||||
|
||||
package baritone.behavior;
|
||||
|
||||
import baritone.event.listener.AbstractGameEventListener;
|
||||
import baritone.api.event.listener.AbstractGameEventListener;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.interfaces.Toggleable;
|
||||
|
||||
|
60
src/main/java/baritone/behavior/impl/FollowBehavior.java
Normal file
60
src/main/java/baritone/behavior/impl/FollowBehavior.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.pathing.goals.GoalNear;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
* Follow an entity
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class FollowBehavior extends Behavior {
|
||||
public static final FollowBehavior INSTANCE = new FollowBehavior();
|
||||
|
||||
private FollowBehavior() {
|
||||
}
|
||||
|
||||
Entity following;
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
return;
|
||||
}
|
||||
if (following == null) {
|
||||
return;
|
||||
}
|
||||
// lol this is trashy but it works
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalNear(new BlockPos(following), 3));
|
||||
PathingBehavior.INSTANCE.path();
|
||||
}
|
||||
|
||||
public void follow(Entity follow) {
|
||||
this.following = follow;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
follow(null);
|
||||
}
|
||||
}
|
@@ -20,7 +20,7 @@ package baritone.behavior.impl;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.chunk.Waypoint;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.event.events.BlockInteractEvent;
|
||||
import baritone.api.event.events.BlockInteractEvent;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.block.BlockBed;
|
||||
|
||||
|
@@ -20,9 +20,8 @@ package baritone.behavior.impl;
|
||||
import baritone.Baritone;
|
||||
import baritone.Settings;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.event.events.PlayerUpdateEvent;
|
||||
import baritone.event.events.RelativeMoveEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.RelativeMoveEvent;
|
||||
import baritone.utils.Rotation;
|
||||
|
||||
public class LookBehavior extends Behavior {
|
||||
|
@@ -17,10 +17,7 @@
|
||||
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.Rotation;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.utils.*;
|
||||
import net.minecraft.block.BlockFire;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.*;
|
||||
@@ -87,18 +84,6 @@ public final class LookBehaviorUtils implements Helper {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static RayTraceResult rayTraceTowards(Rotation rotation) {
|
||||
double blockReachDistance = mc.playerController.getBlockReachDistance();
|
||||
Vec3d start = mc.player.getPositionEyes(1.0F);
|
||||
Vec3d direction = calcVec3dFromRotation(rotation);
|
||||
Vec3d end = start.add(
|
||||
direction.x * blockReachDistance,
|
||||
direction.y * blockReachDistance,
|
||||
direction.z * blockReachDistance
|
||||
);
|
||||
return mc.world.rayTraceBlocks(start, end, false, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if coordinate is reachable with the given block-face rotation offset
|
||||
*
|
||||
@@ -108,7 +93,7 @@ public final class LookBehaviorUtils implements Helper {
|
||||
*/
|
||||
protected static Optional<Rotation> reachableOffset(BlockPos pos, Vec3d offsetPos) {
|
||||
Rotation rotation = Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F), offsetPos);
|
||||
RayTraceResult result = rayTraceTowards(rotation);
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(rotation);
|
||||
System.out.println(result);
|
||||
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
if (result.getBlockPos().equals(pos)) {
|
||||
|
@@ -1,9 +1,9 @@
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.event.events.PacketEvent;
|
||||
import baritone.event.events.PlayerUpdateEvent;
|
||||
import baritone.event.events.type.EventState;
|
||||
import baritone.api.event.events.PacketEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.play.client.CPacketCloseWindow;
|
||||
@@ -59,7 +59,7 @@ public class MemoryBehavior extends Behavior {
|
||||
TileEntityLockable lockable = (TileEntityLockable) tileEntity;
|
||||
int size = lockable.getSizeInventory();
|
||||
|
||||
this.futureInventories.add(new FutureInventory(System.currentTimeMillis(), size, lockable.getGuiID(), tileEntity.getPos()));
|
||||
this.futureInventories.add(new FutureInventory(System.nanoTime() / 1000000L, size, lockable.getGuiID(), tileEntity.getPos()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,7 +81,7 @@ public class MemoryBehavior extends Behavior {
|
||||
SPacketOpenWindow packet = event.cast();
|
||||
|
||||
// Remove any entries that were created over a second ago, this should make up for INSANE latency
|
||||
this.futureInventories.removeIf(i -> System.currentTimeMillis() - i.time > 1000);
|
||||
this.futureInventories.removeIf(i -> System.nanoTime() / 1000000L - i.time > 1000);
|
||||
|
||||
this.futureInventories.stream()
|
||||
.filter(i -> i.type.equals(packet.getGuiId()) && i.slots == packet.getSlotCount())
|
||||
|
111
src/main/java/baritone/behavior/impl/MineBehavior.java
Normal file
111
src/main/java/baritone/behavior/impl/MineBehavior.java
Normal file
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.api.event.events.PathEvent;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.chunk.CachedChunk;
|
||||
import baritone.chunk.ChunkPacker;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.chunk.WorldScanner;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.goals.GoalComposite;
|
||||
import baritone.pathing.goals.GoalTwoBlocks;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Mine blocks of a certain type
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class MineBehavior extends Behavior {
|
||||
public static final MineBehavior INSTANCE = new MineBehavior();
|
||||
|
||||
private MineBehavior() {
|
||||
}
|
||||
|
||||
List<String> mining;
|
||||
|
||||
@Override
|
||||
public void onPathEvent(PathEvent event) {
|
||||
updateGoal();
|
||||
}
|
||||
|
||||
public void updateGoal() {
|
||||
if (mining == null) {
|
||||
return;
|
||||
}
|
||||
List<BlockPos> locs = scanFor(mining, 64);
|
||||
if (locs.isEmpty()) {
|
||||
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalTwoBlocks::new).toArray(Goal[]::new)));
|
||||
PathingBehavior.INSTANCE.path();
|
||||
}
|
||||
|
||||
public static List<BlockPos> scanFor(List<String> mining, int max) {
|
||||
List<BlockPos> locs = new ArrayList<>();
|
||||
List<String> uninteresting = new ArrayList<>();
|
||||
//long b = System.currentTimeMillis();
|
||||
for (String m : mining) {
|
||||
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(ChunkPacker.stringToBlock(m))) {
|
||||
locs.addAll(WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(m, 1, 1));
|
||||
} else {
|
||||
uninteresting.add(m);
|
||||
}
|
||||
}
|
||||
//System.out.println("Scan of cached chunks took " + (System.currentTimeMillis() - b) + "ms");
|
||||
if (!uninteresting.isEmpty()) {
|
||||
//long before = System.currentTimeMillis();
|
||||
locs.addAll(WorldScanner.INSTANCE.scanLoadedChunks(uninteresting, max));
|
||||
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
|
||||
}
|
||||
BlockPos playerFeet = MineBehavior.INSTANCE.playerFeet();
|
||||
locs.sort(Comparator.comparingDouble(playerFeet::distanceSq));
|
||||
|
||||
// remove any that are within loaded chunks that aren't actually what we want
|
||||
locs.removeAll(locs.stream()
|
||||
.filter(pos -> !(MineBehavior.INSTANCE.world().getChunk(pos) instanceof EmptyChunk))
|
||||
.filter(pos -> !mining.contains(ChunkPacker.blockToString(BlockStateInterface.get(pos).getBlock()).toLowerCase()))
|
||||
.collect(Collectors.toList()));
|
||||
if (locs.size() > max) {
|
||||
locs = locs.subList(0, max);
|
||||
}
|
||||
return locs;
|
||||
}
|
||||
|
||||
public void mine(String... mining) {
|
||||
this.mining = mining == null || mining.length == 0 ? null : new ArrayList<>(Arrays.asList(mining));
|
||||
updateGoal();
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
mine();
|
||||
}
|
||||
}
|
@@ -18,17 +18,16 @@
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.PathEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.RenderEvent;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.event.events.PathEvent;
|
||||
import baritone.event.events.PlayerUpdateEvent;
|
||||
import baritone.event.events.RenderEvent;
|
||||
import baritone.event.events.TickEvent;
|
||||
import baritone.pathing.calc.AStarPathFinder;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.calc.IPathFinder;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.goals.GoalBlock;
|
||||
import baritone.pathing.goals.GoalXZ;
|
||||
import baritone.pathing.goals.*;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.pathing.path.PathExecutor;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
@@ -196,27 +195,39 @@ public class PathingBehavior extends Behavior {
|
||||
current = null;
|
||||
next = null;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(AbstractNodeCostSearch::cancel);
|
||||
}
|
||||
|
||||
public void path() {
|
||||
/**
|
||||
* Start calculating a path if we aren't already
|
||||
*
|
||||
* @return true if this call started path calculation, false if it was already calculating or executing a path
|
||||
*/
|
||||
public boolean path() {
|
||||
if (goal == null) {
|
||||
return false;
|
||||
}
|
||||
if (goal.isInGoal(playerFeet())) {
|
||||
return false;
|
||||
}
|
||||
synchronized (pathPlanLock) {
|
||||
if (current != null) {
|
||||
displayChatMessageRaw("Currently executing a path. Please cancel it first.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
synchronized (pathCalcLock) {
|
||||
if (isPathCalcInProgress) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
dispatchPathEvent(PathEvent.CALC_STARTED);
|
||||
findPathInNewThread(pathStart(), true, Optional.empty());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BlockPos pathStart() {
|
||||
BlockPos feet = playerFeet();
|
||||
if (BlockStateInterface.get(feet.down()).getBlock().equals(Blocks.AIR)) {
|
||||
if (BlockStateInterface.get(feet.down()).getBlock().equals(Blocks.AIR) && MovementHelper.canWalkOn(feet.down().down())) {
|
||||
return feet.down();
|
||||
}
|
||||
return feet;
|
||||
@@ -293,18 +304,37 @@ public class PathingBehavior extends Behavior {
|
||||
displayChatMessageRaw("no goal");
|
||||
return Optional.empty();
|
||||
}
|
||||
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof GoalBlock) {
|
||||
BlockPos pos = ((GoalBlock) goal).getGoalPos();
|
||||
if (world().getChunk(pos) instanceof EmptyChunk) {
|
||||
displayChatMessageRaw("Simplifying GoalBlock to GoalXZ due to distance");
|
||||
if (Baritone.settings().simplifyUnloadedYCoord.get()) {
|
||||
BlockPos pos = null;
|
||||
if (goal instanceof GoalBlock) {
|
||||
pos = ((GoalBlock) goal).getGoalPos();
|
||||
}
|
||||
if (goal instanceof GoalTwoBlocks) {
|
||||
pos = ((GoalTwoBlocks) goal).getGoalPos();
|
||||
}
|
||||
if (goal instanceof GoalNear) {
|
||||
pos = ((GoalNear) goal).getGoalPos();
|
||||
}
|
||||
if (goal instanceof GoalGetToBlock) {
|
||||
pos = ((GoalGetToBlock) goal).getGoalPos();
|
||||
}
|
||||
// TODO simplify each individual goal in a GoalComposite
|
||||
if (pos != null && world().getChunk(pos) instanceof EmptyChunk) {
|
||||
displayChatMessageRaw("Simplifying " + goal.getClass() + " to GoalXZ due to distance");
|
||||
goal = new GoalXZ(pos.getX(), pos.getZ());
|
||||
}
|
||||
}
|
||||
long timeout;
|
||||
if (current == null) {
|
||||
timeout = Baritone.settings().pathTimeoutMS.<Long>get();
|
||||
} else {
|
||||
timeout = Baritone.settings().planAheadTimeoutMS.<Long>get();
|
||||
}
|
||||
try {
|
||||
IPathFinder pf = new AStarPathFinder(start, goal, previous.map(IPath::positions));
|
||||
return pf.calculate();
|
||||
return pf.calculate(timeout);
|
||||
} catch (Exception e) {
|
||||
displayChatMessageRaw("Exception: " + e);
|
||||
displayChatMessageRaw("Pathing exception: " + e);
|
||||
e.printStackTrace();
|
||||
return Optional.empty();
|
||||
}
|
||||
|
@@ -121,7 +121,10 @@ public final class CachedChunk implements IBlockTypeAccess {
|
||||
if (heightMap[internalPos] == y) {
|
||||
// we have this exact block, it's a surface block
|
||||
IBlockState state = ChunkPacker.stringToBlock(overview[internalPos]).getDefaultState();
|
||||
//System.out.println("Saying that " + x + "," + y + "," + z + " is " + state);
|
||||
/*System.out.println("Saying that " + x + "," + y + "," + z + " is " + state);
|
||||
if (!Minecraft.getMinecraft().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock().equals(state.getBlock())) {
|
||||
throw new IllegalStateException("failed " + Minecraft.getMinecraft().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock() + " " + state.getBlock() + " " + (x + this.x * 16) + " " + y + " " + (z + this.z * 16));
|
||||
}*/
|
||||
return state;
|
||||
}
|
||||
PathingBlockType type = getType(x, y, z);
|
||||
@@ -139,7 +142,8 @@ public final class CachedChunk implements IBlockTypeAccess {
|
||||
int index = z << 4 | x;
|
||||
heightMap[index] = 0;
|
||||
for (int y = 256; y >= 0; y--) {
|
||||
if (getType(x, y, z) != PathingBlockType.AIR) {
|
||||
int i = getPositionIndex(x, y, z);
|
||||
if (data.get(i) || data.get(i + 1)) {
|
||||
heightMap[index] = y;
|
||||
break;
|
||||
}
|
||||
@@ -183,7 +187,7 @@ public final class CachedChunk implements IBlockTypeAccess {
|
||||
* @return The bit index
|
||||
*/
|
||||
public static int getPositionIndex(int x, int y, int z) {
|
||||
return (x + (z << 4) + (y << 8)) * 2;
|
||||
return (x << 1) | (z << 5) | (y << 9);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -77,6 +77,10 @@ public final class CachedRegion implements IBlockTypeAccess {
|
||||
return null;
|
||||
}
|
||||
|
||||
public final boolean isCached(int x, int z) {
|
||||
return chunks[x >> 4][z >> 4] != null;
|
||||
}
|
||||
|
||||
public final LinkedList<BlockPos> getLocationsOf(String block) {
|
||||
LinkedList<BlockPos> res = new LinkedList<>();
|
||||
for (int chunkX = 0; chunkX < 32; chunkX++) {
|
||||
@@ -117,8 +121,8 @@ public final class CachedRegion implements IBlockTypeAccess {
|
||||
Files.createFile(regionFile);
|
||||
try (
|
||||
FileOutputStream fileOut = new FileOutputStream(regionFile.toFile());
|
||||
GZIPOutputStream gzipOut = new GZIPOutputStream(fileOut);
|
||||
DataOutputStream out = new DataOutputStream(gzipOut);
|
||||
GZIPOutputStream gzipOut = new GZIPOutputStream(fileOut, 16384);
|
||||
DataOutputStream out = new DataOutputStream(gzipOut)
|
||||
) {
|
||||
out.writeInt(CACHED_REGION_MAGIC);
|
||||
for (int z = 0; z < 32; z++) {
|
||||
@@ -179,12 +183,12 @@ public final class CachedRegion implements IBlockTypeAccess {
|
||||
return;
|
||||
|
||||
System.out.println("Loading region " + x + "," + z + " from disk " + path);
|
||||
long start = System.currentTimeMillis();
|
||||
long start = System.nanoTime() / 1000000L;
|
||||
|
||||
try (
|
||||
FileInputStream fileIn = new FileInputStream(regionFile.toFile());
|
||||
GZIPInputStream gzipIn = new GZIPInputStream(fileIn);
|
||||
DataInputStream in = new DataInputStream(gzipIn);
|
||||
GZIPInputStream gzipIn = new GZIPInputStream(fileIn, 32768);
|
||||
DataInputStream in = new DataInputStream(gzipIn)
|
||||
) {
|
||||
int magic = in.readInt();
|
||||
if (magic != CACHED_REGION_MAGIC) {
|
||||
@@ -231,21 +235,23 @@ public final class CachedRegion implements IBlockTypeAccess {
|
||||
if (tmpCached[x][z] != null) {
|
||||
// 16 * 16 * 256 = 65536 so a short is enough
|
||||
// ^ haha jokes on leijurv, java doesn't have unsigned types so that isn't correct
|
||||
// also ur gay if u have more than 32767 special blocks in a chunk
|
||||
short numSpecialBlockTypes = in.readShort();
|
||||
// also why would you have more than 32767 special blocks in a chunk
|
||||
// haha double jokes on you now it works for 65535 not just 32767
|
||||
int numSpecialBlockTypes = in.readShort() & 0xffff;
|
||||
for (int i = 0; i < numSpecialBlockTypes; i++) {
|
||||
String blockName = in.readUTF();
|
||||
List<BlockPos> locs = new ArrayList<>();
|
||||
location[x][z].put(blockName, locs);
|
||||
short numLocations = in.readShort();
|
||||
int numLocations = in.readShort() & 0xffff;
|
||||
if (numLocations == 0) {
|
||||
// an entire chunk full of air can happen in the end
|
||||
numLocations = 65536;
|
||||
}
|
||||
for (int j = 0; j < numLocations; j++) {
|
||||
byte xz = in.readByte();
|
||||
int X = xz & 0x0f;
|
||||
int Z = (xz >>> 4) & 0x0f;
|
||||
int Y = (int) in.readByte();
|
||||
if (Y < 0) {
|
||||
Y += 256;
|
||||
}
|
||||
int Y = in.readByte() & 0xff;
|
||||
locs.add(new BlockPos(X, Y, Z));
|
||||
}
|
||||
}
|
||||
@@ -260,7 +266,7 @@ public final class CachedRegion implements IBlockTypeAccess {
|
||||
}
|
||||
}
|
||||
hasUnsavedChanges = false;
|
||||
long end = System.currentTimeMillis();
|
||||
long end = System.nanoTime() / 1000000L;
|
||||
System.out.println("Loaded region successfully in " + (end - start) + "ms");
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
|
@@ -59,28 +59,28 @@ public final class CachedWorld implements IBlockTypeAccess {
|
||||
if (!Files.exists(directory)) {
|
||||
try {
|
||||
Files.createDirectories(directory);
|
||||
} catch (IOException ignored) {}
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
this.directory = directory.toString();
|
||||
System.out.println("Cached world directory: " + directory);
|
||||
// Insert an invalid region element
|
||||
cachedRegions.put(0, null);
|
||||
new PackerThread().start();
|
||||
new Thread() {
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
// since a region only saves if it's been modified since its last save
|
||||
// saving every 10 minutes means that once it's time to exit
|
||||
// we'll only have a couple regions to save
|
||||
save();
|
||||
Thread.sleep(600000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(30000);
|
||||
while (true) {
|
||||
// since a region only saves if it's been modified since its last save
|
||||
// saving every 10 minutes means that once it's time to exit
|
||||
// we'll only have a couple regions to save
|
||||
save();
|
||||
Thread.sleep(600000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}.start();
|
||||
}).start();
|
||||
}
|
||||
|
||||
public final void queueForPacking(Chunk chunk) {
|
||||
@@ -101,6 +101,17 @@ public final class CachedWorld implements IBlockTypeAccess {
|
||||
return region.getBlock(x & 511, y, z & 511);
|
||||
}
|
||||
|
||||
public final boolean isCached(BlockPos pos) {
|
||||
int x = pos.getX();
|
||||
int z = pos.getZ();
|
||||
CachedRegion region = getRegion(x >> 9, z >> 9);
|
||||
if (region == null) {
|
||||
return false;
|
||||
}
|
||||
return region.isCached(x & 511, z & 511);
|
||||
}
|
||||
|
||||
|
||||
public final LinkedList<BlockPos> getLocationsOf(String block, int minimum, int maxRegionDistanceSq) {
|
||||
LinkedList<BlockPos> res = new LinkedList<>();
|
||||
int playerRegionX = playerFeet().getX() >> 9;
|
||||
@@ -140,22 +151,22 @@ public final class CachedWorld implements IBlockTypeAccess {
|
||||
System.out.println("Not saving to disk; chunk caching is disabled.");
|
||||
return;
|
||||
}
|
||||
long start = System.currentTimeMillis();
|
||||
this.cachedRegions.values().forEach(region -> {
|
||||
long start = System.nanoTime() / 1000000L;
|
||||
this.cachedRegions.values().parallelStream().forEach(region -> {
|
||||
if (region != null)
|
||||
region.save(this.directory);
|
||||
});
|
||||
long now = System.currentTimeMillis();
|
||||
long now = System.nanoTime() / 1000000L;
|
||||
System.out.println("World save took " + (now - start) + "ms");
|
||||
}
|
||||
|
||||
public final void reloadAllFromDisk() {
|
||||
long start = System.currentTimeMillis();
|
||||
long start = System.nanoTime() / 1000000L;
|
||||
this.cachedRegions.values().forEach(region -> {
|
||||
if (region != null)
|
||||
region.load(this.directory);
|
||||
});
|
||||
long now = System.currentTimeMillis();
|
||||
long now = System.nanoTime() / 1000000L;
|
||||
System.out.println("World load took " + (now - start) + "ms");
|
||||
}
|
||||
|
||||
|
@@ -18,18 +18,19 @@
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.PathingBlockType;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockAir;
|
||||
import net.minecraft.block.BlockDoublePlant;
|
||||
import net.minecraft.block.BlockFlower;
|
||||
import net.minecraft.block.BlockTallGrass;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -41,46 +42,86 @@ public final class ChunkPacker implements Helper {
|
||||
|
||||
private ChunkPacker() {}
|
||||
|
||||
private static BitSet originalPacker(Chunk chunk) {
|
||||
BitSet bitSet = new BitSet(CachedChunk.SIZE);
|
||||
for (int y = 0; y < 256; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
||||
IBlockState state = chunk.getBlockState(x, y, z);
|
||||
boolean[] bits = getPathingBlockType(state).getBits();
|
||||
bitSet.set(index, bits[0]);
|
||||
bitSet.set(index + 1, bits[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bitSet;
|
||||
}
|
||||
|
||||
public static CachedChunk pack(Chunk chunk) {
|
||||
long start = System.currentTimeMillis();
|
||||
long start = System.nanoTime() / 1000000L;
|
||||
|
||||
Map<String, List<BlockPos>> specialBlocks = new HashMap<>();
|
||||
BitSet bitSet = new BitSet(CachedChunk.SIZE);
|
||||
try {
|
||||
for (int y = 0; y < 256; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
||||
Block block = chunk.getBlockState(x, y, z).getBlock();
|
||||
boolean[] bits = getPathingBlockType(block).getBits();
|
||||
bitSet.set(index, bits[0]);
|
||||
bitSet.set(index + 1, bits[1]);
|
||||
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(block)) {
|
||||
String name = blockToString(block);
|
||||
specialBlocks.computeIfAbsent(name, b -> new ArrayList<>()).add(new BlockPos(x, y, z));
|
||||
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
|
||||
for (int y0 = 0; y0 < 16; y0++) {
|
||||
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
|
||||
if (extendedblockstorage == null) {
|
||||
// any 16x16x16 area that's all air will have null storage
|
||||
// for example, in an ocean biome, with air from y=64 to y=256
|
||||
// the first 4 extended blocks storages will be full
|
||||
// and the remaining 12 will be null
|
||||
|
||||
// since the index into the bitset is calculated from the x y and z
|
||||
// and doesn't function as an append, we can entirely skip the scanning
|
||||
// since a bitset is initialized to all zero, and air is saved as zeros
|
||||
continue;
|
||||
}
|
||||
BlockStateContainer bsc = extendedblockstorage.getData();
|
||||
int yReal = y0 << 4;
|
||||
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
|
||||
// for better cache locality, iterate in that order
|
||||
for (int y1 = 0; y1 < 16; y1++) {
|
||||
int y = y1 | yReal;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
||||
IBlockState state = bsc.get(x, y1, z);
|
||||
boolean[] bits = getPathingBlockType(state).getBits();
|
||||
bitSet.set(index, bits[0]);
|
||||
bitSet.set(index + 1, bits[1]);
|
||||
Block block = state.getBlock();
|
||||
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(block)) {
|
||||
String name = blockToString(block);
|
||||
specialBlocks.computeIfAbsent(name, b -> new ArrayList<>()).add(new BlockPos(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*if (!bitSet.equals(originalPacker(chunk))) {
|
||||
throw new IllegalStateException();
|
||||
}*/
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//System.out.println("Packed special blocks: " + specialBlocks);
|
||||
long end = System.currentTimeMillis();
|
||||
long end = System.nanoTime() / 1000000L;
|
||||
//System.out.println("Chunk packing took " + (end - start) + "ms for " + chunk.x + "," + chunk.z);
|
||||
String[] blockNames = new String[256];
|
||||
for (int z = 0; z < 16; z++) {
|
||||
outerLoop:
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int height = chunk.getHeightValue(x, z);
|
||||
IBlockState blockState = chunk.getBlockState(x, height, z);
|
||||
for (int y = height; y > 0; y--) {
|
||||
blockState = chunk.getBlockState(x, y, z);
|
||||
if (getPathingBlockType(blockState.getBlock()) != PathingBlockType.AIR) {
|
||||
break;
|
||||
for (int y = 255; y >= 0; y--) {
|
||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
||||
if (bitSet.get(index) || bitSet.get(index + 1)) {
|
||||
String name = blockToString(chunk.getBlockState(x, y, z).getBlock());
|
||||
blockNames[z << 4 | x] = name;
|
||||
continue outerLoop;
|
||||
}
|
||||
}
|
||||
String name = blockToString(blockState.getBlock());
|
||||
blockNames[z << 4 | x] = name;
|
||||
blockNames[z << 4 | x] = "air";
|
||||
}
|
||||
}
|
||||
CachedChunk cached = new CachedChunk(chunk.x, chunk.z, bitSet, blockNames, specialBlocks);
|
||||
@@ -104,19 +145,21 @@ public final class ChunkPacker implements Helper {
|
||||
return Block.getBlockFromName(name);
|
||||
}
|
||||
|
||||
private static PathingBlockType getPathingBlockType(Block block) {
|
||||
if (BlockStateInterface.isWater(block)) {
|
||||
private static PathingBlockType getPathingBlockType(IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block.equals(Blocks.WATER)) {
|
||||
// only water source blocks are plausibly usable, flowing water should be avoid
|
||||
return PathingBlockType.WATER;
|
||||
}
|
||||
|
||||
if (MovementHelper.avoidWalkingInto(block)) {
|
||||
if (MovementHelper.avoidWalkingInto(block) || block.equals(Blocks.FLOWING_WATER) || MovementHelper.isBottomSlab(state)) {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
// We used to do an AABB check here
|
||||
// however, this failed in the nether when you were near a nether fortress
|
||||
// because fences check their adjacent blocks in the world for their fence connection status to determine AABB shape
|
||||
// this caused a nullpointerexception when we saved chunks on unload, because they were unable to check their neighbors
|
||||
if (block instanceof BlockAir || block instanceof BlockTallGrass || block instanceof BlockDoublePlant) {
|
||||
if (block == Blocks.AIR || block instanceof BlockTallGrass || block instanceof BlockDoublePlant || block instanceof BlockFlower) {
|
||||
return PathingBlockType.AIR;
|
||||
}
|
||||
|
||||
|
@@ -17,12 +17,11 @@
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A single waypoint
|
||||
@@ -30,6 +29,7 @@ import java.util.Map;
|
||||
* @author leijurv
|
||||
*/
|
||||
public class Waypoint {
|
||||
|
||||
public final String name;
|
||||
public final Tag tag;
|
||||
private final long creationTimestamp;
|
||||
@@ -72,19 +72,21 @@ public class Waypoint {
|
||||
}
|
||||
|
||||
public enum Tag {
|
||||
HOME, DEATH, BED, USER;
|
||||
HOME("home", "base"),
|
||||
DEATH("death"),
|
||||
BED("bed", "spawn"),
|
||||
USER();
|
||||
|
||||
}
|
||||
private static final List<Tag> TAG_LIST = ImmutableList.<Tag>builder().add(Tag.values()).build();
|
||||
|
||||
public static final Map<String, Tag> TAG_MAP;
|
||||
private final String[] names;
|
||||
|
||||
static {
|
||||
HashMap<String, Tag> map = new HashMap<>();
|
||||
map.put("home", Tag.HOME);
|
||||
map.put("base", Tag.HOME);
|
||||
map.put("bed", Tag.BED);
|
||||
map.put("spawn", Tag.BED);
|
||||
map.put("death", Tag.DEATH);
|
||||
TAG_MAP = Collections.unmodifiableMap(map);
|
||||
Tag(String... names) {
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
public static Tag fromString(String name) {
|
||||
return TAG_LIST.stream().filter(tag -> ArrayUtils.contains(tag.names, name.toLowerCase())).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -18,8 +18,8 @@
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.launch.mixins.accessor.IAnvilChunkLoader;
|
||||
import baritone.launch.mixins.accessor.IChunkProviderServer;
|
||||
import baritone.utils.accessor.IAnvilChunkLoader;
|
||||
import baritone.utils.accessor.IChunkProviderServer;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
|
100
src/main/java/baritone/chunk/WorldScanner.java
Normal file
100
src/main/java/baritone/chunk/WorldScanner.java
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.multiplayer.ChunkProviderClient;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public enum WorldScanner implements Helper {
|
||||
INSTANCE;
|
||||
|
||||
public List<BlockPos> scanLoadedChunks(List<String> blockTypes, int max) {
|
||||
List<Block> asBlocks = blockTypes.stream().map(ChunkPacker::stringToBlock).collect(Collectors.toList());
|
||||
if (asBlocks.contains(null)) {
|
||||
throw new IllegalStateException("Invalid block name should have been caught earlier: " + blockTypes.toString());
|
||||
}
|
||||
LinkedList<BlockPos> res = new LinkedList<>();
|
||||
if (asBlocks.isEmpty()) {
|
||||
return res;
|
||||
}
|
||||
ChunkProviderClient chunkProvider = world().getChunkProvider();
|
||||
|
||||
int playerChunkX = playerFeet().getX() >> 4;
|
||||
int playerChunkZ = playerFeet().getZ() >> 4;
|
||||
|
||||
int searchRadius = 2;
|
||||
while (true) {
|
||||
boolean allUnloaded = true;
|
||||
for (int xoff = -searchRadius; xoff <= searchRadius; xoff++) {
|
||||
for (int zoff = -searchRadius; zoff <= searchRadius; zoff++) {
|
||||
int distance = xoff * xoff + zoff * zoff;
|
||||
if (distance != searchRadius) {
|
||||
continue;
|
||||
}
|
||||
int chunkX = xoff + playerChunkX;
|
||||
int chunkZ = zoff + playerChunkZ;
|
||||
Chunk chunk = chunkProvider.getLoadedChunk(chunkX, chunkZ);
|
||||
if (chunk == null) {
|
||||
continue;
|
||||
}
|
||||
allUnloaded = false;
|
||||
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
|
||||
chunkX = chunkX << 4;
|
||||
chunkZ = chunkZ << 4;
|
||||
for (int y0 = 0; y0 < 16; y0++) {
|
||||
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
|
||||
if (extendedblockstorage == null) {
|
||||
continue;
|
||||
}
|
||||
int yReal = y0 << 4;
|
||||
BlockStateContainer bsc = extendedblockstorage.getData();
|
||||
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
|
||||
// for better cache locality, iterate in that order
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
IBlockState state = bsc.get(x, y, z);
|
||||
if (asBlocks.contains(state.getBlock())) {
|
||||
res.add(new BlockPos(chunkX | x, yReal | y, chunkZ | z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allUnloaded) {
|
||||
return res;
|
||||
}
|
||||
if (res.size() >= max) {
|
||||
return res;
|
||||
}
|
||||
searchRadius++;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.ItemSlotEvent;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/20/2018
|
||||
*/
|
||||
@Mixin(InventoryPlayer.class)
|
||||
public class MixinInventoryPlayer {
|
||||
|
||||
@Redirect(
|
||||
method = "getDestroySpeed",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I"
|
||||
)
|
||||
)
|
||||
private int getDestroySpeed$getCurrentItem(InventoryPlayer inventory) {
|
||||
ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem);
|
||||
Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event);
|
||||
return event.getSlot();
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "canHarvestBlock",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I"
|
||||
)
|
||||
)
|
||||
private int canHarvestBlock$getCurrentItem(InventoryPlayer inventory) {
|
||||
ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem);
|
||||
Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event);
|
||||
return event.getSlot();
|
||||
}
|
||||
}
|
@@ -18,9 +18,9 @@
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.chunk.CachedWorld;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
|
||||
import baritone.pathing.calc.openset.IOpenSet;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.movement.ActionCosts;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
@@ -31,9 +31,9 @@ import baritone.pathing.path.IPath;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ChunkProviderClient;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -55,11 +55,11 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<IPath> calculate0() {
|
||||
protected Optional<IPath> calculate0(long timeout) {
|
||||
startNode = getNodeAtPosition(start);
|
||||
startNode.cost = 0;
|
||||
startNode.combinedCost = startNode.estimatedCostToGoal;
|
||||
IOpenSet openSet = new BinaryHeapOpenSet();
|
||||
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
|
||||
openSet.insert(startNode);
|
||||
startNode.isOpen = true;
|
||||
bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
|
||||
@@ -70,17 +70,23 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
CalculationContext calcContext = new CalculationContext();
|
||||
HashSet<BetterBlockPos> favored = favoredPositions.orElse(null);
|
||||
currentlyRunning = this;
|
||||
long startTime = System.currentTimeMillis();
|
||||
CachedWorld cachedWorld = Optional.ofNullable(WorldProvider.INSTANCE.getCurrentWorld()).map(w -> w.cache).orElse(null);
|
||||
ChunkProviderClient chunkProvider = Minecraft.getMinecraft().world.getChunkProvider();
|
||||
long startTime = System.nanoTime() / 1000000L;
|
||||
boolean slowPath = Baritone.settings().slowPath.get();
|
||||
long timeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS : Baritone.settings().pathTimeoutMS).<Long>get();
|
||||
long lastPrintout = 0;
|
||||
if (slowPath) {
|
||||
displayChatMessageRaw("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + timeout + "ms");
|
||||
}
|
||||
long timeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : timeout);
|
||||
//long lastPrintout = 0;
|
||||
int numNodes = 0;
|
||||
int numMovementsConsidered = 0;
|
||||
int numEmptyChunk = 0;
|
||||
boolean favoring = favoredPositions.isPresent();
|
||||
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
|
||||
double favorCoeff = Baritone.settings().backtrackCostFavoringCoefficient.get();
|
||||
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();
|
||||
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.currentTimeMillis() < timeoutTime) {
|
||||
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.nanoTime() / 1000000L - timeoutTime < 0 && !cancelRequested) {
|
||||
if (slowPath) {
|
||||
try {
|
||||
Thread.sleep(Baritone.settings().slowPathTimeDelayMS.<Long>get());
|
||||
@@ -92,39 +98,33 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
mostRecentConsidered = currentNode;
|
||||
BetterBlockPos currentNodePos = currentNode.pos;
|
||||
numNodes++;
|
||||
if (System.currentTimeMillis() > lastPrintout + 1000) {//print once a second
|
||||
System.out.println("searching... at " + currentNodePos + ", considered " + numNodes + " nodes so far");
|
||||
lastPrintout = System.currentTimeMillis();
|
||||
}
|
||||
if (goal.isInGoal(currentNodePos)) {
|
||||
currentlyRunning = null;
|
||||
displayChatMessageRaw("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, " + numMovementsConsidered + " movements considered");
|
||||
return Optional.of(new Path(startNode, currentNode, numNodes));
|
||||
}
|
||||
//long constructStart = System.nanoTime();
|
||||
Movement[] possibleMovements = getConnectedPositions(currentNodePos, calcContext);//movement that we could take that start at currentNodePos, in random order
|
||||
shuffle(possibleMovements);
|
||||
//long constructEnd = System.nanoTime();
|
||||
//System.out.println(constructEnd - constructStart);
|
||||
for (Movement movementToGetToNeighbor : possibleMovements) {
|
||||
if (movementToGetToNeighbor == null) {
|
||||
continue;
|
||||
}
|
||||
BetterBlockPos dest = (BetterBlockPos) movementToGetToNeighbor.getDest();
|
||||
boolean isPositionCached = false;
|
||||
if (WorldProvider.INSTANCE.getCurrentWorld() != null) {
|
||||
if (WorldProvider.INSTANCE.getCurrentWorld().cache.getBlock(dest) != null) {
|
||||
isPositionCached = true;
|
||||
int chunkX = currentNodePos.x >> 4;
|
||||
int chunkZ = currentNodePos.z >> 4;
|
||||
if (dest.x >> 4 != chunkX || dest.z >> 4 != chunkZ) {
|
||||
// only need to check if the destination is a loaded chunk if it's in a different chunk than the start of the movement
|
||||
if (chunkProvider.getLoadedChunk(chunkX, chunkZ) == null) {
|
||||
// see issue #106
|
||||
if (cachedWorld == null || !cachedWorld.isCached(dest)) {
|
||||
numEmptyChunk++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isPositionCached && Minecraft.getMinecraft().world.getChunk(dest) instanceof EmptyChunk) {
|
||||
numEmptyChunk++;
|
||||
continue;
|
||||
}
|
||||
//long costStart = System.nanoTime();
|
||||
// TODO cache cost
|
||||
double actionCost = movementToGetToNeighbor.getCost(calcContext);
|
||||
//long costEnd = System.nanoTime();
|
||||
//System.out.println(movementToGetToNeighbor.getClass() + "" + (costEnd - costStart));
|
||||
numMovementsConsidered++;
|
||||
if (actionCost >= ActionCosts.COST_INF) {
|
||||
continue;
|
||||
}
|
||||
@@ -162,6 +162,9 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
for (int i = 0; i < bestSoFar.length; i++) {
|
||||
double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i];
|
||||
if (heuristic < bestHeuristicSoFar[i]) {
|
||||
if (bestHeuristicSoFar[i] - heuristic < 0.01 && minimumImprovementRepropagation) {
|
||||
continue;
|
||||
}
|
||||
bestHeuristicSoFar[i] = heuristic;
|
||||
bestSoFar[i] = neighbor;
|
||||
}
|
||||
@@ -169,6 +172,13 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cancelRequested) {
|
||||
currentlyRunning = null;
|
||||
return Optional.empty();
|
||||
}
|
||||
System.out.println(numMovementsConsidered + " movements considered");
|
||||
System.out.println("Open set size: " + openSet.size());
|
||||
System.out.println((int) (numNodes * 1.0 / ((System.nanoTime() / 1000000L - startTime) / 1000F)) + " nodes per second");
|
||||
double bestDist = 0;
|
||||
for (int i = 0; i < bestSoFar.length; i++) {
|
||||
if (bestSoFar[i] == null) {
|
||||
@@ -179,18 +189,18 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
bestDist = dist;
|
||||
}
|
||||
if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
|
||||
displayChatMessageRaw("Took " + (System.currentTimeMillis() - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i]);
|
||||
displayChatMessageRaw("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i] + ", " + numMovementsConsidered + " movements considered");
|
||||
if (COEFFICIENTS[i] >= 3) {
|
||||
System.out.println("Warning: cost coefficient is greater than three! Probably means that");
|
||||
System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
|
||||
System.out.println("But I'm going to do it anyway, because yolo");
|
||||
}
|
||||
System.out.println("Path goes for " + dist + " blocks");
|
||||
System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
|
||||
currentlyRunning = null;
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], numNodes));
|
||||
}
|
||||
}
|
||||
displayChatMessageRaw("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + bestDist + " blocks =(");
|
||||
displayChatMessageRaw("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
|
||||
displayChatMessageRaw("No path found =(");
|
||||
currentlyRunning = null;
|
||||
return Optional.empty();
|
||||
|
@@ -17,13 +17,13 @@
|
||||
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.behavior.impl.PathingBehavior;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -42,7 +42,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
|
||||
protected final Goal goal;
|
||||
|
||||
protected final Map<BetterBlockPos, PathNode> map;
|
||||
private final Long2ObjectOpenHashMap<PathNode> map; // see issue #107
|
||||
|
||||
protected PathNode startNode;
|
||||
|
||||
@@ -52,6 +52,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
|
||||
private volatile boolean isFinished;
|
||||
|
||||
protected boolean cancelRequested;
|
||||
|
||||
/**
|
||||
* This is really complicated and hard to explain. I wrote a comment in the old version of MineBot but it was so
|
||||
* long it was easier as a Google Doc (because I could insert charts).
|
||||
@@ -67,19 +69,34 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
AbstractNodeCostSearch(BlockPos start, Goal goal) {
|
||||
this.start = new BetterBlockPos(start.getX(), start.getY(), start.getZ());
|
||||
this.goal = goal;
|
||||
this.map = new HashMap<>();
|
||||
this.map = new Long2ObjectOpenHashMap<>();
|
||||
}
|
||||
|
||||
public synchronized Optional<IPath> calculate() {
|
||||
public void cancel() {
|
||||
cancelRequested = true;
|
||||
}
|
||||
|
||||
public synchronized Optional<IPath> calculate(long timeout) {
|
||||
if (isFinished) {
|
||||
throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!");
|
||||
}
|
||||
Optional<IPath> path = calculate0();
|
||||
isFinished = true;
|
||||
return path;
|
||||
this.cancelRequested = false;
|
||||
try {
|
||||
Optional<IPath> path = calculate0(timeout);
|
||||
isFinished = true;
|
||||
return path;
|
||||
} catch (Exception e) {
|
||||
currentlyRunning = null;
|
||||
isFinished = true;
|
||||
if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException) e;
|
||||
} else {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Optional<IPath> calculate0();
|
||||
protected abstract Optional<IPath> calculate0(long timeout);
|
||||
|
||||
/**
|
||||
* Determines the distance squared from the specified node to the start
|
||||
@@ -105,7 +122,19 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
* @return The associated node
|
||||
*/
|
||||
protected PathNode getNodeAtPosition(BetterBlockPos pos) {
|
||||
return map.computeIfAbsent(pos, p -> new PathNode(p, goal));
|
||||
// see issue #107
|
||||
long hashCode = pos.hashCode;
|
||||
PathNode node = map.get(hashCode);
|
||||
if (node == null) {
|
||||
node = new PathNode(pos, goal);
|
||||
map.put(hashCode, node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
public static void forceCancel() {
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
currentlyRunning = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -39,7 +39,7 @@ public interface IPathFinder {
|
||||
*
|
||||
* @return The final path
|
||||
*/
|
||||
Optional<IPath> calculate();
|
||||
Optional<IPath> calculate(long timeout);
|
||||
|
||||
/**
|
||||
* Intended to be called concurrently with calculatePath from a different thread to tell if it's finished yet
|
||||
|
@@ -26,7 +26,7 @@ import java.util.Arrays;
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class BinaryHeapOpenSet implements IOpenSet {
|
||||
public final class BinaryHeapOpenSet implements IOpenSet {
|
||||
|
||||
/**
|
||||
* The initial capacity of the heap (2^10)
|
||||
@@ -52,6 +52,10 @@ public class BinaryHeapOpenSet implements IOpenSet {
|
||||
this.array = new PathNode[size];
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void insert(PathNode value) {
|
||||
if (size >= array.length - 1) {
|
||||
@@ -104,14 +108,13 @@ public class BinaryHeapOpenSet implements IOpenSet {
|
||||
int smallerChild = 2;
|
||||
double cost = val.combinedCost;
|
||||
do {
|
||||
int right = smallerChild + 1;
|
||||
PathNode smallerChildNode = array[smallerChild];
|
||||
double smallerChildCost = smallerChildNode.combinedCost;
|
||||
if (right <= size) {
|
||||
PathNode rightChildNode = array[right];
|
||||
if (smallerChild < size) {
|
||||
PathNode rightChildNode = array[smallerChild + 1];
|
||||
double rightChildCost = rightChildNode.combinedCost;
|
||||
if (smallerChildCost > rightChildCost) {
|
||||
smallerChild = right;
|
||||
smallerChild++;
|
||||
smallerChildCost = rightChildCost;
|
||||
smallerChildNode = rightChildNode;
|
||||
}
|
||||
@@ -124,8 +127,7 @@ public class BinaryHeapOpenSet implements IOpenSet {
|
||||
val.heapPosition = smallerChild;
|
||||
smallerChildNode.heapPosition = index;
|
||||
index = smallerChild;
|
||||
smallerChild = index << 1;
|
||||
} while (smallerChild <= size);
|
||||
} while ((smallerChild <<= 1) <= size);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@@ -22,10 +22,11 @@ import baritone.pathing.calc.PathNode;
|
||||
/**
|
||||
* A linked list implementation of an open set. This is the original implementation from MineBot.
|
||||
* It has incredibly fast insert performance, at the cost of O(n) removeLowest.
|
||||
* It sucks. BinaryHeapOpenSet results in more than 10x more nodes considered in 4 seconds.
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class LinkedListOpenSet implements IOpenSet {
|
||||
class LinkedListOpenSet implements IOpenSet {
|
||||
private Node first = null;
|
||||
|
||||
@Override
|
||||
|
@@ -17,25 +17,47 @@
|
||||
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
|
||||
/**
|
||||
* Don't get into the block, but get directly adjacent to it. Useful for chests.
|
||||
*
|
||||
* @author avecowa
|
||||
*/
|
||||
public class GoalGetToBlock extends GoalComposite {
|
||||
public class GoalGetToBlock implements Goal {
|
||||
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
|
||||
public GoalGetToBlock(BlockPos pos) {
|
||||
super(adjacentBlocks(pos));
|
||||
this.x = pos.getX();
|
||||
this.y = pos.getY();
|
||||
this.z = pos.getZ();
|
||||
}
|
||||
|
||||
private static BlockPos[] adjacentBlocks(BlockPos pos) {
|
||||
BlockPos[] sides = new BlockPos[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
sides[i] = pos.offset(EnumFacing.values()[i]);
|
||||
public BlockPos getGoalPos() {
|
||||
return new BetterBlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInGoal(BlockPos pos) {
|
||||
int xDiff = pos.getX() - this.x;
|
||||
int yDiff = pos.getY() - this.y;
|
||||
int zDiff = pos.getZ() - this.z;
|
||||
if (yDiff < 0) {
|
||||
yDiff++;
|
||||
}
|
||||
return sides;
|
||||
return Math.abs(xDiff) + Math.abs(yDiff) + Math.abs(zDiff) <= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic(BlockPos pos) {
|
||||
int xDiff = pos.getX() - this.x;
|
||||
int yDiff = pos.getY() - this.y;
|
||||
int zDiff = pos.getZ() - this.z;
|
||||
return GoalBlock.calculate(xDiff, yDiff, zDiff);
|
||||
}
|
||||
}
|
||||
|
64
src/main/java/baritone/pathing/goals/GoalNear.java
Normal file
64
src/main/java/baritone/pathing/goals/GoalNear.java
Normal file
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class GoalNear implements Goal {
|
||||
final int x;
|
||||
final int y;
|
||||
final int z;
|
||||
final int rangeSq;
|
||||
|
||||
public GoalNear(BlockPos pos, int range) {
|
||||
this.x = pos.getX();
|
||||
this.y = pos.getY();
|
||||
this.z = pos.getZ();
|
||||
this.rangeSq = range * range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInGoal(BlockPos pos) {
|
||||
int diffX = x - pos.getX();
|
||||
int diffY = y - pos.getY();
|
||||
int diffZ = z - pos.getZ();
|
||||
return diffX * diffX + diffY * diffY + diffZ * diffZ <= rangeSq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic(BlockPos pos) {
|
||||
int diffX = x - pos.getX();
|
||||
int diffY = y - pos.getY();
|
||||
int diffZ = z - pos.getZ();
|
||||
return GoalBlock.calculate(diffX, diffY, diffZ);
|
||||
}
|
||||
|
||||
public BlockPos getGoalPos() {
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GoalNear{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
", z=" + z +
|
||||
", rangeSq=" + rangeSq +
|
||||
'}';
|
||||
}
|
||||
}
|
@@ -68,6 +68,10 @@ public class GoalTwoBlocks implements Goal {
|
||||
return GoalBlock.calculate(xDiff, yDiff, zDiff);
|
||||
}
|
||||
|
||||
public BlockPos getGoalPos() {
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GoalTwoBlocks{x=" + x + ",y=" + y + ",z=" + z + "}";
|
||||
|
@@ -20,6 +20,7 @@ package baritone.pathing.goals;
|
||||
import baritone.Baritone;
|
||||
import baritone.utils.Utils;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
/**
|
||||
@@ -88,9 +89,9 @@ public class GoalXZ implements Goal {
|
||||
}
|
||||
|
||||
public static GoalXZ fromDirection(Vec3d origin, float yaw, double distance) {
|
||||
double theta = Utils.degToRad(yaw);
|
||||
double x = origin.x - Math.sin(theta) * distance;
|
||||
double z = origin.z + Math.cos(theta) * distance;
|
||||
float theta = (float) Utils.degToRad(yaw);
|
||||
double x = origin.x - MathHelper.sin(theta) * distance;
|
||||
double z = origin.z + MathHelper.cos(theta) * distance;
|
||||
return new GoalXZ((int) x, (int) z);
|
||||
}
|
||||
|
||||
|
@@ -24,7 +24,8 @@ public interface ActionCosts extends ActionCostsButOnlyTheOnesThatMakeMickeyDieI
|
||||
*/
|
||||
double WALK_ONE_BLOCK_COST = 20 / 4.317; // 4.633
|
||||
double WALK_ONE_IN_WATER_COST = 20 / 2.2;
|
||||
double WALK_ONE_OVER_SOUL_SAND_COST = WALK_ONE_IN_WATER_COST; // TODO issue #7
|
||||
double WALK_ONE_OVER_SOUL_SAND_COST = WALK_ONE_BLOCK_COST * 0.5; // 0.4 in BlockSoulSand but effectively about half
|
||||
double SPRINT_ONE_OVER_SOUL_SAND_COST = WALK_ONE_OVER_SOUL_SAND_COST / 0.75;
|
||||
double LADDER_UP_ONE_COST = 20 / 2.35;
|
||||
double LADDER_DOWN_ONE_COST = 20 / 3.0;
|
||||
double SNEAK_ONE_BLOCK_COST = 20 / 1.3;
|
||||
|
@@ -46,7 +46,6 @@ public class CalculationContext implements Helper {
|
||||
}
|
||||
|
||||
public CalculationContext(ToolSet toolSet) {
|
||||
player().setSprinting(true);
|
||||
this.toolSet = toolSet;
|
||||
this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(false);
|
||||
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) && !world().provider.isNether();
|
||||
|
@@ -21,18 +21,13 @@ import baritone.Baritone;
|
||||
import baritone.behavior.impl.LookBehavior;
|
||||
import baritone.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.pathing.movement.movements.MovementDownward;
|
||||
import baritone.pathing.movement.movements.MovementPillar;
|
||||
import baritone.pathing.movement.movements.MovementTraverse;
|
||||
import baritone.utils.*;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLadder;
|
||||
import net.minecraft.block.BlockVine;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -40,6 +35,8 @@ import static baritone.utils.InputOverrideHandler.Input;
|
||||
|
||||
public abstract class Movement implements Helper, MovementHelper {
|
||||
|
||||
protected static final EnumFacing[] HORIZONTALS = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST};
|
||||
|
||||
private MovementState currentState = new MovementState().setStatus(MovementStatus.PREPPING);
|
||||
|
||||
protected final BlockPos src;
|
||||
@@ -52,44 +49,34 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
protected final BlockPos[] positionsToBreak;
|
||||
|
||||
/**
|
||||
* The positions where we need to place a block before this movement can ensue
|
||||
* The position where we need to place a block before this movement can ensue
|
||||
*/
|
||||
protected final BlockPos[] positionsToPlace;
|
||||
protected final BlockPos positionToPlace;
|
||||
|
||||
private boolean didBreakLastTick;
|
||||
|
||||
private Double cost;
|
||||
|
||||
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak, BlockPos[] toPlace) {
|
||||
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak, BlockPos toPlace) {
|
||||
this.src = src;
|
||||
this.dest = dest;
|
||||
this.positionsToBreak = toBreak;
|
||||
this.positionsToPlace = toPlace;
|
||||
this.positionToPlace = toPlace;
|
||||
}
|
||||
|
||||
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak, BlockPos[] toPlace, Vec3d rotationTarget) {
|
||||
this(src, dest, toBreak, toPlace);
|
||||
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak) {
|
||||
this(src, dest, toBreak, null);
|
||||
}
|
||||
|
||||
public double getCost(CalculationContext context) {
|
||||
if (cost == null) {
|
||||
if (context == null)
|
||||
context = new CalculationContext();
|
||||
cost = calculateCost0(context);
|
||||
cost = calculateCost(context);
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
private double calculateCost0(CalculationContext context) {
|
||||
if (!(this instanceof MovementPillar) && !(this instanceof MovementTraverse) && !(this instanceof MovementDownward)) {
|
||||
Block fromDown = BlockStateInterface.get(src.down()).getBlock();
|
||||
if (fromDown instanceof BlockLadder || fromDown instanceof BlockVine) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
return calculateCost(context);
|
||||
}
|
||||
|
||||
protected abstract double calculateCost(CalculationContext context);
|
||||
|
||||
public double recalculateCost() {
|
||||
@@ -97,6 +84,10 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return getCost(null);
|
||||
}
|
||||
|
||||
public double calculateCostWithoutCaching() {
|
||||
return calculateCost(new CalculationContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the execution of the latest Movement
|
||||
* State, and offers a Status to the calling class.
|
||||
@@ -104,7 +95,6 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
* @return Status
|
||||
*/
|
||||
public MovementStatus update() {
|
||||
player().setSprinting(false);
|
||||
MovementState latestState = updateState(currentState);
|
||||
if (BlockStateInterface.isLiquid(playerFeet())) {
|
||||
latestState.setInput(Input.JUMP, true);
|
||||
@@ -159,7 +149,7 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
somethingInTheWay = true;
|
||||
Optional<Rotation> reachable = LookBehaviorUtils.reachable(blockPos);
|
||||
if (reachable.isPresent()) {
|
||||
player().inventory.currentItem = new ToolSet().getBestSlot(BlockStateInterface.get(blockPos));
|
||||
MovementHelper.switchToBestToolFor(BlockStateInterface.get(blockPos));
|
||||
state.setTarget(new MovementState.MovementTarget(reachable.get(), true)).setInput(Input.CLICK_LEFT, true);
|
||||
return false;
|
||||
}
|
||||
@@ -215,39 +205,53 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
}
|
||||
|
||||
public double getTotalHardnessOfBlocksToBreak(CalculationContext ctx) {
|
||||
/*
|
||||
double sum = 0;
|
||||
HashSet<BlockPos> toBreak = new HashSet();
|
||||
for (BlockPos positionsToBreak1 : positionsToBreak) {
|
||||
toBreak.add(positionsToBreak1);
|
||||
if (this instanceof ActionFall) {//if we are digging straight down, assume we have already broken the sand above us
|
||||
continue;
|
||||
}
|
||||
BlockPos tmp = positionsToBreak1.up();
|
||||
while (canFall(tmp)) {
|
||||
toBreak.add(tmp);
|
||||
tmp = tmp.up();
|
||||
}
|
||||
if (positionsToBreak.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
for (BlockPos pos : toBreak) {
|
||||
sum += getHardness(ts, Baritone.get(pos), pos);
|
||||
if (sum >= COST_INF) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (positionsToBreak.length == 1) {
|
||||
return MovementHelper.getMiningDurationTicks(ctx, positionsToBreak[0], true);
|
||||
}
|
||||
if (!Baritone.allowBreakOrPlace || !Baritone.hasThrowaway) {
|
||||
for (int i = 0; i < blocksToPlace.length; i++) {
|
||||
if (!canWalkOn(positionsToPlace[i])) {
|
||||
return COST_INF;
|
||||
int firstColumnX = positionsToBreak[0].getX();
|
||||
int firstColumnZ = positionsToBreak[0].getZ();
|
||||
int firstColumnMaxY = positionsToBreak[0].getY();
|
||||
int firstColumnMaximalIndex = 0;
|
||||
boolean hasSecondColumn = false;
|
||||
int secondColumnX = -1;
|
||||
int secondColumnZ = -1;
|
||||
int secondColumnMaxY = -1;
|
||||
int secondColumnMaximalIndex = -1;
|
||||
for (int i = 0; i < positionsToBreak.length; i++) {
|
||||
BlockPos pos = positionsToBreak[i];
|
||||
if (pos.getX() == firstColumnX && pos.getZ() == firstColumnZ) {
|
||||
if (pos.getY() > firstColumnMaxY) {
|
||||
firstColumnMaxY = pos.getY();
|
||||
firstColumnMaximalIndex = i;
|
||||
}
|
||||
} else {
|
||||
if (!hasSecondColumn || (pos.getX() == secondColumnX && pos.getZ() == secondColumnZ)) {
|
||||
if (hasSecondColumn) {
|
||||
if (pos.getY() > secondColumnMaxY) {
|
||||
secondColumnMaxY = pos.getY();
|
||||
secondColumnMaximalIndex = i;
|
||||
}
|
||||
} else {
|
||||
hasSecondColumn = true;
|
||||
secondColumnX = pos.getX();
|
||||
secondColumnZ = pos.getZ();
|
||||
secondColumnMaxY = pos.getY();
|
||||
secondColumnMaximalIndex = i;
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("I literally have no idea " + Arrays.asList(positionsToBreak));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
//^ the above implementation properly deals with falling blocks, TODO integrate
|
||||
}
|
||||
|
||||
double sum = 0;
|
||||
for (BlockPos pos : positionsToBreak) {
|
||||
sum += MovementHelper.getMiningDurationTicks(ctx, pos);
|
||||
for (int i = 0; i < positionsToBreak.length; i++) {
|
||||
sum += MovementHelper.getMiningDurationTicks(ctx, positionsToBreak[i], firstColumnMaximalIndex == i || secondColumnMaximalIndex == i);
|
||||
if (sum >= COST_INF) {
|
||||
return COST_INF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
@@ -274,6 +278,10 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return state;
|
||||
}
|
||||
|
||||
public BlockPos getDirection() {
|
||||
return getDest().subtract(getSrc());
|
||||
}
|
||||
|
||||
public List<BlockPos> toBreakCached = null;
|
||||
public List<BlockPos> toPlaceCached = null;
|
||||
public List<BlockPos> toWalkIntoCached = null;
|
||||
@@ -297,10 +305,8 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return toPlaceCached;
|
||||
}
|
||||
List<BlockPos> result = new ArrayList<>();
|
||||
for (BlockPos positionToBreak : positionsToPlace) {
|
||||
if (!MovementHelper.canWalkOn(positionToBreak)) {
|
||||
result.add(positionToBreak);
|
||||
}
|
||||
if (positionToPlace != null && !MovementHelper.canWalkOn(positionToPlace)) {
|
||||
result.add(positionToPlace);
|
||||
}
|
||||
toPlaceCached = result;
|
||||
return result;
|
||||
|
@@ -48,16 +48,14 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static boolean avoidBreaking(BlockPos pos, IBlockState state) {
|
||||
Block b = state.getBlock();
|
||||
BlockPos below = new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ());
|
||||
Block below = BlockStateInterface.get(new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ())).getBlock();
|
||||
return Blocks.ICE.equals(b) // ice becomes water, and water can mess up the path
|
||||
|| b instanceof BlockSilverfish // obvious reasons
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY() + 1, pos.getZ()))//don't break anything touching liquid on any side
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX() + 1, pos.getY(), pos.getZ()))
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX() - 1, pos.getY(), pos.getZ()))
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() + 1))
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() - 1))
|
||||
|| (!(b instanceof BlockLilyPad && BlockStateInterface.isWater(below)) && BlockStateInterface.isLiquid(below));//if it's a lilypad above water, it's ok to break, otherwise don't break if its liquid
|
||||
// TODO revisit this. why is it not okay to break non-lilypads that are right above water?
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,10 +91,18 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
IBlockState up = BlockStateInterface.get(pos.up());
|
||||
if (BlockStateInterface.isFlowing(state) || up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) {
|
||||
if (BlockStateInterface.isFlowing(state)) {
|
||||
return false; // Don't walk through flowing liquids
|
||||
}
|
||||
if (block instanceof BlockLiquid) {
|
||||
if (Baritone.settings().assumeWalkOnWater.get()) {
|
||||
return false;
|
||||
}
|
||||
IBlockState up = BlockStateInterface.get(pos.up());
|
||||
if (up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return block.isPassable(mc.world, pos);
|
||||
}
|
||||
|
||||
@@ -158,7 +164,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (facing == playerFacing) == open;
|
||||
return facing == playerFacing == open;
|
||||
}
|
||||
|
||||
static boolean avoidWalkingInto(Block block) {
|
||||
@@ -178,6 +184,9 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
*/
|
||||
static boolean canWalkOn(BlockPos pos, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR) {
|
||||
return false;
|
||||
}
|
||||
if (block instanceof BlockLadder || (Baritone.settings().allowVines.get() && block instanceof BlockVine)) { // TODO reconsider this
|
||||
return true;
|
||||
}
|
||||
@@ -187,12 +196,33 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
if (Blocks.FARMLAND.equals(block) || Blocks.GRASS_PATH.equals(block)) {
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockAir) {
|
||||
return false;
|
||||
if (Blocks.ENDER_CHEST.equals(block) || Blocks.CHEST.equals(block)) {
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockSlab) {
|
||||
if (!Baritone.settings().allowWalkOnBottomSlab.get()) {
|
||||
if (((BlockSlab) block).isDouble()) {
|
||||
return true;
|
||||
}
|
||||
return state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockStairs) {
|
||||
return true;
|
||||
}
|
||||
if (BlockStateInterface.isWater(block)) {
|
||||
Block up = BlockStateInterface.get(pos.up()).getBlock();
|
||||
return BlockStateInterface.isWater(up) || up instanceof BlockLilyPad; // You can only walk on water if there is water above it
|
||||
if (up instanceof BlockLilyPad) {
|
||||
return true;
|
||||
}
|
||||
if (BlockStateInterface.isFlowing(state)) {
|
||||
// the only scenario in which we can walk on flowing water is if it's under still water with jesus off
|
||||
return BlockStateInterface.isWater(up) && !Baritone.settings().assumeWalkOnWater.get();
|
||||
}
|
||||
// if assumeWalkOnWater is on, we can only walk on water if there isn't water above it
|
||||
// if assumeWalkOnWater is off, we can only walk on water if there is water above it
|
||||
return BlockStateInterface.isWater(up) ^ Baritone.settings().assumeWalkOnWater.get();
|
||||
}
|
||||
if (Blocks.MAGMA.equals(block)) {
|
||||
return false;
|
||||
@@ -208,12 +238,18 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return BlockStateInterface.get(pos).getBlock() instanceof BlockFalling;
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position) {
|
||||
IBlockState state = BlockStateInterface.get(position);
|
||||
return getMiningDurationTicks(context, position, state);
|
||||
static boolean canPlaceAgainst(BlockPos pos) {
|
||||
IBlockState state = BlockStateInterface.get(pos);
|
||||
// TODO isBlockNormalCube isn't the best check for whether or not we can place a block against it. e.g. glass isn't normalCube but we can place against it
|
||||
return state.isBlockNormalCube();
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position, IBlockState state) {
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position, boolean includeFalling) {
|
||||
IBlockState state = BlockStateInterface.get(position);
|
||||
return getMiningDurationTicks(context, position, state, includeFalling);
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position, IBlockState state, boolean includeFalling) {
|
||||
Block block = state.getBlock();
|
||||
if (!block.equals(Blocks.AIR) && !canWalkThrough(position, state)) { // TODO is the air check really necessary? Isn't air canWalkThrough?
|
||||
if (!context.allowBreak()) {
|
||||
@@ -223,9 +259,31 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return COST_INF;
|
||||
}
|
||||
double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table
|
||||
return m / context.getToolSet().getStrVsBlock(state, position);
|
||||
double strVsBlock = context.getToolSet().getStrVsBlock(state);
|
||||
if (strVsBlock < 0)
|
||||
return COST_INF;
|
||||
|
||||
double result = m / strVsBlock;
|
||||
if (includeFalling) {
|
||||
BlockPos up = position.up();
|
||||
IBlockState above = BlockStateInterface.get(up);
|
||||
if (above.getBlock() instanceof BlockFalling) {
|
||||
result += getMiningDurationTicks(context, up, above, true);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
return 0; // we won't actually mine it, so don't check fallings above
|
||||
}
|
||||
|
||||
static boolean isBottomSlab(IBlockState state) {
|
||||
return state.getBlock() instanceof BlockSlab
|
||||
&& !((BlockSlab) state.getBlock()).isDouble()
|
||||
&& state.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM;
|
||||
}
|
||||
|
||||
static boolean isBottomSlab(BlockPos pos) {
|
||||
return isBottomSlab(BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -304,22 +362,22 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
static Movement generateMovementFallOrDescend(BlockPos pos, BlockPos dest, CalculationContext calcContext) {
|
||||
// A
|
||||
//SA
|
||||
// B
|
||||
// A
|
||||
// B
|
||||
// C
|
||||
// D
|
||||
//if S is where you start, both of B need to be air for a movementfall
|
||||
//if S is where you start, B needs to be air for a movementfall
|
||||
//A is plausibly breakable by either descend or fall
|
||||
//C, D, etc determine the length of the fall
|
||||
for (int i = 1; i < 3; i++) {
|
||||
if (!canWalkThrough(dest.down(i))) {
|
||||
//if any of these two (B in the diagram) aren't air
|
||||
//have to do a descend, because fall is impossible
|
||||
|
||||
//this doesn't guarantee descend is possible, it just guarantees fall is impossible
|
||||
return new MovementDescend(pos, dest.down()); // standard move out by 1 and descend by 1
|
||||
}
|
||||
if (!canWalkThrough(dest.down(2))) {
|
||||
//if B in the diagram aren't air
|
||||
//have to do a descend, because fall is impossible
|
||||
|
||||
//this doesn't guarantee descend is possible, it just guarantees fall is impossible
|
||||
return new MovementDescend(pos, dest.down()); // standard move out by 1 and descend by 1
|
||||
}
|
||||
|
||||
// we're clear for a fall 2
|
||||
// let's see how far we can fall
|
||||
for (int fallHeight = 3; true; fallHeight++) {
|
||||
|
@@ -39,29 +39,10 @@ import java.util.Objects;
|
||||
|
||||
public class MovementAscend extends Movement {
|
||||
|
||||
private BlockPos[] against = new BlockPos[3];
|
||||
private int ticksWithoutPlacement = 0;
|
||||
|
||||
public MovementAscend(BlockPos src, BlockPos dest) {
|
||||
super(src, dest, new BlockPos[]{dest, src.up(2), dest.up()}, new BlockPos[]{dest.down()});
|
||||
|
||||
BlockPos placementLocation = positionsToPlace[0]; // dest.down()
|
||||
int i = 0;
|
||||
if (!placementLocation.north().equals(src))
|
||||
against[i++] = placementLocation.north();
|
||||
|
||||
if (!placementLocation.south().equals(src))
|
||||
against[i++] = placementLocation.south();
|
||||
|
||||
if (!placementLocation.east().equals(src))
|
||||
against[i++] = placementLocation.east();
|
||||
|
||||
if (!placementLocation.west().equals(src))
|
||||
against[i] = placementLocation.west();
|
||||
|
||||
// TODO: add ability to place against .down() as well as the cardinal directions
|
||||
// useful for when you are starting a staircase without anything to place against
|
||||
// Counterpoint to the above TODO ^ you should move then pillar instead of ascend
|
||||
super(src, dest, new BlockPos[]{dest, src.up(2), dest.up()}, dest.down());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -72,16 +53,34 @@ public class MovementAscend extends Movement {
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
IBlockState toPlace = BlockStateInterface.get(positionsToPlace[0]);
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0], toPlace)) {
|
||||
IBlockState srcDown = BlockStateInterface.get(src.down());
|
||||
if (srcDown.getBlock() == Blocks.LADDER || srcDown.getBlock() == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
// we can jump from soul sand, but not from a bottom slab
|
||||
boolean jumpingFromBottomSlab = MovementHelper.isBottomSlab(srcDown);
|
||||
IBlockState toPlace = BlockStateInterface.get(positionToPlace);
|
||||
boolean jumpingToBottomSlab = MovementHelper.isBottomSlab(toPlace);
|
||||
|
||||
if (jumpingFromBottomSlab && !jumpingToBottomSlab) {
|
||||
return COST_INF;// the only thing we can ascend onto from a bottom slab is another bottom slab
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(positionToPlace, toPlace)) {
|
||||
if (!context.hasThrowaway()) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!BlockStateInterface.isAir(toPlace) && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(positionsToPlace[0], toPlace)) {
|
||||
if (!BlockStateInterface.isAir(toPlace) && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(positionToPlace, toPlace)) {
|
||||
return COST_INF;
|
||||
}
|
||||
for (BlockPos against1 : against) {
|
||||
if (BlockStateInterface.get(against1).isBlockNormalCube()) {
|
||||
// TODO: add ability to place against .down() as well as the cardinal directions
|
||||
// useful for when you are starting a staircase without anything to place against
|
||||
// Counterpoint to the above TODO ^ you should move then pillar instead of ascend
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BlockPos against1 = positionToPlace.offset(HORIZONTALS[i]);
|
||||
if (against1.equals(src)) {
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canPlaceAgainst(against1)) {
|
||||
return JUMP_ONE_BLOCK_COST + WALK_ONE_BLOCK_COST + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context);
|
||||
}
|
||||
}
|
||||
@@ -108,9 +107,11 @@ public class MovementAscend extends Movement {
|
||||
// it's possible srcUp is AIR from the start, and srcUp2 is falling
|
||||
// and in that scenario, when we arrive and break srcUp2, that lets srcUp3 fall on us and suffocate us
|
||||
}
|
||||
// TODO maybe change behavior if src.down() is soul sand?
|
||||
double walk = WALK_ONE_BLOCK_COST;
|
||||
if (toPlace.getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
if (jumpingToBottomSlab && !jumpingFromBottomSlab) {
|
||||
return walk + getTotalHardnessOfBlocksToBreak(context); // we don't hit space we just walk into the slab
|
||||
}
|
||||
if (!jumpingToBottomSlab && toPlace.getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
walk *= WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST;
|
||||
}
|
||||
// we hit space immediately on entering this action
|
||||
@@ -129,9 +130,14 @@ public class MovementAscend extends Movement {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0])) {
|
||||
for (BlockPos anAgainst : against) {
|
||||
if (BlockStateInterface.get(anAgainst).isBlockNormalCube()) {
|
||||
IBlockState jumpingOnto = BlockStateInterface.get(positionToPlace);
|
||||
if (!MovementHelper.canWalkOn(positionToPlace, jumpingOnto)) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BlockPos anAgainst = positionToPlace.offset(HORIZONTALS[i]);
|
||||
if (anAgainst.equals(src)) {
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canPlaceAgainst(anAgainst)) {
|
||||
if (!MovementHelper.throwaway(true)) {//get ready to place a throwaway block
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
@@ -142,7 +148,7 @@ public class MovementAscend extends Movement {
|
||||
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
|
||||
|
||||
LookBehaviorUtils.getSelectedBlock().ifPresent(selectedBlock -> {
|
||||
if (Objects.equals(selectedBlock, anAgainst) && selectedBlock.offset(side).equals(positionsToPlace[0])) {
|
||||
if (Objects.equals(selectedBlock, anAgainst) && selectedBlock.offset(side).equals(positionToPlace)) {
|
||||
ticksWithoutPlacement++;
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
if (player().isSneaking()) {
|
||||
@@ -152,6 +158,8 @@ public class MovementAscend extends Movement {
|
||||
// After 20 ticks without placement, we might be standing in the way, move back
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);
|
||||
}
|
||||
} else {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true); // break whatever replaceable block is in the way
|
||||
}
|
||||
System.out.println("Trying to look at " + anAgainst + ", actually looking at" + selectedBlock);
|
||||
});
|
||||
@@ -161,6 +169,11 @@ public class MovementAscend extends Movement {
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
if (MovementHelper.isBottomSlab(jumpingOnto)) {
|
||||
if (!MovementHelper.isBottomSlab(src.down())) {
|
||||
return state; // don't jump while walking from a non double slab into a bottom slab
|
||||
}
|
||||
}
|
||||
|
||||
if (headBonkClear()) {
|
||||
return state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
|
@@ -25,15 +25,13 @@ import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLadder;
|
||||
import net.minecraft.block.BlockVine;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class MovementDescend extends Movement {
|
||||
|
||||
public MovementDescend(BlockPos start, BlockPos end) {
|
||||
super(start, end, new BlockPos[]{end.up(2), end.up(), end}, new BlockPos[]{end.down()});
|
||||
super(start, end, new BlockPos[]{end.up(2), end.up(), end}, end.down());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -44,18 +42,22 @@ public class MovementDescend extends Movement {
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0])) {
|
||||
Block fromDown = BlockStateInterface.get(src.down()).getBlock();
|
||||
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(positionToPlace)) {
|
||||
return COST_INF;
|
||||
}
|
||||
Block tmp1 = BlockStateInterface.get(dest).getBlock();
|
||||
if (tmp1 instanceof BlockLadder || tmp1 instanceof BlockVine) {
|
||||
if (tmp1 == Blocks.LADDER || tmp1 == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
// we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel)
|
||||
double walk = WALK_OFF_BLOCK_COST;
|
||||
if (BlockStateInterface.get(src.down()).getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
if (fromDown == Blocks.SOUL_SAND) {
|
||||
// use this ratio to apply the soul sand speed penalty to our 0.8 block distance
|
||||
walk *= WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST;
|
||||
walk = WALK_ONE_OVER_SOUL_SAND_COST;
|
||||
}
|
||||
return walk + Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST) + getTotalHardnessOfBlocksToBreak(context);
|
||||
}
|
||||
|
@@ -17,12 +17,13 @@
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockMagma;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -49,66 +50,52 @@ public class MovementDiagonal extends Movement {
|
||||
super(start, end, new BlockPos[]{dir1, dir1.up(), dir2, dir2.up(), end, end.up()}, new BlockPos[]{end.down()});
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
if (state.getStatus() != MovementState.MovementStatus.RUNNING)
|
||||
return state;
|
||||
|
||||
if (playerFeet().equals(dest)) {
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
if (!BlockStateInterface.isLiquid(playerFeet()) && Baritone.settings().allowSprint.get()) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
Block fromDown = BlockStateInterface.get(src.down()).getBlock();
|
||||
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!MovementHelper.canWalkThrough(positionsToBreak[4]) || !MovementHelper.canWalkThrough(positionsToBreak[5])) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState destWalkOn = BlockStateInterface.get(positionsToPlace[0]);
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0], destWalkOn)) {
|
||||
BlockPos destDown = dest.down();
|
||||
IBlockState destWalkOn = BlockStateInterface.get(destDown);
|
||||
if (!MovementHelper.canWalkOn(destDown, destWalkOn)) {
|
||||
return COST_INF;
|
||||
}
|
||||
double multiplier = WALK_ONE_BLOCK_COST;
|
||||
|
||||
// For either possible soul sand, that affects half of our walking
|
||||
if (destWalkOn.getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
if (BlockStateInterface.get(src.down()).getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
if (fromDown == Blocks.SOUL_SAND) {
|
||||
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
|
||||
if (BlockStateInterface.get(positionsToBreak[2].down()).getBlock() instanceof BlockMagma) {
|
||||
Block cuttingOver1 = BlockStateInterface.get(positionsToBreak[2].down()).getBlock();
|
||||
if (cuttingOver1 instanceof BlockMagma || BlockStateInterface.isLava(cuttingOver1)) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (BlockStateInterface.get(positionsToBreak[4].down()).getBlock() instanceof BlockMagma) {
|
||||
Block cuttingOver2 = BlockStateInterface.get(positionsToBreak[4].down()).getBlock();
|
||||
if (cuttingOver2 instanceof BlockMagma || BlockStateInterface.isLava(cuttingOver2)) {
|
||||
return COST_INF;
|
||||
}
|
||||
double optionA = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1]);
|
||||
double optionB = MovementHelper.getMiningDurationTicks(context, positionsToBreak[2]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[3]);
|
||||
IBlockState pb0 = BlockStateInterface.get(positionsToBreak[0]);
|
||||
IBlockState pb1 = BlockStateInterface.get(positionsToBreak[1]);
|
||||
IBlockState pb2 = BlockStateInterface.get(positionsToBreak[2]);
|
||||
IBlockState pb3 = BlockStateInterface.get(positionsToBreak[3]);
|
||||
double optionA = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0], pb0, false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1], pb1, true);
|
||||
double optionB = MovementHelper.getMiningDurationTicks(context, positionsToBreak[2], pb2, false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[3], pb3, true);
|
||||
if (optionA != 0 && optionB != 0) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (optionA == 0) {
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[2]))) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[3]))) {
|
||||
if (MovementHelper.avoidWalkingInto(pb2.getBlock()) || MovementHelper.avoidWalkingInto(pb3.getBlock())) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
if (optionB == 0) {
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[0]))) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[1]))) {
|
||||
if (MovementHelper.avoidWalkingInto(pb0.getBlock()) || MovementHelper.avoidWalkingInto(pb1.getBlock())) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
@@ -129,6 +116,23 @@ public class MovementDiagonal extends Movement {
|
||||
return multiplier * SQRT_2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
if (state.getStatus() != MovementState.MovementStatus.RUNNING)
|
||||
return state;
|
||||
|
||||
if (playerFeet().equals(dest)) {
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
if (!BlockStateInterface.isLiquid(playerFeet())) {
|
||||
state.setInput(InputOverrideHandler.Input.SPRINT, true);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean prepared(MovementState state) {
|
||||
return true;
|
||||
|
@@ -23,9 +23,8 @@ import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLadder;
|
||||
import net.minecraft.block.BlockVine;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class MovementDownward extends Movement {
|
||||
@@ -33,7 +32,7 @@ public class MovementDownward extends Movement {
|
||||
private int numTicks = 0;
|
||||
|
||||
public MovementDownward(BlockPos start, BlockPos end) {
|
||||
super(start, end, new BlockPos[]{end}, new BlockPos[0]);
|
||||
super(start, end, new BlockPos[]{end});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -49,11 +48,12 @@ public class MovementDownward extends Movement {
|
||||
}
|
||||
IBlockState d = BlockStateInterface.get(dest);
|
||||
Block td = d.getBlock();
|
||||
boolean ladder = td instanceof BlockLadder || td instanceof BlockVine;
|
||||
boolean ladder = td == Blocks.LADDER || td == Blocks.VINE;
|
||||
if (ladder) {
|
||||
return LADDER_DOWN_ONE_COST;
|
||||
} else {
|
||||
return FALL_N_BLOCKS_COST[1] + MovementHelper.getMiningDurationTicks(context, dest, d);
|
||||
// we're standing on it, while it might be block falling, it'll be air by the time we get here in the movement
|
||||
return FALL_N_BLOCKS_COST[1] + MovementHelper.getMiningDurationTicks(context, dest, d, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -25,7 +25,11 @@ import baritone.pathing.movement.MovementState;
|
||||
import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.utils.*;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -38,14 +42,22 @@ public class MovementFall extends Movement {
|
||||
private static final ItemStack STACK_BUCKET_EMPTY = new ItemStack(Items.BUCKET);
|
||||
|
||||
public MovementFall(BlockPos src, BlockPos dest) {
|
||||
super(src, dest, MovementFall.buildPositionsToBreak(src, dest), new BlockPos[]{dest.down()});
|
||||
super(src, dest, MovementFall.buildPositionsToBreak(src, dest));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0])) {
|
||||
Block fromDown = BlockStateInterface.get(src.down()).getBlock();
|
||||
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState fallOnto = BlockStateInterface.get(dest.down());
|
||||
if (!MovementHelper.canWalkOn(dest.down(), fallOnto)) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (MovementHelper.isBottomSlab(fallOnto)) {
|
||||
return COST_INF; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect
|
||||
}
|
||||
double placeBucketCost = 0.0;
|
||||
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > context.maxFallHeightNoWater()) {
|
||||
if (!context.hasWaterBucket()) {
|
||||
@@ -56,25 +68,29 @@ public class MovementFall extends Movement {
|
||||
}
|
||||
placeBucketCost = context.placeBlockCost();
|
||||
}
|
||||
double frontTwo = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1]);
|
||||
if (frontTwo >= COST_INF) {
|
||||
return COST_INF;
|
||||
double frontThree = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
frontThree += MovementHelper.getMiningDurationTicks(context, positionsToBreak[i], false);
|
||||
// don't include falling because we will check falling right after this, and if it's there it's COST_INF
|
||||
if (frontThree >= COST_INF) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
if (BlockStateInterface.get(positionsToBreak[0].up()).getBlock() instanceof BlockFalling) {
|
||||
return COST_INF;
|
||||
}
|
||||
for (int i = 2; i < positionsToBreak.length; i++) {
|
||||
for (int i = 3; i < positionsToBreak.length; i++) {
|
||||
// TODO is this the right check here?
|
||||
// MiningDurationTicks is all right, but shouldn't it be canWalkThrough instead?
|
||||
// Lilypads (i think?) are 0 ticks to mine, but they definitely cause fall damage
|
||||
// Same thing for falling through water... we can't actually do that
|
||||
// And falling through signs is possible, but they do have a mining duration, right?
|
||||
if (MovementHelper.getMiningDurationTicks(context, positionsToBreak[i]) > 0) {
|
||||
if (MovementHelper.getMiningDurationTicks(context, positionsToBreak[i], false) > 0) {
|
||||
//can't break while falling
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
return WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[positionsToBreak.length - 1] + placeBucketCost + frontTwo;
|
||||
return WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[positionsToBreak.length - 1] + placeBucketCost + frontThree;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,7 +102,7 @@ public class MovementFall extends Movement {
|
||||
BlockPos playerFeet = playerFeet();
|
||||
Rotation targetRotation = null;
|
||||
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) {
|
||||
if (!player().inventory.hasItemStack(STACK_BUCKET_WATER) || world().provider.isNether()) {
|
||||
if (!InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) || world().provider.isNether()) {
|
||||
state.setStatus(MovementStatus.UNREACHABLE);
|
||||
return state;
|
||||
}
|
||||
@@ -109,7 +125,7 @@ public class MovementFall extends Movement {
|
||||
}
|
||||
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 // lilypads
|
||||
|| BlockStateInterface.isWater(dest))) {
|
||||
if (BlockStateInterface.isWater(dest) && player().inventory.hasItemStack(STACK_BUCKET_EMPTY)) {
|
||||
if (BlockStateInterface.isWater(dest) && InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_EMPTY))) {
|
||||
player().inventory.currentItem = player().inventory.getSlotFor(STACK_BUCKET_EMPTY);
|
||||
if (player().motionY >= 0) {
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
|
@@ -28,14 +28,13 @@ import baritone.utils.Utils;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class MovementPillar extends Movement {
|
||||
private int numTicks = 0;
|
||||
|
||||
public MovementPillar(BlockPos start, BlockPos end) {
|
||||
super(start, end, new BlockPos[]{start.up(2)}, new BlockPos[]{start});
|
||||
super(start, end, new BlockPos[]{start.up(2)}, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,11 +47,16 @@ public class MovementPillar extends Movement {
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
Block fromDown = BlockStateInterface.get(src).getBlock();
|
||||
boolean ladder = fromDown instanceof BlockLadder || fromDown instanceof BlockVine;
|
||||
Block fromDownDown = BlockStateInterface.get(src.down()).getBlock();
|
||||
IBlockState fromDownDown = BlockStateInterface.get(src.down());
|
||||
if (!ladder) {
|
||||
if (fromDownDown instanceof BlockLadder || fromDownDown instanceof BlockVine) {
|
||||
if (fromDownDown.getBlock() instanceof BlockLadder || fromDownDown.getBlock() instanceof BlockVine) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (fromDownDown.getBlock() instanceof BlockSlab) {
|
||||
if (!((BlockSlab) fromDownDown.getBlock()).isDouble() && fromDownDown.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM) {
|
||||
return COST_INF; // can't pillar up from a bottom slab onto a non ladder
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!context.hasThrowaway() && !ladder) {
|
||||
return COST_INF;
|
||||
@@ -63,6 +67,9 @@ public class MovementPillar extends Movement {
|
||||
}
|
||||
}
|
||||
double hardness = getTotalHardnessOfBlocksToBreak(context);
|
||||
if (hardness >= COST_INF) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (hardness != 0) {
|
||||
Block tmp = BlockStateInterface.get(src.up(2)).getBlock();
|
||||
if (tmp instanceof BlockLadder || tmp instanceof BlockVine) {
|
||||
@@ -70,15 +77,22 @@ public class MovementPillar extends Movement {
|
||||
} else {
|
||||
BlockPos chkPos = src.up(3);
|
||||
IBlockState check = BlockStateInterface.get(chkPos);
|
||||
if (!MovementHelper.canWalkOn(chkPos, check) || MovementHelper.canWalkThrough(chkPos, check) || check.getBlock() instanceof BlockFalling) {//if the block above where we want to break is not a full block, don't do it
|
||||
// TODO why does canWalkThrough mean this action is COST_INF?
|
||||
// BlockFalling makes sense, and !canWalkOn deals with weird cases like if it were lava
|
||||
// but I don't understand why canWalkThrough makes it impossible
|
||||
return COST_INF;
|
||||
if (check.getBlock() instanceof BlockFalling) {
|
||||
// see MovementAscend's identical check for breaking a falling block above our head
|
||||
if (!(tmp instanceof BlockFalling) || !(BlockStateInterface.get(src.up(1)).getBlock() instanceof BlockFalling)) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
// this is commented because it may have had a purpose, but it's very unclear what it was. it's from the minebot era.
|
||||
//if (!MovementHelper.canWalkOn(chkPos, check) || MovementHelper.canWalkThrough(chkPos, check)) {//if the block above where we want to break is not a full block, don't do it
|
||||
// TODO why does canWalkThrough mean this action is COST_INF?
|
||||
// BlockFalling makes sense, and !canWalkOn deals with weird cases like if it were lava
|
||||
// but I don't understand why canWalkThrough makes it impossible
|
||||
// return COST_INF;
|
||||
//}
|
||||
}
|
||||
}
|
||||
if (fromDown instanceof BlockLiquid || fromDownDown instanceof BlockLiquid) {//can't pillar on water or in water
|
||||
if (fromDown instanceof BlockLiquid || fromDownDown.getBlock() instanceof BlockLiquid) {//can't pillar on water or in water
|
||||
return COST_INF;
|
||||
}
|
||||
if (ladder) {
|
||||
@@ -115,7 +129,7 @@ public class MovementPillar extends Movement {
|
||||
boolean vine = fromDown.getBlock() instanceof BlockVine;
|
||||
if (!ladder) {
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Utils.getBlockPosCenter(positionsToPlace[0]),
|
||||
Utils.getBlockPosCenter(positionToPlace),
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)), true));
|
||||
}
|
||||
|
||||
@@ -127,9 +141,12 @@ public class MovementPillar extends Movement {
|
||||
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
|
||||
}
|
||||
|
||||
if (playerFeet().equals(against.up()) || playerFeet().equals(dest))
|
||||
if (playerFeet().equals(against.up()) || playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
|
||||
}
|
||||
if (MovementHelper.isBottomSlab(src.down())) {
|
||||
state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
}
|
||||
/*
|
||||
if (thePlayer.getPosition0().getX() != from.getX() || thePlayer.getPosition0().getZ() != from.getZ()) {
|
||||
Baritone.moveTowardsBlock(from);
|
||||
|
@@ -17,7 +17,6 @@
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
@@ -38,30 +37,13 @@ import java.util.Objects;
|
||||
|
||||
public class MovementTraverse extends Movement {
|
||||
|
||||
private BlockPos[] against = new BlockPos[3];
|
||||
|
||||
/**
|
||||
* Did we have to place a bridge block or was it always there
|
||||
*/
|
||||
private boolean wasTheBridgeBlockAlwaysThere = true;
|
||||
|
||||
public MovementTraverse(BlockPos from, BlockPos to) {
|
||||
super(from, to, new BlockPos[]{to.up(), to}, new BlockPos[]{to.down()});
|
||||
int i = 0;
|
||||
|
||||
if (!to.north().equals(from))
|
||||
against[i++] = to.north().down();
|
||||
|
||||
if (!to.south().equals(from))
|
||||
against[i++] = to.south().down();
|
||||
|
||||
if (!to.east().equals(from))
|
||||
against[i++] = to.east().down();
|
||||
|
||||
if (!to.west().equals(from))
|
||||
against[i] = to.west().down();
|
||||
|
||||
//note: do NOT add ability to place against .down().down()
|
||||
super(from, to, new BlockPos[]{to.up(), to}, to.down());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -74,20 +56,26 @@ public class MovementTraverse extends Movement {
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
IBlockState pb0 = BlockStateInterface.get(positionsToBreak[0]);
|
||||
IBlockState pb1 = BlockStateInterface.get(positionsToBreak[1]);
|
||||
IBlockState destOn = BlockStateInterface.get(positionsToPlace[0]);
|
||||
if (MovementHelper.canWalkOn(positionsToPlace[0], destOn)) {//this is a walk, not a bridge
|
||||
IBlockState destOn = BlockStateInterface.get(positionToPlace);
|
||||
Block srcDown = BlockStateInterface.getBlock(src.down());
|
||||
if (MovementHelper.canWalkOn(positionToPlace, destOn)) {//this is a walk, not a bridge
|
||||
double WC = WALK_ONE_BLOCK_COST;
|
||||
if (BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock())) {
|
||||
WC = WALK_ONE_IN_WATER_COST;
|
||||
} else {
|
||||
if (Blocks.SOUL_SAND.equals(destOn.getBlock())) {
|
||||
if (destOn.getBlock() == Blocks.SOUL_SAND) {
|
||||
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
if (Blocks.SOUL_SAND.equals(BlockStateInterface.get(src.down()).getBlock())) {
|
||||
if (srcDown == Blocks.SOUL_SAND) {
|
||||
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
}
|
||||
if (MovementHelper.canWalkThrough(positionsToBreak[0], pb0) && MovementHelper.canWalkThrough(positionsToBreak[1], pb1)) {
|
||||
double hardness1 = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0], pb0, true);
|
||||
if (hardness1 >= COST_INF) {
|
||||
return COST_INF;
|
||||
}
|
||||
double hardness2 = MovementHelper.getMiningDurationTicks(context, positionsToBreak[1], pb1, false);
|
||||
if (hardness1 == 0 && hardness2 == 0) {
|
||||
if (WC == WALK_ONE_BLOCK_COST && context.canSprint()) {
|
||||
// If there's nothing in the way, and this isn't water or soul sand, and we aren't sneak placing
|
||||
// We can sprint =D
|
||||
@@ -95,28 +83,36 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
return WC;
|
||||
}
|
||||
// double hardness1 = blocksToBreak[0].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[0]);
|
||||
// double hardness2 = blocksToBreak[1].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[1]);
|
||||
// Out.log("Can't walk through " + blocksToBreak[0] + " (hardness" + hardness1 + ") or " + blocksToBreak[1] + " (hardness " + hardness2 + ")");
|
||||
return WC + getTotalHardnessOfBlocksToBreak(context);
|
||||
if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) {
|
||||
hardness1 *= 5;
|
||||
hardness2 *= 5;
|
||||
}
|
||||
return WC + hardness1 + hardness2;
|
||||
} else {//this is a bridge, so we need to place a block
|
||||
Block srcDown = BlockStateInterface.get(src.down()).getBlock();
|
||||
if (srcDown instanceof BlockLadder || srcDown instanceof BlockVine) {
|
||||
if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState pp0 = BlockStateInterface.get(positionsToPlace[0]);
|
||||
if (pp0.getBlock().equals(Blocks.AIR) || (!BlockStateInterface.isWater(pp0.getBlock()) && MovementHelper.isReplacable(positionsToPlace[0], pp0))) {
|
||||
if (destOn.getBlock().equals(Blocks.AIR) || MovementHelper.isReplacable(positionToPlace, destOn)) {
|
||||
boolean throughWater = BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock());
|
||||
if (BlockStateInterface.isWater(destOn.getBlock()) && throughWater) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!context.hasThrowaway()) {
|
||||
return COST_INF;
|
||||
}
|
||||
double WC = BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock()) ? WALK_ONE_IN_WATER_COST : WALK_ONE_BLOCK_COST;
|
||||
for (BlockPos against1 : against) {
|
||||
if (BlockStateInterface.get(against1).isBlockNormalCube()) {
|
||||
double WC = throughWater ? WALK_ONE_IN_WATER_COST : WALK_ONE_BLOCK_COST;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BlockPos against1 = dest.offset(HORIZONTALS[i]);
|
||||
if (against1.equals(src)) {
|
||||
continue;
|
||||
}
|
||||
against1 = against1.down();
|
||||
if (MovementHelper.canPlaceAgainst(against1)) {
|
||||
return WC + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context);
|
||||
}
|
||||
}
|
||||
if (Blocks.SOUL_SAND.equals(srcDown)) {
|
||||
return COST_INF; // can't sneak and backplace against soul sand =/
|
||||
if (srcDown == Blocks.SOUL_SAND || (srcDown instanceof BlockSlab && !((BlockSlab) srcDown).isDouble())) {
|
||||
return COST_INF; // can't sneak and backplace against soul sand or half slabs =/
|
||||
}
|
||||
WC = WC * SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST;//since we are placing, we are sneaking
|
||||
return WC + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context);
|
||||
@@ -132,6 +128,8 @@ public class MovementTraverse extends Movement {
|
||||
if (state.getStatus() != MovementState.MovementStatus.RUNNING)
|
||||
return state;
|
||||
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, false);
|
||||
|
||||
Block fd = BlockStateInterface.get(src.down()).getBlock();
|
||||
boolean ladder = fd instanceof BlockLadder || fd instanceof BlockVine;
|
||||
IBlockState pb0 = BlockStateInterface.get(positionsToBreak[0]);
|
||||
@@ -169,7 +167,7 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
}
|
||||
|
||||
boolean isTheBridgeBlockThere = MovementHelper.canWalkOn(positionsToPlace[0]) || ladder;
|
||||
boolean isTheBridgeBlockThere = MovementHelper.canWalkOn(positionToPlace) || ladder;
|
||||
BlockPos whereAmI = playerFeet();
|
||||
if (whereAmI.getY() != dest.getY() && !ladder) {
|
||||
displayChatMessageRaw("Wrong Y coordinate");
|
||||
@@ -184,11 +182,11 @@ public class MovementTraverse extends Movement {
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
if (wasTheBridgeBlockAlwaysThere && !BlockStateInterface.isLiquid(playerFeet()) && Baritone.settings().allowSprint.get()) {
|
||||
player().setSprinting(true);
|
||||
if (wasTheBridgeBlockAlwaysThere && !BlockStateInterface.isLiquid(playerFeet())) {
|
||||
state.setInput(InputOverrideHandler.Input.SPRINT, true);
|
||||
}
|
||||
Block destDown = BlockStateInterface.get(dest.down()).getBlock();
|
||||
if (ladder && (destDown instanceof BlockVine || destDown instanceof BlockLadder)) {
|
||||
if (whereAmI.getY() != dest.getY() && ladder && (destDown instanceof BlockVine || destDown instanceof BlockLadder)) {
|
||||
new MovementPillar(dest.down(), dest).updateState(state); // i'm sorry
|
||||
return state;
|
||||
}
|
||||
@@ -196,13 +194,29 @@ public class MovementTraverse extends Movement {
|
||||
return state;
|
||||
} else {
|
||||
wasTheBridgeBlockAlwaysThere = false;
|
||||
for (BlockPos against1 : against) {
|
||||
if (BlockStateInterface.get(against1).isBlockNormalCube()) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BlockPos against1 = dest.offset(HORIZONTALS[i]);
|
||||
if (against1.equals(src)) {
|
||||
continue;
|
||||
}
|
||||
against1 = against1.down();
|
||||
if (MovementHelper.canPlaceAgainst(against1)) {
|
||||
if (!MovementHelper.throwaway(true)) { // get ready to place a throwaway block
|
||||
displayChatMessageRaw("bb pls get me some blocks. dirt or cobble");
|
||||
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
|
||||
}
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
Block standingOn = BlockStateInterface.get(playerFeet().down()).getBlock();
|
||||
if (standingOn.equals(Blocks.SOUL_SAND) || standingOn instanceof BlockSlab) { // see issue #118
|
||||
double dist = Math.max(Math.abs(dest.getX() + 0.5 - player().posX), Math.abs(dest.getZ() + 0.5 - player().posZ));
|
||||
if (dist < 0.85) { // 0.5 + 0.3 + epsilon
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, false);
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);
|
||||
return state;
|
||||
}
|
||||
}
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_BACK, false);
|
||||
double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D;
|
||||
double faceY = (dest.getY() + against1.getY()) * 0.5D;
|
||||
double faceZ = (dest.getZ() + against1.getZ() + 1.0D) * 0.5D;
|
||||
@@ -210,7 +224,7 @@ public class MovementTraverse extends Movement {
|
||||
|
||||
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
|
||||
if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), against1) && Minecraft.getMinecraft().player.isSneaking()) {
|
||||
if (LookBehaviorUtils.getSelectedBlock().get().offset(side).equals(positionsToPlace[0])) {
|
||||
if (LookBehaviorUtils.getSelectedBlock().get().offset(side).equals(positionToPlace)) {
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
} else {
|
||||
// Out.gui("Wrong. " + side + " " + LookBehaviorUtils.getSelectedBlock().get().offset(side) + " " + positionsToPlace[0], Out.Mode.Debug);
|
||||
@@ -242,7 +256,7 @@ public class MovementTraverse extends Movement {
|
||||
return state;
|
||||
}
|
||||
// Out.log("Trying to look at " + goalLook + ", actually looking at" + Baritone.whatAreYouLookingAt());
|
||||
return state;
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
} else {
|
||||
MovementHelper.moveTowards(state, positionsToBreak[0]);
|
||||
return state;
|
||||
@@ -250,4 +264,15 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean prepared(MovementState state) {
|
||||
if (playerFeet().equals(src) || playerFeet().equals(src.down())) {
|
||||
Block block = BlockStateInterface.getBlock(src.down());
|
||||
if (block == Blocks.LADDER || block == Blocks.VINE) {
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
}
|
||||
}
|
||||
return super.prepared(state);
|
||||
}
|
||||
}
|
||||
|
@@ -18,10 +18,12 @@
|
||||
package baritone.pathing.path;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.TickEvent;
|
||||
import baritone.pathing.movement.ActionCosts;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.pathing.movement.*;
|
||||
import baritone.pathing.movement.movements.MovementDescend;
|
||||
import baritone.pathing.movement.movements.MovementDiagonal;
|
||||
import baritone.pathing.movement.movements.MovementFall;
|
||||
import baritone.pathing.movement.movements.MovementTraverse;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
@@ -42,8 +44,9 @@ import static baritone.pathing.movement.MovementState.MovementStatus.*;
|
||||
* @author leijurv
|
||||
*/
|
||||
public class PathExecutor implements Helper {
|
||||
private static final double MAX_MAX_DIST_FROM_PATH = 3;
|
||||
private static final double MAX_DIST_FROM_PATH = 2;
|
||||
private static final double MAX_TICKS_AWAY = 200; // ten seconds
|
||||
private static final double MAX_TICKS_AWAY = 200; // ten seconds. ok to decrease this, but it must be at least 110, see issue #102
|
||||
private final IPath path;
|
||||
private int pathPosition;
|
||||
private int ticksAway;
|
||||
@@ -128,6 +131,17 @@ public class PathExecutor implements Helper {
|
||||
} else {
|
||||
ticksAway = 0;
|
||||
}
|
||||
if (distanceFromPath > MAX_MAX_DIST_FROM_PATH) {
|
||||
if (!(path.movements().get(pathPosition) instanceof MovementFall)) { // might be midair
|
||||
if (pathPosition == 0 || !(path.movements().get(pathPosition - 1) instanceof MovementFall)) { // might have overshot the landing
|
||||
displayChatMessageRaw("too far from path");
|
||||
pathPosition = path.length() + 3;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
failed = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
//this commented block is literally cursed.
|
||||
/*Out.log(actions.get(pathPosition));
|
||||
if (pathPosition < actions.size() - 1) {//if there are two ActionBridges in a row and they are at right angles, walk diagonally. This makes it so you walk at 45 degrees along a zigzag path instead of doing inefficient zigging and zagging
|
||||
@@ -160,7 +174,7 @@ public class PathExecutor implements Helper {
|
||||
}
|
||||
}
|
||||
}*/
|
||||
long start = System.currentTimeMillis();
|
||||
long start = System.nanoTime() / 1000000L;
|
||||
for (int i = pathPosition - 10; i < pathPosition + 10; i++) {
|
||||
if (i >= 0 && i < path.movements().size()) {
|
||||
Movement m = path.movements().get(i);
|
||||
@@ -195,11 +209,25 @@ public class PathExecutor implements Helper {
|
||||
toWalkInto = newWalkInto;
|
||||
recalcBP = false;
|
||||
}
|
||||
long end = System.currentTimeMillis();
|
||||
long end = System.nanoTime() / 1000000L;
|
||||
if (end - start > 0) {
|
||||
//displayChatMessageRaw("Recalculating break and place took " + (end - start) + "ms");
|
||||
}
|
||||
Movement movement = path.movements().get(pathPosition);
|
||||
if (costEstimateIndex == null || costEstimateIndex != pathPosition) {
|
||||
costEstimateIndex = pathPosition;
|
||||
// do this only once, when the movement starts, and deliberately get the cost as cached when this path was calculated, not the cost as it is right now
|
||||
currentMovementInitialCostEstimate = movement.getCost(null);
|
||||
for (int i = 1; i < Baritone.settings().costVerificationLookahead.get() && pathPosition + i < path.length() - 1; i++) {
|
||||
if (path.movements().get(pathPosition + i).calculateCostWithoutCaching() >= ActionCosts.COST_INF) {
|
||||
displayChatMessageRaw("Something has changed in the world and a future movement has become impossible. Cancelling.");
|
||||
pathPosition = path.length() + 3;
|
||||
failed = true;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
double currentCost = movement.recalculateCost();
|
||||
if (currentCost >= ActionCosts.COST_INF) {
|
||||
displayChatMessageRaw("Something has changed in the world and this movement has become impossible. Cancelling.");
|
||||
@@ -208,10 +236,6 @@ public class PathExecutor implements Helper {
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
return true;
|
||||
}
|
||||
if (costEstimateIndex == null || costEstimateIndex != pathPosition) {
|
||||
costEstimateIndex = pathPosition;
|
||||
currentMovementInitialCostEstimate = currentCost; // do this only once, when the movement starts
|
||||
}
|
||||
MovementState.MovementStatus movementStatus = movement.update();
|
||||
if (movementStatus == UNREACHABLE || movementStatus == FAILED) {
|
||||
displayChatMessageRaw("Movement returns status " + movementStatus);
|
||||
@@ -228,6 +252,7 @@ public class PathExecutor implements Helper {
|
||||
onTick(event);
|
||||
return true;
|
||||
} else {
|
||||
sprintIfRequested();
|
||||
ticksOnCurrent++;
|
||||
if (ticksOnCurrent > currentMovementInitialCostEstimate + Baritone.settings().movementTimeoutTicks.get()) {
|
||||
// only fail if the total time has exceeded the initial estimate
|
||||
@@ -245,6 +270,59 @@ public class PathExecutor implements Helper {
|
||||
return false; // movement is in progress
|
||||
}
|
||||
|
||||
private void sprintIfRequested() {
|
||||
if (!new CalculationContext().canSprint()) {
|
||||
player().setSprinting(false);
|
||||
return;
|
||||
}
|
||||
if (Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown(mc.gameSettings.keyBindSprint)) {
|
||||
if (!player().isSprinting()) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
Movement movement = path.movements().get(pathPosition);
|
||||
if (movement instanceof MovementDescend && pathPosition < path.length() - 2) {
|
||||
Movement next = path.movements().get(pathPosition + 1);
|
||||
if (next instanceof MovementDescend) {
|
||||
if (next.getDirection().equals(movement.getDirection())) {
|
||||
if (playerFeet().equals(movement.getDest())) {
|
||||
pathPosition++;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
}
|
||||
if (!player().isSprinting()) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (next instanceof MovementTraverse) {
|
||||
if (next.getDirection().down().equals(movement.getDirection()) && MovementHelper.canWalkOn(next.getDest().down())) {
|
||||
if (playerFeet().equals(movement.getDest())) {
|
||||
pathPosition++;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
}
|
||||
if (!player().isSprinting()) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (next instanceof MovementDiagonal && Baritone.settings().allowOvershootDiagonalDescend.get()) {
|
||||
if (playerFeet().equals(movement.getDest())) {
|
||||
pathPosition++;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
}
|
||||
if (!player().isSprinting()) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
//displayChatMessageRaw("Turning off sprinting " + movement + " " + next + " " + movement.getDirection() + " " + next.getDirection().down() + " " + next.getDirection().down().equals(movement.getDirection()));
|
||||
}
|
||||
player().setSprinting(false);
|
||||
}
|
||||
|
||||
public int getPosition() {
|
||||
return pathPosition;
|
||||
}
|
||||
|
@@ -30,6 +30,8 @@ import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
public class BlockStateInterface implements Helper {
|
||||
|
||||
private static Chunk prev = null;
|
||||
|
||||
public static IBlockState get(BlockPos pos) { // wrappers for chunk caching capability
|
||||
|
||||
// Invalid vertical position
|
||||
@@ -37,8 +39,18 @@ public class BlockStateInterface implements Helper {
|
||||
return Blocks.AIR.getDefaultState();
|
||||
|
||||
if (!Baritone.settings().pathThroughCachedOnly.get()) {
|
||||
Chunk cached = prev;
|
||||
// there's great cache locality in block state lookups
|
||||
// generally it's within each movement
|
||||
// if it's the same chunk as last time
|
||||
// we can just skip the mc.world.getChunk lookup
|
||||
// which is a Long2ObjectOpenHashMap.get
|
||||
if (cached != null && cached.x == pos.getX() >> 4 && cached.z == pos.getZ() >> 4) {
|
||||
return cached.getBlockState(pos);
|
||||
}
|
||||
Chunk chunk = mc.world.getChunk(pos);
|
||||
if (chunk.isLoaded()) {
|
||||
prev = chunk;
|
||||
return chunk.getBlockState(pos);
|
||||
}
|
||||
}
|
||||
@@ -54,6 +66,10 @@ public class BlockStateInterface implements Helper {
|
||||
return Blocks.AIR.getDefaultState();
|
||||
}
|
||||
|
||||
public static void clearCachedChunk() {
|
||||
prev = null;
|
||||
}
|
||||
|
||||
public static Block getBlock(BlockPos pos) {
|
||||
return get(pos).getBlock();
|
||||
}
|
||||
|
@@ -19,24 +19,27 @@ package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.Settings;
|
||||
import baritone.api.event.events.ChatEvent;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.behavior.impl.FollowBehavior;
|
||||
import baritone.behavior.impl.MineBehavior;
|
||||
import baritone.behavior.impl.PathingBehavior;
|
||||
import baritone.chunk.ChunkPacker;
|
||||
import baritone.chunk.Waypoint;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.event.events.ChatEvent;
|
||||
import baritone.pathing.calc.AStarPathFinder;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.goals.*;
|
||||
import baritone.pathing.movement.ActionCosts;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ExampleBaritoneControl extends Behavior {
|
||||
public static ExampleBaritoneControl INSTANCE = new ExampleBaritoneControl();
|
||||
@@ -52,7 +55,9 @@ public class ExampleBaritoneControl extends Behavior {
|
||||
@Override
|
||||
public void onSendChatMessage(ChatEvent event) {
|
||||
if (!Baritone.settings().chatControl.get()) {
|
||||
return;
|
||||
if (!Baritone.settings().removePrefix.get()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
String msg = event.getMessage();
|
||||
if (Baritone.settings().prefix.get()) {
|
||||
@@ -99,16 +104,30 @@ public class ExampleBaritoneControl extends Behavior {
|
||||
return;
|
||||
}
|
||||
if (msg.equals("path")) {
|
||||
PathingBehavior.INSTANCE.path();
|
||||
if (!PathingBehavior.INSTANCE.path()) {
|
||||
if (PathingBehavior.INSTANCE.getGoal() == null) {
|
||||
displayChatMessageRaw("No goal.");
|
||||
} else {
|
||||
displayChatMessageRaw("Currently executing a path. Please cancel it first.");
|
||||
}
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
if (msg.toLowerCase().equals("cancel")) {
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
FollowBehavior.INSTANCE.cancel();
|
||||
MineBehavior.INSTANCE.cancel();
|
||||
event.cancel();
|
||||
displayChatMessageRaw("ok canceled");
|
||||
return;
|
||||
}
|
||||
if (msg.toLowerCase().equals("forcecancel")) {
|
||||
AbstractNodeCostSearch.forceCancel();
|
||||
event.cancel();
|
||||
displayChatMessageRaw("ok force canceled");
|
||||
return;
|
||||
}
|
||||
if (msg.toLowerCase().equals("invert")) {
|
||||
Goal goal = PathingBehavior.INSTANCE.getGoal();
|
||||
BlockPos runAwayFrom;
|
||||
@@ -127,7 +146,21 @@ public class ExampleBaritoneControl extends Behavior {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
PathingBehavior.INSTANCE.path();
|
||||
if (!PathingBehavior.INSTANCE.path()) {
|
||||
displayChatMessageRaw("Currently executing a path. Please cancel it first.");
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
if (msg.toLowerCase().equals("follow")) {
|
||||
Optional<Entity> entity = MovementHelper.whatEntityAmILookingAt();
|
||||
if (!entity.isPresent()) {
|
||||
displayChatMessageRaw("You aren't looking at an entity bruh");
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
FollowBehavior.INSTANCE.follow(entity.get());
|
||||
displayChatMessageRaw("Following " + entity.get());
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
@@ -157,28 +190,16 @@ public class ExampleBaritoneControl extends Behavior {
|
||||
return;
|
||||
}
|
||||
if (msg.toLowerCase().startsWith("mine")) {
|
||||
String blockType = msg.toLowerCase().substring(4).trim();
|
||||
List<BlockPos> locs = new ArrayList<>(WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(blockType, 1, 1));
|
||||
if (locs.isEmpty()) {
|
||||
displayChatMessageRaw("No locations known");
|
||||
event.cancel();
|
||||
return;
|
||||
String[] blockTypes = msg.toLowerCase().substring(4).trim().split(" ");
|
||||
for (String s : blockTypes) {
|
||||
if (ChunkPacker.stringToBlock(s) == null) {
|
||||
displayChatMessageRaw(s + " isn't a valid block name");
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
BlockPos playerFeet = playerFeet();
|
||||
locs.sort(Comparator.comparingDouble(playerFeet::distanceSq));
|
||||
|
||||
// remove any that are within loaded chunks that aren't actually what we want
|
||||
locs.removeAll(locs.stream()
|
||||
.filter(pos -> !(world().getChunk(pos) instanceof EmptyChunk))
|
||||
.filter(pos -> !ChunkPacker.blockToString(BlockStateInterface.get(pos).getBlock()).equalsIgnoreCase(blockType))
|
||||
.collect(Collectors.toList()));
|
||||
|
||||
if (locs.size() > 30) {
|
||||
displayChatMessageRaw("Pathing to any of closest 30");
|
||||
locs = locs.subList(0, 30);
|
||||
}
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalTwoBlocks::new).toArray(Goal[]::new)));
|
||||
PathingBehavior.INSTANCE.path();
|
||||
MineBehavior.INSTANCE.mine(blockTypes);
|
||||
displayChatMessageRaw("Started mining blocks of type " + Arrays.toString(blockTypes));
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
@@ -195,7 +216,7 @@ public class ExampleBaritoneControl extends Behavior {
|
||||
// for example, "show deaths"
|
||||
waypointType = waypointType.substring(0, waypointType.length() - 1);
|
||||
}
|
||||
Waypoint.Tag tag = Waypoint.TAG_MAP.get(waypointType);
|
||||
Waypoint.Tag tag = Waypoint.Tag.fromString(waypointType);
|
||||
if (tag == null) {
|
||||
displayChatMessageRaw("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
|
||||
event.cancel();
|
||||
@@ -214,14 +235,26 @@ public class ExampleBaritoneControl extends Behavior {
|
||||
}
|
||||
if (msg.toLowerCase().startsWith("goto")) {
|
||||
String waypointType = msg.toLowerCase().substring(4).trim();
|
||||
if (waypointType.endsWith("s")) {
|
||||
if (waypointType.endsWith("s") && Waypoint.Tag.fromString(waypointType.substring(0, waypointType.length() - 1)) != null) {
|
||||
// for example, "show deaths"
|
||||
waypointType = waypointType.substring(0, waypointType.length() - 1);
|
||||
}
|
||||
Waypoint.Tag tag = Waypoint.TAG_MAP.get(waypointType);
|
||||
Waypoint.Tag tag = Waypoint.Tag.fromString(waypointType);
|
||||
if (tag == null) {
|
||||
displayChatMessageRaw("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
|
||||
String mining = waypointType;
|
||||
//displayChatMessageRaw("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
|
||||
event.cancel();
|
||||
if (ChunkPacker.stringToBlock(mining) == null) {
|
||||
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
||||
return;
|
||||
}
|
||||
List<BlockPos> locs = MineBehavior.scanFor(Arrays.asList(mining), 64);
|
||||
if (locs.isEmpty()) {
|
||||
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
||||
return;
|
||||
}
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new)));
|
||||
PathingBehavior.INSTANCE.path();
|
||||
return;
|
||||
}
|
||||
Waypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().waypoints.getMostRecentByTag(tag);
|
||||
@@ -232,7 +265,9 @@ public class ExampleBaritoneControl extends Behavior {
|
||||
}
|
||||
Goal goal = new GoalBlock(waypoint.location);
|
||||
PathingBehavior.INSTANCE.setGoal(goal);
|
||||
PathingBehavior.INSTANCE.path();
|
||||
if (!PathingBehavior.INSTANCE.path()) {
|
||||
displayChatMessageRaw("Currently executing a path. Please cancel it first.");
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
@@ -286,7 +321,7 @@ public class ExampleBaritoneControl extends Behavior {
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
List<Settings.Setting<Boolean>> toggleable = Baritone.settings().getByValueType(Boolean.class);
|
||||
List<Settings.Setting<Boolean>> toggleable = Baritone.settings().getAllValuesByType(Boolean.class);
|
||||
for (Settings.Setting<Boolean> setting : toggleable) {
|
||||
if (msg.equalsIgnoreCase(setting.getName())) {
|
||||
setting.value ^= true;
|
||||
|
@@ -18,6 +18,7 @@
|
||||
package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.block.BlockSlab;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
@@ -33,7 +34,13 @@ import net.minecraft.util.text.TextFormatting;
|
||||
*/
|
||||
public interface Helper {
|
||||
|
||||
ITextComponent MESSAGE_PREFIX = new TextComponentString("§5[§dBaritone§5]§7");
|
||||
ITextComponent MESSAGE_PREFIX = new TextComponentString(String.format(
|
||||
"%s[%sBaritone%s]%s",
|
||||
TextFormatting.DARK_PURPLE,
|
||||
TextFormatting.LIGHT_PURPLE,
|
||||
TextFormatting.DARK_PURPLE,
|
||||
TextFormatting.GRAY
|
||||
));
|
||||
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
@@ -47,10 +54,11 @@ public interface Helper {
|
||||
|
||||
default BlockPos playerFeet() {
|
||||
// TODO find a better way to deal with soul sand!!!!!
|
||||
return new BlockPos(player().posX, player().posY + 0.1251, player().posZ);
|
||||
/*if (BlockStateInterface.get(feet).getBlock().equals(Blocks.SOUL_SAND) && player().posY > feet.getY() + 0.874999) {
|
||||
BlockPos feet = new BlockPos(player().posX, player().posY + 0.1251, player().posZ);
|
||||
if (BlockStateInterface.get(feet).getBlock() instanceof BlockSlab) {
|
||||
return feet.up();
|
||||
}*/
|
||||
}
|
||||
return feet;
|
||||
}
|
||||
|
||||
default Vec3d playerFeetAsVec() {
|
||||
|
@@ -34,6 +34,7 @@ import net.minecraft.entity.player.EntityPlayer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collection;
|
||||
@@ -188,7 +189,7 @@ public final class PathRenderer implements Helper {
|
||||
maxX = goalPos.getX() + 1 - 0.002 - renderPosX;
|
||||
minZ = goalPos.getZ() + 0.002 - renderPosZ;
|
||||
maxZ = goalPos.getZ() + 1 - 0.002 - renderPosZ;
|
||||
double y = Math.sin((System.currentTimeMillis() % 2000L) / 2000F * Math.PI * 2);
|
||||
double y = MathHelper.sin((float) (((float) (System.nanoTime() / 1000000L) % 2000L) / 2000F * Math.PI * 2));
|
||||
y1 = 1 + y + goalPos.getY() - renderPosY;
|
||||
y2 = 1 - y + goalPos.getY() - renderPosY;
|
||||
minY = goalPos.getY() - renderPosY;
|
||||
|
@@ -18,6 +18,9 @@
|
||||
package baritone.utils;
|
||||
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import static baritone.behavior.impl.LookBehaviorUtils.calcVec3dFromRotation;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -44,4 +47,16 @@ public final class RayTraceUtils implements Helper {
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static RayTraceResult rayTraceTowards(Rotation rotation) {
|
||||
double blockReachDistance = mc.playerController.getBlockReachDistance();
|
||||
Vec3d start = mc.player.getPositionEyes(1.0F);
|
||||
Vec3d direction = calcVec3dFromRotation(rotation);
|
||||
Vec3d end = start.add(
|
||||
direction.x * blockReachDistance,
|
||||
direction.y * blockReachDistance,
|
||||
direction.z * blockReachDistance
|
||||
);
|
||||
return mc.world.rayTraceBlocks(start, end, false, false, true);
|
||||
}
|
||||
}
|
||||
|
@@ -18,92 +18,33 @@
|
||||
package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.event.events.ItemSlotEvent;
|
||||
import baritone.event.listener.AbstractGameEventListener;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemAir;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.init.Enchantments;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemTool;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A cached list of the best tools on the hotbar for any block
|
||||
*
|
||||
* @author avecowa, Brady
|
||||
* @author avecowa, Brady, leijurv
|
||||
*/
|
||||
public class ToolSet implements Helper {
|
||||
|
||||
/**
|
||||
* Instance of the internal event listener used to hook into Baritone's event bus
|
||||
*/
|
||||
private static final InternalEventListener INTERNAL_EVENT_LISTENER = new InternalEventListener();
|
||||
|
||||
static {
|
||||
Baritone.INSTANCE.getGameEventHandler().registerEventListener(INTERNAL_EVENT_LISTENER);
|
||||
}
|
||||
|
||||
/**
|
||||
* A list of tools on the hotbar that should be considered.
|
||||
* Note that if there are no tools on the hotbar this list will still have one (null) entry.
|
||||
*/
|
||||
private List<ItemTool> tools;
|
||||
|
||||
/**
|
||||
* A mapping from the tools array to what hotbar slots the tool is actually in.
|
||||
* tools.get(i) will be on your hotbar in slot slots.get(i)
|
||||
*/
|
||||
private List<Byte> slots;
|
||||
|
||||
/**
|
||||
* A mapping from a block to which tool index is best for it.
|
||||
* The values in this map are *not* hotbar slots indexes, they need to be looked up in slots
|
||||
* in order to be converted into hotbar slots.
|
||||
*/
|
||||
private Map<Block, Byte> slotCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* A cache mapping a {@link IBlockState} to how long it will take to break
|
||||
* A cache mapping a {@link Block} to how long it will take to break
|
||||
* with this toolset, given the optimum tool is used.
|
||||
*/
|
||||
private Map<IBlockState, Double> breakStrengthCache = new HashMap<>();
|
||||
private Map<Block, Double> breakStrengthCache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create a toolset from the current player's inventory (but don't calculate any hardness values just yet)
|
||||
*/
|
||||
public ToolSet() {
|
||||
EntityPlayerSP p = Minecraft.getMinecraft().player;
|
||||
NonNullList<ItemStack> inv = p.inventory.mainInventory;
|
||||
tools = new ArrayList<>();
|
||||
slots = new ArrayList<>();
|
||||
boolean fnull = false;
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
if (!fnull || ((!(inv.get(i).getItem() instanceof ItemAir)) && inv.get(i).getItem() instanceof ItemTool)) {
|
||||
tools.add(inv.get(i).getItem() instanceof ItemTool ? (ItemTool) inv.get(i).getItem() : null);
|
||||
slots.add(i);
|
||||
fnull |= (inv.get(i).getItem() instanceof ItemAir) || (!inv.get(i).getItem().isDamageable());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A caching wrapper around getBestToolIndex
|
||||
*
|
||||
* @param state the blockstate to be mined
|
||||
* @return get which tool on the hotbar is best for mining it
|
||||
*/
|
||||
public Item getBestTool(IBlockState state) {
|
||||
return tools.get(slotCache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state)));
|
||||
}
|
||||
public ToolSet() {}
|
||||
|
||||
/**
|
||||
* Calculate which tool on the hotbar is best for mining
|
||||
@@ -111,15 +52,11 @@ public class ToolSet implements Helper {
|
||||
* @param b the blockstate to be mined
|
||||
* @return a byte indicating the index in the tools array that worked best
|
||||
*/
|
||||
private byte getBestToolIndex(IBlockState b) {
|
||||
public byte getBestSlot(IBlockState b) {
|
||||
byte best = 0;
|
||||
float value = -1;
|
||||
for (byte i = 0; i < tools.size(); i++) {
|
||||
Item item = tools.get(i);
|
||||
if (item == null)
|
||||
continue;
|
||||
|
||||
float v = item.getDestroySpeed(new ItemStack(item), b);
|
||||
double value = -1;
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
double v = calculateStrVsBlock(i, b);
|
||||
if (v > value || value == -1) {
|
||||
value = v;
|
||||
best = i;
|
||||
@@ -128,62 +65,65 @@ public class ToolSet implements Helper {
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get which hotbar slot should be selected for fastest mining
|
||||
*
|
||||
* @param state the blockstate to be mined
|
||||
* @return a byte indicating which hotbar slot worked best
|
||||
*/
|
||||
public byte getBestSlot(IBlockState state) {
|
||||
return slots.get(slotCache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Using the best tool on the hotbar, how long would it take to mine this block
|
||||
*
|
||||
* @param state the blockstate to be mined
|
||||
* @param pos the blockpos to be mined
|
||||
* @return how long it would take in ticks
|
||||
*/
|
||||
public double getStrVsBlock(IBlockState state, BlockPos pos) {
|
||||
return this.breakStrengthCache.computeIfAbsent(state, s -> calculateStrVsBlock(s, pos));
|
||||
public double getStrVsBlock(IBlockState state) {
|
||||
return this.breakStrengthCache.computeIfAbsent(state.getBlock(), b -> calculateStrVsBlock(getBestSlot(state), state));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates how long would it take to mine the specified block given the best tool
|
||||
* in this toolset is used.
|
||||
* in this toolset is used. A negative value is returned if the specified block is unbreakable.
|
||||
*
|
||||
* @param state the blockstate to be mined
|
||||
* @param pos the blockpos to be mined
|
||||
* @return how long it would take in ticks
|
||||
*/
|
||||
private double calculateStrVsBlock(IBlockState state, BlockPos pos) {
|
||||
private double calculateStrVsBlock(byte slot, IBlockState state) {
|
||||
// Calculate the slot with the best item
|
||||
byte slot = this.getBestSlot(state);
|
||||
ItemStack contents = player().inventory.getStackInSlot(slot);
|
||||
|
||||
INTERNAL_EVENT_LISTENER.setOverrideSlot(slot);
|
||||
float blockHard = state.getBlockHardness(null, null);
|
||||
if (blockHard < 0)
|
||||
return -1;
|
||||
|
||||
// Calculate the relative hardness of the block to the player
|
||||
float hardness = state.getPlayerRelativeBlockHardness(player(), world(), pos);
|
||||
|
||||
// Restore the old slot
|
||||
INTERNAL_EVENT_LISTENER.setOverrideSlot(-1);
|
||||
|
||||
return hardness;
|
||||
}
|
||||
|
||||
private static final class InternalEventListener implements AbstractGameEventListener {
|
||||
|
||||
private int overrideSlot;
|
||||
|
||||
@Override
|
||||
public void onQueryItemSlotForBlocks(ItemSlotEvent event) {
|
||||
if (this.overrideSlot >= 0)
|
||||
event.setSlot(this.overrideSlot);
|
||||
float speed = contents.getDestroySpeed(state);
|
||||
if (speed > 1) {
|
||||
int effLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.EFFICIENCY, contents);
|
||||
if (effLevel > 0 && !contents.isEmpty()) {
|
||||
speed += effLevel * effLevel + 1;
|
||||
}
|
||||
}
|
||||
|
||||
final void setOverrideSlot(int overrideSlot) {
|
||||
this.overrideSlot = overrideSlot;
|
||||
if (Baritone.settings().considerPotionEffects.get()) {
|
||||
if (player().isPotionActive(MobEffects.HASTE)) {
|
||||
speed *= 1 + (player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
|
||||
}
|
||||
if (player().isPotionActive(MobEffects.MINING_FATIGUE)) {
|
||||
switch (player().getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) {
|
||||
case 0:
|
||||
speed *= 0.3;
|
||||
break;
|
||||
case 1:
|
||||
speed *= 0.09;
|
||||
break;
|
||||
case 2:
|
||||
speed *= 0.0027;
|
||||
break;
|
||||
default:
|
||||
speed *= 0.00081;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
speed /= blockHard;
|
||||
if (state.getMaterial().isToolNotRequired() || (!contents.isEmpty() && contents.canHarvestBlock(state))) {
|
||||
return speed / 30;
|
||||
} else {
|
||||
return speed / 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -54,9 +54,9 @@ public final class Utils {
|
||||
*/
|
||||
public static Rotation calcRotationFromVec3d(Vec3d orig, Vec3d dest) {
|
||||
double[] delta = {orig.x - dest.x, orig.y - dest.y, orig.z - dest.z};
|
||||
double yaw = Math.atan2(delta[0], -delta[2]);
|
||||
double yaw = MathHelper.atan2(delta[0], -delta[2]);
|
||||
double dist = Math.sqrt(delta[0] * delta[0] + delta[2] * delta[2]);
|
||||
double pitch = Math.atan2(delta[1], dist);
|
||||
double pitch = MathHelper.atan2(delta[1], dist);
|
||||
return new Rotation(
|
||||
(float) radToDeg(yaw),
|
||||
(float) radToDeg(pitch)
|
||||
|
@@ -15,11 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins.accessor;
|
||||
|
||||
import net.minecraft.world.chunk.storage.AnvilChunkLoader;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
package baritone.utils.accessor;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -27,8 +23,7 @@ import java.io.File;
|
||||
* @author Brady
|
||||
* @since 8/4/2018 11:36 AM
|
||||
*/
|
||||
@Mixin(AnvilChunkLoader.class)
|
||||
public interface IAnvilChunkLoader {
|
||||
|
||||
@Accessor File getChunkSaveLocation();
|
||||
File getChunkSaveLocation();
|
||||
}
|
@@ -15,19 +15,15 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins.accessor;
|
||||
package baritone.utils.accessor;
|
||||
|
||||
import net.minecraft.world.chunk.storage.IChunkLoader;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/4/2018 11:33 AM
|
||||
*/
|
||||
@Mixin(ChunkProviderServer.class)
|
||||
public interface IChunkProviderServer {
|
||||
|
||||
@Accessor IChunkLoader getChunkLoader();
|
||||
IChunkLoader getChunkLoader();
|
||||
}
|
@@ -26,11 +26,11 @@ import net.minecraft.util.math.Vec3i;
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class BetterBlockPos extends BlockPos {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final int hashCode;
|
||||
public final class BetterBlockPos extends BlockPos {
|
||||
public final int x;
|
||||
public final int y;
|
||||
public final int z;
|
||||
public final long hashCode;
|
||||
|
||||
public BetterBlockPos(int x, int y, int z) {
|
||||
super(x, y, z);
|
||||
@@ -48,10 +48,10 @@ public class BetterBlockPos extends BlockPos {
|
||||
*
|
||||
* That's why we grab out the X, Y, Z and calculate our own hashcode
|
||||
*/
|
||||
int hash = 3241;
|
||||
hash = 3457689 * hash + x;
|
||||
hash = 8734625 * hash + y;
|
||||
hash = 2873465 * hash + z;
|
||||
long hash = 3241;
|
||||
hash = 3457689L * hash + x;
|
||||
hash = 8734625L * hash + y;
|
||||
hash = 2873465L * hash + z;
|
||||
this.hashCode = hash;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ public class BetterBlockPos extends BlockPos {
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return hashCode;
|
||||
return (int) hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@@ -23,7 +23,7 @@ package baritone.utils.pathing;
|
||||
*/
|
||||
public enum PathingBlockType {
|
||||
|
||||
AIR (0b00),
|
||||
AIR(0b00),
|
||||
WATER(0b01),
|
||||
AVOID(0b10),
|
||||
SOLID(0b11);
|
||||
@@ -31,7 +31,7 @@ public enum PathingBlockType {
|
||||
private final boolean[] bits;
|
||||
|
||||
PathingBlockType(int bits) {
|
||||
this.bits = new boolean[] {
|
||||
this.bits = new boolean[]{
|
||||
(bits & 0b10) != 0,
|
||||
(bits & 0b01) != 0
|
||||
};
|
||||
@@ -42,11 +42,18 @@ public enum PathingBlockType {
|
||||
}
|
||||
|
||||
public static PathingBlockType fromBits(boolean b1, boolean b2) {
|
||||
for (PathingBlockType type : values())
|
||||
if (type.bits[0] == b1 && type.bits[1] == b2)
|
||||
return type;
|
||||
|
||||
// This will never happen, but if it does, assume it's just AIR
|
||||
return PathingBlockType.AIR;
|
||||
if (b1) {
|
||||
if (b2) {
|
||||
return PathingBlockType.SOLID;
|
||||
} else {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
} else {
|
||||
if (b2) {
|
||||
return PathingBlockType.WATER;
|
||||
} else {
|
||||
return PathingBlockType.AIR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -33,10 +33,7 @@ public class CachedRegionTest {
|
||||
byte xz = part1;
|
||||
int X = xz & 0x0f;
|
||||
int Z = (xz >>> 4) & 0x0f;
|
||||
int Y = (int) part2;
|
||||
if (Y < 0) {
|
||||
Y += 256;
|
||||
}
|
||||
int Y = part2 & 0xff;
|
||||
if (x != X || y != Y || z != Z) {
|
||||
System.out.println(x + " " + X + " " + y + " " + Y + " " + z + " " + Z);
|
||||
}
|
||||
|
@@ -42,7 +42,7 @@ public class OpenSetsTest {
|
||||
public void removeAndTest(int amount, IOpenSet[] test, Optional<Collection<PathNode>> mustContain) {
|
||||
double[][] results = new double[test.length][amount];
|
||||
for (int i = 0; i < test.length; i++) {
|
||||
long before = System.currentTimeMillis();
|
||||
long before = System.nanoTime() / 1000000L;
|
||||
for (int j = 0; j < amount; j++) {
|
||||
PathNode pn = test[i].removeLowest();
|
||||
if (mustContain.isPresent() && !mustContain.get().contains(pn)) {
|
||||
@@ -50,7 +50,7 @@ public class OpenSetsTest {
|
||||
}
|
||||
results[i][j] = pn.combinedCost;
|
||||
}
|
||||
System.out.println(test[i].getClass() + " " + (System.currentTimeMillis() - before));
|
||||
System.out.println(test[i].getClass() + " " + (System.nanoTime() / 1000000L - before));
|
||||
}
|
||||
for (int j = 0; j < amount; j++) {
|
||||
for (int i = 1; i < test.length; i++) {
|
||||
@@ -104,10 +104,10 @@ public class OpenSetsTest {
|
||||
|
||||
System.out.println("Insertion");
|
||||
for (IOpenSet set : test) {
|
||||
long before = System.currentTimeMillis();
|
||||
long before = System.nanoTime() / 1000000L;
|
||||
for (int i = 0; i < size; i++)
|
||||
set.insert(toInsert[i]);
|
||||
System.out.println(set.getClass() + " " + (System.currentTimeMillis() - before));
|
||||
System.out.println(set.getClass() + " " + (System.nanoTime() / 1000000L - before));
|
||||
//all three take either 0 or 1ms to insert up to 10,000 nodes
|
||||
//linkedlist takes 0ms most often (because there's no array resizing or allocation there, just pointer shuffling)
|
||||
}
|
||||
|
49
src/test/java/baritone/pathing/goals/GoalGetToBlockTest.java
Normal file
49
src/test/java/baritone/pathing/goals/GoalGetToBlockTest.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class GoalGetToBlockTest {
|
||||
|
||||
@Test
|
||||
public void isInGoal() {
|
||||
List<String> acceptableOffsets = new ArrayList<>(Arrays.asList("0,0,0", "0,0,1", "0,0,-1", "1,0,0", "-1,0,0", "0,-1,1", "0,-1,-1", "1,-1,0", "-1,-1,0", "0,1,0", "0,-1,0", "0,-2,0"));
|
||||
for (int x = -10; x <= 10; x++) {
|
||||
for (int y = -10; y <= 10; y++) {
|
||||
for (int z = -10; z <= 10; z++) {
|
||||
boolean inGoal = new GoalGetToBlock(new BlockPos(0, 0, 0)).isInGoal(new BlockPos(x, y, z));
|
||||
String repr = x + "," + y + "," + z;
|
||||
System.out.println(repr + " " + inGoal);
|
||||
if (inGoal) {
|
||||
assertTrue(repr, acceptableOffsets.contains(repr));
|
||||
acceptableOffsets.remove(repr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue(acceptableOffsets.toString(), acceptableOffsets.isEmpty());
|
||||
}
|
||||
}
|
@@ -44,21 +44,21 @@ public class BetterBlockPosTest {
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
long before1 = System.currentTimeMillis();
|
||||
long before1 = System.nanoTime() / 1000000L;
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
pos.up();
|
||||
}
|
||||
long after1 = System.currentTimeMillis();
|
||||
long after1 = System.nanoTime() / 1000000L;
|
||||
try {
|
||||
Thread.sleep(1000); // give GC some time
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
long before2 = System.currentTimeMillis();
|
||||
long before2 = System.nanoTime() / 1000000L;
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
pos2.up();
|
||||
}
|
||||
long after2 = System.currentTimeMillis();
|
||||
long after2 = System.nanoTime() / 1000000L;
|
||||
System.out.println((after1 - before1) + " " + (after2 - before2));
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class BetterBlockPosTest {
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
long before1 = System.currentTimeMillis();
|
||||
long before1 = System.nanoTime() / 1000000L;
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
pos.up(0);
|
||||
pos.up(1);
|
||||
@@ -78,13 +78,13 @@ public class BetterBlockPosTest {
|
||||
pos.up(3);
|
||||
pos.up(4);
|
||||
}
|
||||
long after1 = System.currentTimeMillis();
|
||||
long after1 = System.nanoTime() / 1000000L;
|
||||
try {
|
||||
Thread.sleep(1000); // give GC some time
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
long before2 = System.currentTimeMillis();
|
||||
long before2 = System.nanoTime() / 1000000L;
|
||||
for (int i = 0; i < 1000000; i++) {
|
||||
pos2.up(0);
|
||||
pos2.up(1);
|
||||
@@ -92,7 +92,7 @@ public class BetterBlockPosTest {
|
||||
pos2.up(3);
|
||||
pos2.up(4);
|
||||
}
|
||||
long after2 = System.currentTimeMillis();
|
||||
long after2 = System.nanoTime() / 1000000L;
|
||||
System.out.println((after1 - before1) + " " + (after2 - before2));
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user