Initial commit of commands

This commit is contained in:
Logan Darklock 2019-08-30 11:55:25 -07:00
parent e7412d0d46
commit e3c4d06b2b
No known key found for this signature in database
GPG Key ID: B8C37CEDE1AC60EA
106 changed files with 6155 additions and 129 deletions

2
.gitignore vendored
View File

@ -14,6 +14,8 @@ classes/
# IntelliJ Files
.idea/
*.iml
*.ipr
*.iws
/logs/
# Copyright Files

View File

@ -483,15 +483,20 @@ public final class Settings {
public final Setting<Boolean> chatControl = new Setting<>(true);
/**
* A second override over chatControl to force it on
* Some clients like Impact try to force chatControl to off, so here's a second setting to do it anyway
*/
public final Setting<Boolean> removePrefix = new Setting<>(false);
public final Setting<Boolean> chatControlAnyway = new Setting<>(false);
/**
* Render the path
*/
public final Setting<Boolean> renderPath = new Setting<>(true);
/**
* Render the path as a line instead of a frickin thingy
*/
public final Setting<Boolean> renderPathAsLine = new Setting<>(true);
/**
* Render the goal
*/
@ -592,10 +597,25 @@ public final class Settings {
public final Setting<Float> cachedChunksOpacity = new Setting<>(0.5f);
/**
* Whether or not to use the "#" command prefix
* Whether or not to allow you to run Baritone commands with the prefix
*/
public final Setting<Boolean> prefixControl = new Setting<>(true);
/**
* The command prefix for chat control
*/
public final Setting<String> prefix = new Setting<>("#");
/**
* Use a short Baritone prefix [B] instead of [Baritone] when logging to chat
*/
public final Setting<Boolean> shortBaritonePrefix = new Setting<>(false);
/**
* Echo commands to chat when they are run
*/
public final Setting<Boolean> echoCommands = new Setting<>(true);
/**
* Don't stop walking forward when you need to break blocks in your way
*/
@ -894,6 +914,11 @@ public final class Settings {
*/
public final Setting<Color> colorGoalBox = new Setting<>(Color.GREEN);
/**
* The color of the goal box when it's inverted
*/
public final Setting<Color> colorInvertedGoalBox = new Setting<>(Color.RED);
/**
* A map of lowercase setting field names to their respective setting

View File

@ -64,11 +64,17 @@ public interface IPathingBehavior extends IBehavior {
Goal getGoal();
/**
* @return Whether or not a path is currently being executed.
* @return Whether or not a path is currently being executed. This will be false if there's currently a pause.
* @see #hasPath()
*/
default boolean isPathing() {
return getCurrent() != null;
}
boolean isPathing();
/**
* @return If there is a current path. Note that the path is not necessarily being executed, for example when there
* is a pause in effect.
* @see #isPathing()
*/
boolean hasPath();
/**
* Cancels the pathing behavior or the current path calculation, and all processes that could be controlling path.

View File

@ -17,6 +17,7 @@
package baritone.api.cache;
import baritone.api.utils.IBlockFilter;
import baritone.api.utils.IPlayerContext;
import net.minecraft.block.Block;
import net.minecraft.util.math.BlockPos;
@ -35,26 +36,26 @@ public interface IWorldScanner {
*
* @param ctx The {@link IPlayerContext} containing player and world info that the
* scan is based upon
* @param blocks The blocks to scan for
* @param filter The block filter to scan for
* @param max The maximum number of blocks to scan before cutoff
* @param yLevelThreshold If a block is found within this Y level, the current result will be
* returned, if the value is negative, then this condition doesn't apply.
* @param maxSearchRadius The maximum chunk search radius
* @return The matching block positions
*/
List<BlockPos> scanChunkRadius(IPlayerContext ctx, List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius);
List<BlockPos> scanChunkRadius(IPlayerContext ctx, IBlockFilter filter, int max, int yLevelThreshold, int maxSearchRadius);
/**
* Scans a single chunk for the specified blocks.
*
* @param ctx The {@link IPlayerContext} containing player and world info that the
* scan is based upon
* @param blocks The blocks to scan for
* @param filter The block filter to scan for
* @param pos The position of the target chunk
* @param max The maximum number of blocks to scan before cutoff
* @param yLevelThreshold If a block is found within this Y level, the current result will be
* returned, if the value is negative, then this condition doesn't apply.
* @return The matching block positions
*/
List<BlockPos> scanChunk(IPlayerContext ctx, List<Block> blocks, ChunkPos pos, int max, int yLevelThreshold);
List<BlockPos> scanChunk(IPlayerContext ctx, IBlockFilter filter, ChunkPos pos, int max, int yLevelThreshold);
}

View File

@ -0,0 +1,50 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.event.events;
import baritone.api.event.events.type.Cancellable;
import baritone.api.event.events.type.Overrideable;
/**
* @author LoganDark
*/
public abstract class TabCompleteEvent extends Cancellable {
public final Overrideable<String> prefix;
public final Overrideable<String[]> completions;
TabCompleteEvent(String prefix, String[] completions) {
this.prefix = new Overrideable<>(prefix);
this.completions = new Overrideable<>(completions);
}
public boolean wasModified() {
return prefix.wasModified() || completions.wasModified();
}
public static final class Pre extends TabCompleteEvent {
public Pre(String prefix) {
super(prefix, null);
}
}
public static final class Post extends TabCompleteEvent {
public Post(String prefix, String[] completions) {
super(prefix, completions);
}
}
}

View File

@ -0,0 +1,35 @@
package baritone.api.event.events.type;
/**
* @author LoganDark
*/
public class Overrideable<T> {
private T value;
private boolean modified;
public Overrideable(T current) {
value = current;
}
public T get() {
return value;
}
public void set(T newValue) {
value = newValue;
modified = true;
}
public boolean wasModified() {
return modified;
}
@Override
public String toString() {
return String.format(
"Overrideable{modified=%s,value=%s}",
Boolean.toString(modified),
value.toString()
);
}
}

View File

@ -39,6 +39,12 @@ public interface AbstractGameEventListener extends IGameEventListener {
@Override
default void onSendChatMessage(ChatEvent event) {}
@Override
default void onPreTabComplete(TabCompleteEvent.Pre event) {};
@Override
default void onPostTabComplete(TabCompleteEvent.Post event) {};
@Override
default void onChunkEvent(ChunkEvent event) {}

View File

@ -57,6 +57,21 @@ public interface IGameEventListener {
*/
void onSendChatMessage(ChatEvent event);
/**
* Runs whenever the client player tries to tab complete in chat.
*
* @param event The event
*/
void onPreTabComplete(TabCompleteEvent.Pre event);
/**
* Runs whenever the client player tries to tab complete in chat once completions have been recieved from the
* server. This will only be called if the {@link TabCompleteEvent.Pre#cancel()} method was not called.
*
* @param event The event
*/
void onPostTabComplete(TabCompleteEvent.Post event);
/**
* Runs before and after whenever a chunk is either loaded, unloaded, or populated.
*

View File

@ -0,0 +1,46 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.pathing.goals;
/**
* Invert any goal
*
* @author LoganDark
*/
public class GoalInverted implements Goal {
public final Goal origin;
public GoalInverted(Goal origin) {
this.origin = origin;
}
@Override
public boolean isInGoal(int x, int y, int z) {
return false;
}
@Override
public double heuristic(int x, int y, int z) {
return -origin.heuristic(x, y, z);
}
@Override
public String toString() {
return String.format("GoalInverted{%s}", origin.toString());
}
}

View File

@ -18,6 +18,7 @@
package baritone.api.pathing.goals;
import baritone.api.BaritoneAPI;
import baritone.api.utils.BetterBlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
@ -45,6 +46,11 @@ public class GoalXZ implements Goal {
this.z = z;
}
public GoalXZ(BetterBlockPos pos) {
this.x = pos.x;
this.z = pos.z;
}
@Override
public boolean isInGoal(int x, int y, int z) {
return x == this.x && z == this.z;

View File

@ -58,6 +58,8 @@ public interface IBuilderProcess extends IBaritoneProcess {
void pause();
boolean isPaused();
void resume();
void clearArea(BlockPos corner1, BlockPos corner2);

View File

@ -17,6 +17,8 @@
package baritone.api.process;
import baritone.api.utils.BlockListFilter;
import baritone.api.utils.IBlockFilter;
import net.minecraft.block.Block;
/**
@ -24,13 +26,12 @@ import net.minecraft.block.Block;
* @since 9/23/2018
*/
public interface IMineProcess extends IBaritoneProcess {
/**
* Begin to search for and mine the specified blocks until
* the number of specified items to get from the blocks that
* are mined. This is based on the first target block to mine.
* are mined.
*
* @param quantity The number of items to get from blocks mined
* @param quantity The total number of items to get
* @param blocks The blocks to mine
*/
void mineByName(int quantity, String... blocks);
@ -41,9 +42,18 @@ public interface IMineProcess extends IBaritoneProcess {
* are mined. This is based on the first target block to mine.
*
* @param quantity The number of items to get from blocks mined
* @param blocks The blocks to mine
* @param filter The filter to run blocks through
*/
void mine(int quantity, Block... blocks);
void mine(int quantity, IBlockFilter filter);
/**
* Begin to search for and mine the specified blocks.
*
* @param filter The filter to run blocks through
*/
default void mine(IBlockFilter filter) {
mine(0, filter);
}
/**
* Begin to search for and mine the specified blocks.
@ -54,6 +64,16 @@ public interface IMineProcess extends IBaritoneProcess {
mineByName(0, blocks);
}
/**
* Begin to search for and mine the specified blocks.
*
* @param quantity The total number of items to get
* @param blocks The blocks to mine
*/
default void mine(int quantity, Block... blocks) {
mine(quantity, new BlockListFilter(blocks));
}
/**
* Begin to search for and mine the specified blocks.
*

View File

@ -0,0 +1,46 @@
package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BlockListFilter implements IBlockFilter {
private final List<Block> blocks = new ArrayList<>();
public BlockListFilter(List<Block> blocks) {
this.blocks.addAll(blocks);
}
public BlockListFilter(Block... blocks) {
this.blocks.addAll(Arrays.asList(blocks));
}
@Override
public boolean selected(@Nonnull IBlockState blockstate) {
return false;
}
@Override
public List<Block> blocks() {
return null;
}
@Override
public String toString() {
return String.format(
"BlockListFilter{%s}",
String.join(
",",
blocks.stream()
.map(Block.REGISTRY::getNameForObject)
.map(ResourceLocation::toString)
.toArray(String[]::new)
)
);
}
}

View File

@ -0,0 +1,63 @@
package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.util.Objects.isNull;
public class BlockSelector implements IBlockFilter {
private final Block block;
private final IBlockState blockstate;
private static final Pattern pattern = Pattern.compile("^(.+?)(?::(\\d+))?$");
public BlockSelector(@Nonnull String selector) {
Matcher matcher = pattern.matcher(selector);
if (!matcher.find()) {
throw new RuntimeException("invalid block selector");
}
MatchResult matchResult = matcher.toMatchResult();
boolean hasData = matchResult.groupCount() > 1;
ResourceLocation id = new ResourceLocation(matchResult.group(1));
if (!Block.REGISTRY.containsKey(id)) {
throw new IllegalArgumentException("Invalid block ID");
}
block = Block.REGISTRY.getObject(id);
//noinspection deprecation
blockstate = hasData ? block.getStateFromMeta(Integer.parseInt(matchResult.group(2))) : null;
}
@Override
public boolean selected(@Nonnull IBlockState blockstate) {
return blockstate.getBlock() == block && (isNull(this.blockstate) ||
block.damageDropped(blockstate) == block.damageDropped(this.blockstate));
}
@Override
public List<Block> blocks() {
return Collections.singletonList(block);
}
@Override
public String toString() {
return String.format("BlockSelector{block=%s,blockstate=%s}", block, blockstate);
}
public static IBlockState stateFromItem(ItemStack stack) {
//noinspection deprecation
return Block.getBlockFromItem(stack.getItem()).getStateFromMeta(stack.getMetadata());
}
}

View File

@ -39,7 +39,7 @@ public class BlockUtils {
public static Block stringToBlockRequired(String name) {
Block block = stringToBlockNullable(name);
Objects.requireNonNull(block);
Objects.requireNonNull(block, String.format("Invalid block name %s", name));
return block;
}

View File

@ -0,0 +1,51 @@
package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
import static java.util.Arrays.asList;
public class CompositeBlockFilter implements IBlockFilter {
List<IBlockFilter> filters = new ArrayList<>();
public CompositeBlockFilter() {
}
public CompositeBlockFilter(List<? extends IBlockFilter> filters) {
this.filters.addAll(filters);
}
public CompositeBlockFilter(IBlockFilter... filters) {
this.filters.addAll(asList(filters));
}
@Override
public boolean selected(@Nonnull IBlockState blockstate) {
return filters.stream()
.map(f -> f.selected(blockstate))
.filter(Boolean::valueOf).findFirst()
.orElse(false);
}
@Override
public List<Block> blocks() {
return filters.stream()
.map(IBlockFilter::blocks)
.flatMap(Collection::stream)
.collect(Collectors.toCollection(ArrayList::new));
}
@Override
public String toString() {
return String.format(
"CompositeBlockFilter{%s}",
String.join(",", filters.stream().map(Object::toString).toArray(String[]::new))
);
}
}

View File

@ -26,7 +26,14 @@ import baritone.api.cache.IWaypoint;
import baritone.api.cache.Waypoint;
import baritone.api.event.events.ChatEvent;
import baritone.api.event.listener.AbstractGameEventListener;
import baritone.api.pathing.goals.*;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalAxis;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.pathing.goals.GoalGetToBlock;
import baritone.api.pathing.goals.GoalRunAway;
import baritone.api.pathing.goals.GoalStrictDirection;
import baritone.api.pathing.goals.GoalXZ;
import baritone.api.pathing.goals.GoalYLevel;
import baritone.api.process.IBaritoneProcess;
import baritone.api.process.ICustomGoalProcess;
import baritone.api.process.IGetToBlockProcess;
@ -48,17 +55,24 @@ import net.minecraft.world.DimensionType;
import net.minecraft.world.chunk.Chunk;
import java.nio.file.Path;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import static org.apache.commons.lang3.math.NumberUtils.isCreatable;
public class ExampleBaritoneControl implements Helper, AbstractGameEventListener {
public class ExampleBaritoneControlOld implements Helper, AbstractGameEventListener {
private static final String COMMAND_PREFIX = "#";
public final IBaritone baritone;
public final IPlayerContext ctx;
public ExampleBaritoneControl(IBaritone baritone) {
public ExampleBaritoneControlOld(IBaritone baritone) {
this.baritone = baritone;
this.ctx = baritone.getPlayerContext();
baritone.getGameEventHandler().registerEventListener(this);
@ -74,7 +88,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
event.cancel(); // always cancel if using prefixControl
return;
}
if (!BaritoneAPI.getSettings().chatControl.value && !BaritoneAPI.getSettings().removePrefix.value) {
if (!BaritoneAPI.getSettings().chatControl.value && !BaritoneAPI.getSettings().chatControlAnyway.value) {
return;
}
if (runCommand(msg)) {
@ -123,7 +137,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
return true;
}
if (msg.equals("") || msg.equals("help") || msg.equals("?")) {
ITextComponent component = MESSAGE_PREFIX.createCopy();
ITextComponent component = Helper.getPrefix();
component.getStyle().setColor(TextFormatting.GRAY);
TextComponentString helpLink = new TextComponentString(" Click here for instructions on how to use Baritone (https://github.com/cabaletta/baritone/blob/master/USAGE.md)");
helpLink.getStyle().setClickEvent(new ClickEvent(ClickEvent.Action.OPEN_URL, "https://github.com/cabaletta/baritone/blob/master/USAGE.md"));
@ -166,7 +180,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
} else {
String[] params = rest.split(" ");
if (params[0].equals("")) {
params = new String[]{};
params = new String[] {};
}
goal = parseGoal(params);
if (goal == null) {
@ -232,7 +246,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
return true;
}
if (msg.equals("version")) {
String version = ExampleBaritoneControl.class.getPackage().getImplementationVersion();
String version = ExampleBaritoneControlOld.class.getPackage().getImplementationVersion();
if (version == null) {
logDirect("No version detected. Either dev environment or broken install.");
} else {
@ -510,7 +524,8 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
baritone.getMineProcess().mine(quantity, block);
logDirect("Will mine " + quantity + " " + blockTypes[0]);
return true;
} catch (NumberFormatException | ArrayIndexOutOfBoundsException | NullPointerException ex) {}
} catch (NumberFormatException | ArrayIndexOutOfBoundsException | NullPointerException ex) {
}
for (String s : blockTypes) {
if (BlockUtils.stringToBlockNullable(s) == null) {
logDirect(s + " isn't a valid block name");

View File

@ -23,6 +23,10 @@ import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import java.util.Arrays;
import static java.util.Arrays.asList;
/**
* @author Brady
* @since 8/1/2018
@ -32,15 +36,19 @@ public interface Helper {
/**
* Instance of {@link Helper}. Used for static-context reference.
*/
Helper HELPER = new Helper() {};
Helper HELPER = new Helper() {
};
ITextComponent MESSAGE_PREFIX = new TextComponentString(String.format(
"%s[%sBaritone%s]%s",
TextFormatting.DARK_PURPLE,
TextFormatting.LIGHT_PURPLE,
TextFormatting.DARK_PURPLE,
TextFormatting.GRAY
));
static ITextComponent getPrefix() {
return new TextComponentString("") {{
getStyle().setColor(TextFormatting.DARK_PURPLE);
appendSibling(new TextComponentString("["));
appendSibling(new TextComponentString(BaritoneAPI.getSettings().shortBaritonePrefix.value ? "B" : "Baritone") {{
getStyle().setColor(TextFormatting.LIGHT_PURPLE);
}});
appendSibling(new TextComponentString("]"));
}};
}
Minecraft mc = Minecraft.getMinecraft();
@ -58,15 +66,41 @@ public interface Helper {
logDirect(message);
}
/**
* Send components to chat with the [Baritone] prefix
*
* @param components The components to send
*/
default void logDirect(ITextComponent... components) {
ITextComponent component = new TextComponentString("") {{
appendSibling(getPrefix());
appendSibling(new TextComponentString(" "));
asList(components).forEach(this::appendSibling);
}};
Minecraft.getMinecraft().addScheduledTask(() -> BaritoneAPI.getSettings().logger.value.accept(component));
}
/**
* Send a message to chat regardless of chatDebug (should only be used for critically important messages, or as a direct response to a chat command)
*
* @param message The message to display in chat
* @param color The color to print that message in
*/
default void logDirect(String message, TextFormatting color) {
Arrays.stream(message.split("\\n")).forEach(line ->
logDirect(new TextComponentString(line.replace("\t", " ")) {{
getStyle().setColor(color);
}})
);
}
/**
* Send a message to chat regardless of chatDebug (should only be used for critically important messages, or as a direct response to a chat command)
*
* @param message The message to display in chat
*/
default void logDirect(String message) {
ITextComponent component = MESSAGE_PREFIX.createCopy();
component.getStyle().setColor(TextFormatting.GRAY);
component.appendSibling(new TextComponentString(" " + message));
Minecraft.getMinecraft().addScheduledTask(() -> BaritoneAPI.getSettings().logger.value.accept(component));
logDirect(message, TextFormatting.GRAY);
}
}

View File

@ -0,0 +1,22 @@
package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import javax.annotation.Nonnull;
import java.util.List;
public interface IBlockFilter {
/**
* @param blockstate The blockstate of the block to test.
* @return If that blockstate passes this filter.
*/
boolean selected(@Nonnull IBlockState blockstate);
/**
* @return A possibly incomplete list of blocks this filter selects. Not all states of each block may be selected,
* and this may not contain all selected blocks, but every block on this list is guaranteed to have a selected
* state.
*/
List<Block> blocks();
}

View File

@ -120,15 +120,37 @@ public class SettingsUtil {
return modified;
}
public static String settingTypeToString(Settings.Setting setting) {
return setting.getType().getTypeName()
.replaceAll("(?:\\w+\\.)+(\\w+)", "$1");
}
public static <T> String settingValueToString(Settings.Setting<T> setting, T value) throws IllegalArgumentException {
Parser io = Parser.getParser(setting.getType());
if (io == null) {
throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting.getName());
}
return io.toString(new ParserContext(setting), value);
}
public static String settingValueToString(Settings.Setting setting) throws IllegalArgumentException {
//noinspection unchecked
return settingValueToString(setting, setting.value);
}
public static String settingDefaultToString(Settings.Setting setting) throws IllegalArgumentException {
//noinspection unchecked
return settingValueToString(setting, setting.defaultValue);
}
public static String settingToString(Settings.Setting setting) throws IllegalStateException {
if (setting.getName().equals("logger")) {
return "logger";
}
Parser io = Parser.getParser(setting.getType());
if (io == null) {
throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting.getName());
}
return setting.getName() + " " + io.toString(new ParserContext(setting), setting.value);
return setting.getName() + " " + settingValueToString(setting);
}
public static void parseAndApply(Settings settings, String settingName, String settingValue) throws IllegalStateException, NumberFormatException {
@ -174,6 +196,7 @@ public class SettingsUtil {
INTEGER(Integer.class, Integer::parseInt),
FLOAT(Float.class, Float::parseFloat),
LONG(Long.class, Long::parseLong),
STRING(String.class, String::new),
ENUMFACING(EnumFacing.class, EnumFacing::byName),
COLOR(
Color.class,

View File

@ -0,0 +1,231 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.Settings;
import baritone.api.event.events.ChatEvent;
import baritone.api.event.events.TabCompleteEvent;
import baritone.api.event.listener.AbstractGameEventListener;
import baritone.api.utils.Helper;
import baritone.api.utils.IPlayerContext;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.command.argument.CommandArgument;
import baritone.api.utils.command.exception.CommandNotFoundException;
import baritone.api.utils.command.execution.CommandExecution;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper;
import baritone.api.utils.command.manager.CommandManager;
import com.mojang.realmsclient.util.Pair;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.event.ClickEvent;
import net.minecraft.util.text.event.HoverEvent;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.stream.Stream;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static java.util.stream.Stream.of;
public class BaritoneChatControl implements Helper, AbstractGameEventListener {
public final IBaritone baritone;
public final IPlayerContext ctx;
public final Settings settings = BaritoneAPI.getSettings();
public static String FORCE_COMMAND_PREFIX = String.format("<<%s>>", UUID.randomUUID().toString());
public BaritoneChatControl(IBaritone baritone) {
this.baritone = baritone;
this.ctx = baritone.getPlayerContext();
baritone.getGameEventHandler().registerEventListener(this);
}
@Override
public void onSendChatMessage(ChatEvent event) {
String msg = event.getMessage();
String prefix = settings.prefix.value;
boolean forceRun = msg.startsWith(FORCE_COMMAND_PREFIX);
if (!forceRun && !settings.chatControl.value && !settings.chatControlAnyway.value && !settings.prefixControl.value) {
return;
}
if ((settings.prefixControl.value && msg.startsWith(prefix)) || forceRun) {
event.cancel();
String commandStr = msg.substring(forceRun ? FORCE_COMMAND_PREFIX.length() : prefix.length());
if (!runCommand(commandStr) && !commandStr.trim().isEmpty()) {
new CommandNotFoundException(CommandExecution.expand(commandStr).first()).handle(null, null);
}
return;
}
if ((settings.chatControl.value || settings.chatControlAnyway.value) && runCommand(msg)) {
event.cancel();
}
}
private void logRanCommand(String msg) {
if (settings.echoCommands.value) {
logDirect(new TextComponentString(String.format("> %s", msg)) {{
getStyle()
.setColor(TextFormatting.WHITE)
.setHoverEvent(new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new TextComponentString("Click to rerun command")
))
.setClickEvent(new ClickEvent(
ClickEvent.Action.RUN_COMMAND,
FORCE_COMMAND_PREFIX + msg
));
}});
}
}
public boolean runCommand(String msg) {
if (msg.trim().equalsIgnoreCase("damn")) {
logDirect("daniel");
return false;
} else if (msg.trim().equalsIgnoreCase("orderpizza")) {
try {
((Lol) mc.currentScreen).openLink(new URI("https://www.dominos.com/en/pages/order/"));
} catch (NullPointerException | URISyntaxException ignored) {
}
return false;
}
if (msg.isEmpty()) {
msg = "help";
}
Pair<String, List<CommandArgument>> pair = CommandExecution.expand(msg);
ArgConsumer argc = new ArgConsumer(pair.second());
if (!argc.has()) {
for (Settings.Setting setting : settings.allSettings) {
if (setting.getName().equals("logger")) {
continue;
}
if (setting.getName().equalsIgnoreCase(pair.first())) {
logRanCommand(msg);
if (setting.getValueClass() == Boolean.class) {
CommandManager.execute(String.format("set toggle %s", setting.getName()));
} else {
CommandManager.execute(String.format("set %s", setting.getName()));
}
return true;
}
}
} else if (argc.hasExactlyOne()) {
for (Settings.Setting setting : settings.allSettings) {
if (setting.getName().equals("logger")) {
continue;
}
if (setting.getName().equalsIgnoreCase(pair.first())) {
logRanCommand(msg);
CommandManager.execute(String.format("set %s %s", setting.getName(), argc.getS()));
return true;
}
}
}
CommandExecution execution = CommandExecution.from(pair);
if (isNull(execution)) {
return false;
}
logRanCommand(msg);
CommandManager.execute(execution);
return true;
}
@Override
public void onPreTabComplete(TabCompleteEvent.Pre event) {
if (!settings.prefixControl.value) {
return;
}
String prefix = event.prefix.get();
String commandPrefix = settings.prefix.value;
if (!prefix.startsWith(commandPrefix)) {
return;
}
String msg = prefix.substring(commandPrefix.length());
List<CommandArgument> args = CommandArgument.from(msg, true);
Stream<String> stream = tabComplete(msg);
if (args.size() == 1) {
stream = stream.map(x -> commandPrefix + x);
}
event.completions.set(stream.toArray(String[]::new));
}
public Stream<String> tabComplete(String msg) {
List<CommandArgument> args = CommandArgument.from(msg, true);
ArgConsumer argc = new ArgConsumer(args);
if (argc.hasAtMost(2)) {
if (argc.hasExactly(1)) {
return new TabCompleteHelper()
.addCommands()
.addSettings()
.filterPrefix(argc.getS())
.stream();
}
Settings.Setting setting = settings.byLowerName.get(argc.getS().toLowerCase(Locale.US));
if (nonNull(setting)) {
if (setting.getValueClass() == Boolean.class) {
TabCompleteHelper helper = new TabCompleteHelper();
if ((Boolean) setting.value) {
helper.append(of("true", "false"));
} else {
helper.append(of("false", "true"));
}
return helper.filterPrefix(argc.getS()).stream();
} else {
return of(SettingsUtil.settingValueToString(setting));
}
}
}
return CommandManager.tabComplete(msg);
}
}

View File

@ -0,0 +1,114 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.Settings;
import baritone.api.utils.Helper;
import baritone.api.utils.IPlayerContext;
import baritone.api.utils.command.execution.CommandExecution;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import net.minecraft.client.Minecraft;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public abstract class Command implements Helper {
protected IBaritone baritone = BaritoneAPI.getProvider().getPrimaryBaritone();
protected IPlayerContext ctx = baritone.getPlayerContext();
protected Minecraft MC = mc;
/**
* The names of this command. This is what you put after the command prefix.
*/
public final List<String> names;
/**
* A <b>single-line</b> string containing a short description of this command's purpose.
*/
public final String shortDesc;
/**
* Creates a new Baritone control command.
*
* @param names The names of this command. This is what you put after the command prefix.
* @param shortDesc A <b>single-line</b> string containing a short description of this command's purpose.
*/
protected Command(List<String> names, String shortDesc) {
this.names = names.stream()
.map(s -> s.toLowerCase(Locale.US))
.collect(Collectors.toCollection(ArrayList::new));
this.shortDesc = shortDesc;
}
protected Command(String name, String shortDesc) {
this(Collections.singletonList(name), shortDesc);
}
/**
* Executes this command with the specified arguments.
*
* @param execution The command execution to execute this command with
*/
public void execute(CommandExecution execution) {
executed(execution.label, execution.args, execution.settings);
}
/**
* Tab completes this command with the specified arguments. This won't throw any exceptions ever.
*
* @param execution The command execution to tab complete
* @return The list of completions.
*/
public Stream<String> tabComplete(CommandExecution execution) {
try {
return tabCompleted(execution.label, execution.args, execution.settings);
} catch (Throwable t) {
return Arrays.stream(new String[0]);
}
}
/**
* Called when this command is executed.
*/
protected abstract void executed(String label, ArgConsumer args, Settings settings);
/**
* Called when the command needs to tab complete. Return a Stream representing the entries to put in the completions
* list.
*/
protected abstract Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings);
/**
* @return A list of lines that will be printed by the help command when the user wishes to view them.
*/
public abstract List<String> getLongDesc();
/**
* @return {@code true} if this command should be hidden from the help menu
*/
public boolean hiddenFromHelp() {
return false;
}
}

View File

@ -0,0 +1,7 @@
package baritone.api.utils.command;
import java.net.URI;
public interface Lol {
void openLink(URI url);
}

View File

@ -0,0 +1,45 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.argparser;
public abstract class ArgParser<T> implements IArgParser<T> {
private final Class<T> klass;
protected ArgParser(Class<T> klass) {
this.klass = klass;
}
@Override
public Class<T> getKlass() {
return klass;
}
public static abstract class Stated<T, S> extends ArgParser<T> implements IArgParser.Stated<T, S> {
private final Class<S> stateKlass;
protected Stated(Class<T> klass, Class<S> stateKlass) {
super(klass);
this.stateKlass = stateKlass;
}
@Override
public Class<S> getStateKlass() {
return stateKlass;
}
}
}

View 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 Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.argparser;
import baritone.api.utils.command.argument.CommandArgument;
import baritone.api.utils.command.exception.CommandInvalidTypeException;
import baritone.api.utils.command.exception.CommandNoParserForTypeException;
import baritone.api.utils.command.registry.Registry;
import java.util.Iterator;
import static java.util.Objects.isNull;
public class ArgParserManager {
public static final Registry<ArgParser> REGISTRY = new Registry<>();
static {
DefaultArgParsers.all.forEach(REGISTRY::register);
}
/**
* @param klass The class to search for.
* @return A parser that can parse arguments into this class, if found.
*/
public static <T> ArgParser.Stateless<T> getParserStateless(Class<T> klass) {
for (Iterator<ArgParser> it = REGISTRY.descendingIterator(); it.hasNext(); ) {
ArgParser<?> parser = it.next();
if (parser instanceof ArgParser.Stateless && parser.getKlass().isAssignableFrom(klass)) {
//noinspection unchecked
return (ArgParser.Stateless<T>) parser;
}
}
return null;
}
/**
* @param klass The class to search for.
* @return A parser that can parse arguments into this class, if found.
*/
public static <T, S> ArgParser.Stated<T, S> getParserStated(Class<T> klass, Class<S> stateKlass) {
for (Iterator<ArgParser> it = REGISTRY.descendingIterator(); it.hasNext(); ) {
ArgParser<?> parser = it.next();
//noinspection unchecked
if (parser instanceof ArgParser.Stated
&& parser.getKlass().isAssignableFrom(klass)
&& ((ArgParser.Stated) parser).getStateKlass().isAssignableFrom(stateKlass)) {
//noinspection unchecked
return (ArgParser.Stated<T, S>) parser;
}
}
return null;
}
public static <T> T parseStateless(Class<T> klass, CommandArgument arg) {
ArgParser.Stateless<T> parser = getParserStateless(klass);
if (isNull(parser)) {
throw new CommandNoParserForTypeException(klass);
}
try {
return parser.parseArg(arg);
} catch (RuntimeException exc) {
throw new CommandInvalidTypeException(arg, klass.getSimpleName());
}
}
public static <T, S> T parseStated(Class<T> klass, Class<S> stateKlass, CommandArgument arg, S state) {
ArgParser.Stated<T, S> parser = getParserStated(klass, stateKlass);
if (isNull(parser)) {
throw new CommandNoParserForTypeException(klass);
}
try {
return parser.parseArg(arg, state);
} catch (RuntimeException exc) {
throw new CommandInvalidTypeException(arg, klass.getSimpleName());
}
}
}

View File

@ -0,0 +1,110 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.argparser;
import baritone.api.utils.command.argument.CommandArgument;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import static java.util.Arrays.asList;
public class DefaultArgParsers {
public static class IntArgumentParser extends ArgParser<Integer> implements IArgParser.Stateless<Integer> {
public static final IntArgumentParser INSTANCE = new IntArgumentParser();
public IntArgumentParser() {
super(Integer.class);
}
@Override
public Integer parseArg(CommandArgument arg) throws RuntimeException {
return Integer.parseInt(arg.value);
}
}
public static class FloatArgumentParser extends ArgParser<Float> implements IArgParser.Stateless<Float> {
public static final FloatArgumentParser INSTANCE = new FloatArgumentParser();
public FloatArgumentParser() {
super(Float.class);
}
@Override
public Float parseArg(CommandArgument arg) throws RuntimeException {
String value = arg.value;
if (!value.matches("^[+-]?\\d+(?:\\.\\d+)$")) {
throw new RuntimeException("failed float format check");
}
return Float.parseFloat(value);
}
}
public static class DoubleArgumentParser extends ArgParser<Double> implements IArgParser.Stateless<Double> {
public static final DoubleArgumentParser INSTANCE = new DoubleArgumentParser();
public DoubleArgumentParser() {
super(Double.class);
}
@Override
public Double parseArg(CommandArgument arg) throws RuntimeException {
String value = arg.value;
if (!value.matches("^[+-]?\\d+(?:\\.\\d+)$")) {
throw new RuntimeException("failed double format check");
}
return Double.parseDouble(value);
}
}
public static class BooleanArgumentParser extends ArgParser<Boolean> implements IArgParser.Stateless<Boolean> {
public static final BooleanArgumentParser INSTANCE = new BooleanArgumentParser();
public static final List<String> TRUTHY_VALUES = asList("1", "true", "yes", "t", "y", "on", "enable");
public static final List<String> FALSY_VALUES = asList("0", "false", "no", "f", "n", "off", "disable");
public BooleanArgumentParser() {
super(Boolean.class);
}
@Override
public Boolean parseArg(CommandArgument arg) throws RuntimeException {
String value = arg.value;
if (TRUTHY_VALUES.contains(value.toLowerCase(Locale.US))) {
return true;
} else if (FALSY_VALUES.contains(value.toLowerCase(Locale.US))) {
return false;
} else {
throw new RuntimeException("invalid boolean");
}
}
}
public static final List<ArgParser<?>> all = Collections.unmodifiableList(asList(
IntArgumentParser.INSTANCE,
FloatArgumentParser.INSTANCE,
DoubleArgumentParser.INSTANCE,
BooleanArgumentParser.INSTANCE
));
}

View File

@ -0,0 +1,50 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.argparser;
import baritone.api.utils.command.argument.CommandArgument;
public interface IArgParser<T> {
/**
* @return the class of this parser.
*/
Class<T> getKlass();
interface Stateless<T> extends IArgParser<T> {
/**
* @param arg The argument to parse.
* @return What it was parsed into.
* @throws RuntimeException if you want the parsing to fail. The exception will be caught and turned into an
* appropriate error.
*/
T parseArg(CommandArgument arg) throws RuntimeException;
}
interface Stated<T, S> extends IArgParser<T> {
Class<S> getStateKlass();
/**
* @param arg The argument to parse.
* @param state Can be anything.
* @return What it was parsed into.
* @throws RuntimeException if you want the parsing to fail. The exception will be caught and turned into an
* appropriate error.
*/
T parseArg(CommandArgument arg, S state) throws RuntimeException;
}
}

View File

@ -0,0 +1,104 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.argument;
import baritone.api.utils.command.argparser.ArgParserManager;
import baritone.api.utils.command.exception.CommandInvalidTypeException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@SuppressWarnings("UnusedReturnValue")
public class CommandArgument {
public final int index;
public final String value;
public final String rawRest;
public final static Pattern argPattern = Pattern.compile("\\S+");
private CommandArgument(int index, String value, String rawRest) {
this.index = index;
this.value = value;
this.rawRest = rawRest;
}
public <E extends Enum<?>> E getE(Class<E> enumClass) {
//noinspection OptionalGetWithoutIsPresent
return Arrays.stream(enumClass.getEnumConstants())
.filter(e -> e.name().equalsIgnoreCase(value))
.findFirst()
.get();
}
public <T> T getAs(Class<T> type) {
return ArgParserManager.parseStateless(type, this);
}
public <T> boolean is(Class<T> type) {
try {
getAs(type);
return true;
} catch (Throwable t) {
return false;
}
}
public <T, S> T getAs(Class<T> type, Class<S> stateType, S state) {
return ArgParserManager.parseStated(type, stateType, this, state);
}
public <T, S> boolean is(Class<T> type, Class<S> stateType, S state) {
try {
getAs(type, stateType, state);
return true;
} catch (Throwable t) {
return false;
}
}
public static List<CommandArgument> from(String string, boolean preserveEmptyLast) {
List<CommandArgument> args = new ArrayList<>();
Matcher argMatcher = argPattern.matcher(string);
int lastEnd = -1;
while (argMatcher.find()) {
args.add(new CommandArgument(
args.size(),
argMatcher.group(),
string.substring(argMatcher.start())
));
lastEnd = argMatcher.end();
}
if (preserveEmptyLast && lastEnd < string.length()) {
args.add(new CommandArgument(args.size(), "", ""));
}
return args;
}
public static List<CommandArgument> from(String string) {
return from(string, false);
}
public static CommandArgument unknown() {
return new CommandArgument(-1, "<unknown>", "");
}
}

View File

@ -0,0 +1,43 @@
package baritone.api.utils.command.datatypes;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper;
import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.util.ResourceLocation;
import java.util.stream.Stream;
public class BlockById implements IDatatypeFor<Block> {
public final Block block;
public BlockById() {
block = null;
}
public BlockById(ArgConsumer consumer) {
ResourceLocation id = new ResourceLocation(consumer.getS());
if ((block = Block.REGISTRY.getObject(id)) == Blocks.AIR) {
throw new RuntimeException("no block found by that id");
}
}
@Override
public Block get() {
return block;
}
@Override
public Stream<String> tabComplete(ArgConsumer consumer) {
return new TabCompleteHelper()
.append(
Block.REGISTRY.getKeys()
.stream()
.map(Object::toString)
)
.filterPrefixNamespaced(consumer.getS())
.sortAlphabetically()
.stream();
}
}

View File

@ -0,0 +1,45 @@
package baritone.api.utils.command.datatypes;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.util.ResourceLocation;
import java.util.stream.Stream;
import static java.util.Objects.isNull;
public class EntityClassById implements IDatatypeFor<Class<? extends Entity>> {
public final Class<? extends Entity> entity;
public EntityClassById() {
entity = null;
}
public EntityClassById(ArgConsumer consumer) {
ResourceLocation id = new ResourceLocation(consumer.getS());
if (isNull(entity = EntityList.REGISTRY.getObject(id))) {
throw new RuntimeException("no entity found by that id");
}
}
@Override
public Class<? extends Entity> get() {
return entity;
}
@Override
public Stream<String> tabComplete(ArgConsumer consumer) {
return new TabCompleteHelper()
.append(
EntityList.getEntityNameList()
.stream()
.map(Object::toString)
)
.filterPrefixNamespaced(consumer.getS())
.sortAlphabetically()
.stream();
}
}

View File

@ -0,0 +1,28 @@
package baritone.api.utils.command.datatypes;
import baritone.api.utils.BlockSelector;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.stream.Stream;
public class ForBlockSelector implements IDatatypeFor<BlockSelector> {
public final BlockSelector selector;
public ForBlockSelector() {
selector = null;
}
public ForBlockSelector(ArgConsumer consumer) {
selector = new BlockSelector(consumer.getS());
}
@Override
public BlockSelector get() {
return selector;
}
@Override
public Stream<String> tabComplete(ArgConsumer consumer) {
return consumer.tabCompleteDatatype(BlockById.class);
}
}

View File

@ -0,0 +1,17 @@
package baritone.api.utils.command.datatypes;
import baritone.api.utils.command.exception.CommandInvalidArgumentException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.stream.Stream;
/**
* Since interfaces cannot enforce the presence of a constructor, it's on you to make sure there is a constructor that
* accepts a single {@link ArgConsumer} argument. The constructor will perform all needed validation, and
* {@link ArgConsumer#getDatatype(Class)} will handle RuntimeExceptions and translate them into
* {@link CommandInvalidArgumentException}s. There must always be a constructor with no arguments so that
* {@link ArgConsumer} can create an instance for tab completion.
*/
public interface IDatatype {
Stream<String> tabComplete(ArgConsumer consumer);
}

View File

@ -0,0 +1,5 @@
package baritone.api.utils.command.datatypes;
public interface IDatatypeFor<T> extends IDatatype {
T get();
}

View File

@ -0,0 +1,5 @@
package baritone.api.utils.command.datatypes;
public interface IDatatypePost<T, O> extends IDatatype {
T apply(O original);
}

View File

@ -0,0 +1,53 @@
package baritone.api.utils.command.datatypes;
import baritone.api.BaritoneAPI;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper;
import net.minecraft.entity.player.EntityPlayer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Objects.isNull;
public class PlayerByUsername implements IDatatypeFor<EntityPlayer> {
private final List<EntityPlayer> players =
BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().world().playerEntities;
public final EntityPlayer player;
public PlayerByUsername() {
player = null;
}
public PlayerByUsername(ArgConsumer consumer) {
String username = consumer.getS();
if (isNull(
player = players
.stream()
.filter(s -> s.getName().equalsIgnoreCase(username))
.findFirst()
.orElse(null)
)) {
throw new RuntimeException("no player found by that username");
}
}
@Override
public EntityPlayer get() {
return player;
}
@Override
public Stream<String> tabComplete(ArgConsumer consumer) {
return new TabCompleteHelper()
.append(
players
.stream()
.map(EntityPlayer::getName)
)
.filterPrefix(consumer.getS())
.sortAlphabetically()
.stream();
}
}

View File

@ -0,0 +1,54 @@
package baritone.api.utils.command.datatypes;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.stream.Stream;
import static java.util.Objects.isNull;
public class RelativeBlockPos implements IDatatypePost<BetterBlockPos, BetterBlockPos> {
final RelativeCoordinate x;
final RelativeCoordinate y;
final RelativeCoordinate z;
public RelativeBlockPos() {
x = null;
y = null;
z = null;
}
public RelativeBlockPos(ArgConsumer consumer) {
x = consumer.getDatatype(RelativeCoordinate.class);
y = consumer.getDatatype(RelativeCoordinate.class);
z = consumer.getDatatype(RelativeCoordinate.class);
}
@Override
public BetterBlockPos apply(BetterBlockPos origin) {
return new BetterBlockPos(
x.apply((double) origin.x),
y.apply((double) origin.y),
z.apply((double) origin.z)
);
}
@Override
public Stream<String> tabComplete(ArgConsumer consumer) {
if (consumer.has() && !consumer.has(4)) {
while (consumer.has(2)) {
if (isNull(consumer.peekDatatypeOrNull(RelativeCoordinate.class))) {
break;
}
consumer.get();
if (!consumer.has(2)) {
return consumer.tabCompleteDatatype(RelativeCoordinate.class);
}
}
}
return Stream.empty();
}
}

View File

@ -0,0 +1,57 @@
package baritone.api.utils.command.datatypes;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import net.minecraft.util.math.MathHelper;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
public class RelativeCoordinate implements IDatatypePost<Double, Double> {
public static Pattern PATTERN = Pattern.compile("^(~?)([+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)|)$");
final boolean isRelative;
final double offset;
public RelativeCoordinate() {
isRelative = true;
offset = 0;
}
public RelativeCoordinate(ArgConsumer consumer) {
if (!consumer.has()) {
throw new RuntimeException("relative coordinate requires an argument");
}
Matcher matcher = PATTERN.matcher(consumer.getS());
if (!matcher.matches()) {
throw new RuntimeException("pattern doesn't match");
}
isRelative = !matcher.group(1).isEmpty();
offset = matcher.group(2).isEmpty() ? 0 : Double.parseDouble(matcher.group(2));
}
@Override
public Double apply(Double origin) {
if (isRelative) {
return origin + offset;
}
return offset;
}
public int applyFloor(double origin) {
return MathHelper.floor(apply(origin));
}
@Override
public Stream<String> tabComplete(ArgConsumer consumer) {
if (!consumer.has(2) && consumer.getS().matches("^(~|$)")) {
return Stream.of("~");
}
return Stream.empty();
}
}

View File

@ -0,0 +1,51 @@
package baritone.api.utils.command.datatypes;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.io.File;
import java.nio.file.FileSystems;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Locale;
import java.util.Objects;
import java.util.stream.Stream;
public class RelativeFile implements IDatatypePost<File, File> {
private final Path path;
public RelativeFile() {
path = null;
}
public RelativeFile(ArgConsumer consumer) {
try {
path = FileSystems.getDefault().getPath(consumer.getS());
} catch (InvalidPathException e) {
throw new RuntimeException("invalid path");
}
}
@Override
public Stream<String> tabComplete(ArgConsumer consumer) {
return Stream.empty();
}
public static Stream<String> tabComplete(ArgConsumer consumer, File base) {
String currentPathStringThing = consumer.getS();
Path currentPath = FileSystems.getDefault().getPath(currentPathStringThing);
Path basePath = currentPath.isAbsolute() ? currentPath.getRoot() : base.toPath();
boolean useParent = !currentPathStringThing.isEmpty() && !currentPathStringThing.endsWith(File.separator);
File currentFile = currentPath.isAbsolute() ? currentPath.toFile() : new File(base, currentPathStringThing);
return Arrays.stream(Objects.requireNonNull((useParent ? currentFile.getParentFile() : currentFile).listFiles()))
.map(f -> (currentPath.isAbsolute() ? f : basePath.relativize(f.toPath()).toString()) +
(f.isDirectory() ? File.separator : ""))
.filter(s -> s.toLowerCase(Locale.US).startsWith(currentPathStringThing.toLowerCase(Locale.US)));
}
@Override
public File apply(File original) {
return original.toPath().resolve(path).toFile();
}
}

View File

@ -0,0 +1,64 @@
package baritone.api.utils.command.datatypes;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.pathing.goals.GoalXZ;
import baritone.api.pathing.goals.GoalYLevel;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Objects.nonNull;
public class RelativeGoal implements IDatatypePost<Goal, BetterBlockPos> {
final RelativeCoordinate[] coords;
public RelativeGoal() {
coords = new RelativeCoordinate[0];
}
public RelativeGoal(ArgConsumer consumer) {
List<RelativeCoordinate> coordsList = new ArrayList<>();
for (int i = 0; i < 3; i++) {
if (nonNull(consumer.peekDatatypeOrNull(RelativeCoordinate.class))) {
coordsList.add(consumer.getDatatype(RelativeCoordinate.class));
}
}
coords = coordsList.toArray(new RelativeCoordinate[0]);
}
@Override
public Goal apply(BetterBlockPos origin) {
switch (coords.length) {
case 0:
return new GoalBlock(origin);
case 1:
return new GoalYLevel(
coords[0].applyFloor(origin.y)
);
case 2:
return new GoalXZ(
coords[0].applyFloor(origin.x),
coords[1].applyFloor(origin.z)
);
case 3:
return new GoalBlock(
coords[0].applyFloor(origin.x),
coords[1].applyFloor(origin.y),
coords[2].applyFloor(origin.z)
);
default:
throw new IllegalStateException("Unexpected coords size: " + coords.length);
}
}
@Override
public Stream<String> tabComplete(ArgConsumer consumer) {
return consumer.tabCompleteDatatype(RelativeCoordinate.class);
}
}

View File

@ -0,0 +1,42 @@
package baritone.api.utils.command.datatypes;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.stream.Stream;
public class RelativeGoalBlock implements IDatatypePost<GoalBlock, BetterBlockPos> {
final RelativeCoordinate[] coords;
public RelativeGoalBlock() {
coords = new RelativeCoordinate[0];
}
public RelativeGoalBlock(ArgConsumer consumer) {
coords = new RelativeCoordinate[] {
consumer.getDatatype(RelativeCoordinate.class),
consumer.getDatatype(RelativeCoordinate.class),
consumer.getDatatype(RelativeCoordinate.class)
};
}
@Override
public GoalBlock apply(BetterBlockPos origin) {
return new GoalBlock(
coords[0].applyFloor(origin.x),
coords[1].applyFloor(origin.y),
coords[2].applyFloor(origin.z)
);
}
@Override
public Stream<String> tabComplete(ArgConsumer consumer) {
if (consumer.hasAtMost(3)) {
return consumer.tabCompleteDatatype(RelativeCoordinate.class);
}
return Stream.empty();
}
}

View File

@ -0,0 +1,40 @@
package baritone.api.utils.command.datatypes;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalXZ;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.stream.Stream;
public class RelativeGoalXZ implements IDatatypePost<GoalXZ, BetterBlockPos> {
final RelativeCoordinate[] coords;
public RelativeGoalXZ() {
coords = new RelativeCoordinate[0];
}
public RelativeGoalXZ(ArgConsumer consumer) {
coords = new RelativeCoordinate[] {
consumer.getDatatype(RelativeCoordinate.class),
consumer.getDatatype(RelativeCoordinate.class)
};
}
@Override
public GoalXZ apply(BetterBlockPos origin) {
return new GoalXZ(
coords[0].applyFloor(origin.x),
coords[1].applyFloor(origin.z)
);
}
@Override
public Stream<String> tabComplete(ArgConsumer consumer) {
if (consumer.hasAtMost(2)) {
return consumer.tabCompleteDatatype(RelativeCoordinate.class);
}
return Stream.empty();
}
}

View File

@ -0,0 +1,34 @@
package baritone.api.utils.command.datatypes;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalYLevel;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.stream.Stream;
public class RelativeGoalYLevel implements IDatatypePost<GoalYLevel, BetterBlockPos> {
final RelativeCoordinate coord;
public RelativeGoalYLevel() {
coord = null;
}
public RelativeGoalYLevel(ArgConsumer consumer) {
coord = consumer.getDatatype(RelativeCoordinate.class);
}
@Override
public GoalYLevel apply(BetterBlockPos origin) {
return new GoalYLevel(coord.applyFloor(origin.y));
}
@Override
public Stream<String> tabComplete(ArgConsumer consumer) {
if (consumer.hasAtMost(1)) {
return consumer.tabCompleteDatatype(RelativeCoordinate.class);
}
return Stream.empty();
}
}

View File

@ -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 Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalAxis;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class AxisCommand extends Command {
public AxisCommand() {
super(asList("axis", "highway"), "Set a goal to the axes");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
Goal goal = new GoalAxis();
baritone.getCustomGoalProcess().setGoal(goal);
logDirect(String.format("Goal: %s", goal.toString()));
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The axis command sets a goal that tells Baritone to head towards the nearest axis. That is, X=0 or Z=0.",
"",
"Usage:",
"> axis"
);
}
}

View File

@ -0,0 +1,66 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.process.IGetToBlockProcess;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.exception.CommandInvalidStateException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class BlacklistCommand extends Command {
public BlacklistCommand() {
super("blacklist", "Blacklist closest block");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
IGetToBlockProcess proc = baritone.getGetToBlockProcess();
if (!proc.isActive()) {
throw new CommandInvalidStateException("GetToBlockProcess is not currently active");
}
if (proc.blacklistClosest()) {
logDirect("Blacklisted closest instances");
} else {
throw new CommandInvalidStateException("No known locations, unable to blacklist");
}
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"While, for example, mining, this command blacklists the closest block so that Baritone won't attempt to get to it.",
"",
"Usage:",
"> blacklist"
);
}
}

View File

@ -0,0 +1,81 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.datatypes.RelativeBlockPos;
import baritone.api.utils.command.exception.CommandInvalidStateException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class BuildCommand extends Command {
public BuildCommand() {
super("build", "Build a schematic");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
String filename = String.format("%s.schematic", args.getS());
BetterBlockPos origin = ctx.playerFeet();
BetterBlockPos buildOrigin;
if (args.has()) {
args.requireMax(3);
buildOrigin = args.getDatatype(RelativeBlockPos.class).apply(origin);
} else {
args.requireMax(0);
buildOrigin = origin;
}
boolean success = baritone.getBuilderProcess().build(filename, buildOrigin);
if (!success) {
throw new CommandInvalidStateException("Couldn't load the schematic");
}
logDirect(String.format("Successfully loaded schematic '%s' for building\nOrigin: %s", filename, buildOrigin));
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
if (args.has(2)) {
args.get();
return args.tabCompleteDatatype(RelativeBlockPos.class);
}
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"Build a schematic from a file.",
"",
"Usage:",
"> build <filename> - Loads and builds '<filename>.schematic'",
"> build <filename> <x> <y> <z> - Custom position"
);
}
}

View File

@ -0,0 +1,55 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class CancelCommand extends Command {
public CancelCommand() {
super(asList("cancel", "stop"), "Cancel what Baritone is currently doing");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
baritone.getPathingBehavior().cancelEverything();
logDirect("ok canceled");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The cancel command tells Baritons to stop whatever it's currently doing.",
"",
"Usage:",
"> cancel"
);
}
}

View File

@ -0,0 +1,79 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.cache.IRememberedInventory;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.exception.CommandInvalidStateException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.ITextComponent;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class ChestsCommand extends Command {
public ChestsCommand() {
super("chests", "Display remembered inventories");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
Set<Map.Entry<BlockPos, IRememberedInventory>> entries =
ctx.worldData().getContainerMemory().getRememberedInventories().entrySet();
if (entries.isEmpty()) {
throw new CommandInvalidStateException("No remembered inventories");
}
for (Map.Entry<BlockPos, IRememberedInventory> entry : entries) {
BlockPos pos = entry.getKey();
IRememberedInventory inv = entry.getValue();
logDirect(pos.toString());
for (ItemStack item : inv.getContents()) {
ITextComponent component = item.getTextComponent();
component.appendText(String.format(" x %d", item.getCount()));
logDirect(component);
}
}
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The chests command lists remembered inventories, I guess?",
"",
"Usage:",
"> chests"
);
}
}

View File

@ -0,0 +1,78 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.datatypes.RelativeBlockPos;
import baritone.api.utils.command.exception.CommandInvalidStateException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class ClearareaCommand extends Command {
public ClearareaCommand() {
super("cleararea", "Clear an area of all blocks");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
BetterBlockPos pos1 = ctx.playerFeet();
BetterBlockPos pos2;
if (args.has()) {
args.requireMax(3);
pos2 = args.getDatatype(RelativeBlockPos.class).apply(pos1);
} else {
args.requireMax(0);
Goal goal = baritone.getCustomGoalProcess().getGoal();
if (!(goal instanceof GoalBlock)) {
throw new CommandInvalidStateException("Goal is not a GoalBlock");
} else {
pos2 = new BetterBlockPos(((GoalBlock) goal).getGoalPos());
}
}
baritone.getBuilderProcess().clearArea(pos1, pos2);
logDirect("Success");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return args.tabCompleteDatatype(RelativeBlockPos.class);
}
@Override
public List<String> getLongDesc() {
return asList(
"Clear an area of all blocks.",
"",
"Usage:",
"> cleararea - Clears the area marked by your current position and the current GoalBlock",
"> cleararea <x> <y> <z> - Custom second corner rather than your goal"
);
}
}

View File

@ -0,0 +1,68 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.exception.CommandInvalidStateException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Objects.isNull;
public class ComeCommand extends Command {
public ComeCommand() {
super("come", "Start heading towards your camera");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
Entity entity = MC.getRenderViewEntity();
if (isNull(entity)) {
throw new CommandInvalidStateException("render view entity is null");
}
baritone.getCustomGoalProcess().setGoalAndPath(new GoalBlock(new BlockPos(entity)));
logDirect("Coming");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The come command tells Baritone to head towards your camera.",
"",
"I'm... not actually sure how useful this is, to be honest.",
"",
"Usage:",
"> come"
);
}
}

View File

@ -0,0 +1,56 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import baritone.api.utils.command.manager.CommandManager;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
public class CommandAlias extends Command {
public final String target;
public CommandAlias(List<String> names, String shortDesc, String target) {
super(names, shortDesc);
this.target = target;
}
public CommandAlias(String name, String shortDesc, String target) {
super(name, shortDesc);
this.target = target;
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
CommandManager.execute(String.format("%s %s", target, args.rawRest()));
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return CommandManager.tabComplete(String.format("%s %s", target, args.rawRest()));
}
@Override
public List<String> getLongDesc() {
return Collections.singletonList(String.format("This command is an alias, for: %s ...", target));
}
}

View 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 Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.utils.command.Command;
import java.util.Collections;
import java.util.List;
import static java.util.Arrays.asList;
public class DefaultCommands {
public static final List<Command> commands = Collections.unmodifiableList(asList(
new HelpCommand(),
new SetCommand(),
new CommandAlias(asList("modified", "mod", "baritone", "modifiedsettings"), "List modified settings", "set modified"),
new CommandAlias("reset", "Reset all settings or just one", "set reset"),
new ExcCommand(), // TODO: remove this debug command... eventually
new GoalCommand(),
new PathCommand(),
new ProcCommand(),
new VersionCommand(),
new RepackCommand(),
new BuildCommand(),
new SchematicaCommand(),
new ComeCommand(),
new AxisCommand(),
new CancelCommand(),
new ForceCancelCommand(),
new GcCommand(),
new InvertCommand(),
new ClearareaCommand(),
PauseResumeCommands.pauseCommand,
PauseResumeCommands.resumeCommand,
PauseResumeCommands.pausedCommand,
new TunnelCommand(),
new RenderCommand(),
new FarmCommand(),
new ChestsCommand(),
new FollowCommand(),
new ExploreFilterCommand(),
new ReloadAllCommand(),
new SaveAllCommand(),
new ExploreCommand(),
new BlacklistCommand(),
new FindCommand(),
new MineCommand()
));
}

View File

@ -0,0 +1,54 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.Helper;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class EmptyCommand extends Command {
public EmptyCommand() {
super(asList("name1", "name2"), "Short description");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
;
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"",
"",
"Usage:",
"> "
);
}
}

View 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 Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.Collections;
import java.util.List;
import java.util.stream.Stream;
public class ExcCommand extends Command {
public ExcCommand() {
super("exc", "Throw an unhandled exception");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
throw new RuntimeException("HI THERE");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return Collections.emptyList();
}
}

View File

@ -0,0 +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 Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.pathing.goals.GoalXZ;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.datatypes.RelativeGoalXZ;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class ExploreCommand extends Command {
public ExploreCommand() {
super("explore", "Explore things");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
if (args.has()) {
args.requireExactly(2);
} else {
args.requireMax(0);
}
GoalXZ goal = args.has()
? args.getDatatypePost(RelativeGoalXZ.class, ctx.playerFeet())
: new GoalXZ(ctx.playerFeet());
baritone.getExploreProcess().explore(goal.getX(), goal.getZ());
logDirect(String.format("Exploring from %s", goal.toString()));
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
if (args.hasAtMost(2)) {
return args.tabCompleteDatatype(RelativeGoalXZ.class);
}
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"Tell Baritone to explore randomly. If you used explorefilter before this, it will be applied.",
"",
"Usage:",
"> explore - Explore from your current position.",
"> explore <x> <z> - Explore from the specified X and Z position."
);
}
}

View File

@ -0,0 +1,89 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.datatypes.RelativeFile;
import baritone.api.utils.command.exception.CommandInvalidStateException;
import baritone.api.utils.command.exception.CommandInvalidTypeException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import com.google.gson.JsonSyntaxException;
import java.io.File;
import java.nio.file.NoSuchFileException;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class ExploreFilterCommand extends Command {
public ExploreFilterCommand() {
super("explorefilter", "Explore chunks from a json");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(2);
File file = args.getDatatypePost(RelativeFile.class, MC.gameDir.getAbsoluteFile().getParentFile());
boolean invert = false;
if (args.has()) {
if (args.getS().equalsIgnoreCase("invert")) {
invert = true;
} else {
throw new CommandInvalidTypeException(args.consumed(), "either \"invert\" or nothing");
}
}
try {
baritone.getExploreProcess().applyJsonFilter(file.toPath().toAbsolutePath(), invert);
} catch (NoSuchFileException e) {
throw new CommandInvalidStateException("File not found");
} catch (JsonSyntaxException e) {
throw new CommandInvalidStateException("Invalid JSON syntax");
} catch (Exception e) {
throw new RuntimeException(e);
}
logDirect(String.format("Explore filter applied. Inverted: %s", Boolean.toString(invert)));
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
if (args.hasExactlyOne()) {
return RelativeFile.tabComplete(args, MC.gameDir.getAbsoluteFile().getParentFile());
}
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"Apply an explore filter before using explore, which tells the explore process which chunks have been explored/not explored.",
"",
"The JSON file will follow this format: [{\"x\":0,\"z\":0},...]",
"",
"If 'invert' is specified, the chunks listed will be considered NOT explored, rather than explored.",
"",
"Usage:",
"> explorefilter <path> [invert] - Load the JSON file referenced by the specified path. If invert is specified, it must be the literal word 'invert'."
);
}
}

View File

@ -0,0 +1,55 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class FarmCommand extends Command {
public FarmCommand() {
super("farm", "Farm nearby crops");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
baritone.getFarmProcess().farm();
logDirect("Farming");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The farm command starts farming nearby plants. It harvests mature crops and plants new ones.",
"",
"Usage:",
"> farm"
);
}
}

View File

@ -0,0 +1,77 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.datatypes.BlockById;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import net.minecraft.block.Block;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class FindCommand extends Command {
public FindCommand() {
super("find", "Find positions of a certain block");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
List<Block> toFind = new ArrayList<>();
while (args.has()) {
toFind.add(args.getDatatypeFor(BlockById.class));
}
BetterBlockPos origin = ctx.playerFeet();
toFind.stream()
.flatMap(block ->
ctx.worldData().getCachedWorld().getLocationsOf(
Block.REGISTRY.getNameForObject(block).getPath(),
Integer.MAX_VALUE,
origin.x,
origin.y,
4
).stream()
)
.map(BetterBlockPos::new)
.map(BetterBlockPos::toString)
.forEach(this::logDirect);
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return args.tabCompleteDatatype(BlockById.class);
}
@Override
public List<String> getLongDesc() {
return asList(
"",
"",
"Usage:",
"> "
);
}
}

View File

@ -0,0 +1,171 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.datatypes.EntityClassById;
import baritone.api.utils.command.datatypes.IDatatype;
import baritone.api.utils.command.datatypes.IDatatypeFor;
import baritone.api.utils.command.datatypes.PlayerByUsername;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityList;
import net.minecraft.entity.EntityLiving;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.util.ResourceLocation;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Objects;
import java.util.function.Predicate;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
public class FollowCommand extends Command {
public FollowCommand() {
super("follow", "Follow entity things");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMin(1);
FollowGroup group;
FollowList list;
List<Entity> entities = new ArrayList<>();
List<Class<? extends Entity>> classes = new ArrayList<>();
if (args.hasExactlyOne()) {
baritone.getFollowProcess().follow((group = args.getE(FollowGroup.class)).filter);
list = null;
} else {
args.requireMin(2);
group = null;
list = args.getE(FollowList.class);
while (args.has()) {
//noinspection unchecked
Object gotten = args.getDatatypeFor(list.datatype);
if (gotten instanceof Class) {
//noinspection unchecked
classes.add((Class<? extends Entity>) gotten);
} else {
entities.add((Entity) gotten);
}
}
baritone.getFollowProcess().follow(
classes.isEmpty()
? entities::contains
: e -> classes.stream().anyMatch(c -> c.isInstance(e))
);
}
if (nonNull(group)) {
logDirect(String.format("Following all %s", group.name().toLowerCase(Locale.US)));
} else {
logDirect("Following these types of entities:");
if (classes.isEmpty()) {
entities.stream()
.map(Entity::toString)
.forEach(this::logDirect);
} else {
classes.stream()
.map(EntityList::getKey)
.map(Objects::requireNonNull)
.map(ResourceLocation::toString)
.forEach(this::logDirect);
}
}
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
if (args.hasExactlyOne()) {
return new TabCompleteHelper()
.append(FollowGroup.class)
.append(FollowList.class)
.filterPrefix(args.getS())
.stream();
} else {
Class<? extends IDatatype> followType;
try {
followType = args.getE(FollowList.class).datatype;
} catch (NullPointerException e) {
return Stream.empty();
}
while (args.has(2)) {
if (isNull(args.peekDatatypeOrNull(followType))) {
return Stream.empty();
}
args.get();
}
return args.tabCompleteDatatype(followType);
}
}
@Override
public List<String> getLongDesc() {
return asList(
"The follow command tells Baritone to follow certain kinds of entities.",
"",
"Usage:",
"> follow entities - Follows all entities.",
"> follow entity <entity1> <entity2> <...> - Follow certain entities (for example 'skeleton', 'horse' etc.)",
"> follow players - Follow players",
"> follow player <username1> <username2> <...> - Follow certain players"
);
}
private enum FollowGroup {
ENTITIES(EntityLiving.class::isInstance),
PLAYERS(EntityPlayer.class::isInstance); /* ,
FRIENDLY(entity -> entity.getAttackTarget() != HELPER.mc.player),
HOSTILE(FRIENDLY.filter.negate()); */
final Predicate<Entity> filter;
FollowGroup(Predicate<Entity> filter) {
this.filter = filter;
}
}
private enum FollowList {
ENTITY(EntityClassById.class),
PLAYER(PlayerByUsername.class);
final Class<? extends IDatatypeFor> datatype;
FollowList(Class<? extends IDatatypeFor> datatype) {
this.datatype = datatype;
}
}
}

View File

@ -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 Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.behavior.IPathingBehavior;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class ForceCancelCommand extends Command {
public ForceCancelCommand() {
super("forcecancel", "Force cancel");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
IPathingBehavior pathingBehavior = baritone.getPathingBehavior();
pathingBehavior.cancelEverything();
pathingBehavior.forceCancel();
logDirect("ok force canceled");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"Like cancel, but more forceful.",
"",
"Usage:",
"> forcecancel"
);
}
}

View File

@ -0,0 +1,57 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class GcCommand extends Command {
public GcCommand() {
super("gc", "Call System.gc()");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
System.gc();
logDirect("ok called System.gc()");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"Calls System.gc().",
"",
"Usage:",
"> gc"
);
}
}

View File

@ -0,0 +1,104 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.pathing.goals.Goal;
import baritone.api.process.ICustomGoalProcess;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.datatypes.RelativeCoordinate;
import baritone.api.utils.command.datatypes.RelativeGoal;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
public class GoalCommand extends Command {
public GoalCommand() {
super("goal", "Set or clear the goal");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
ICustomGoalProcess goalProcess = baritone.getCustomGoalProcess();
if (args.has() && asList("reset", "clear", "none").contains(args.peekS())) {
args.requireMax(1);
if (nonNull(goalProcess.getGoal())) {
goalProcess.setGoal(null);
logDirect("Cleared goal");
} else {
logDirect("There was no goal to clear");
}
} else {
args.requireMax(3);
BetterBlockPos origin = baritone.getPlayerContext().playerFeet();
Goal goal = args.getDatatype(RelativeGoal.class).apply(origin);
goalProcess.setGoal(goal);
logDirect(String.format("Goal: %s", goal.toString()));
}
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
TabCompleteHelper helper = new TabCompleteHelper();
if (args.hasExactlyOne()) {
helper.append(Stream.of("reset", "clear", "none", "~"));
} else {
if (args.hasAtMost(3)) {
while (args.has(2)) {
if (isNull(args.peekDatatypeOrNull(RelativeCoordinate.class))) {
break;
}
args.get();
if (!args.has(2)) {
helper.append("~");
}
}
}
}
return helper.filterPrefix(args.getS()).stream();
}
@Override
public List<String> getLongDesc() {
return asList(
"The goal command allows you to set or clear Baritone's goal.",
"",
"Wherever a coordinate is expected, you can use ~ just like in regular Minecraft commands. Or, you can just use regular numbers.",
"",
"Usage:",
"> goal - Set the goal to your current position",
"> goal <reset/clear/none> - Erase the goal",
"> goal <y> - Set the goal to a Y level",
"> goal <x> <z> - Set the goal to an X,Z position",
"> goal <x> <y> <z> - Set the goal to an X,Y,Z position"
);
}
}

View File

@ -0,0 +1,131 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.exception.CommandNotFoundException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import baritone.api.utils.command.helpers.pagination.Paginator;
import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper;
import baritone.api.utils.command.manager.CommandManager;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.event.ClickEvent;
import net.minecraft.util.text.event.HoverEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static baritone.api.utils.command.BaritoneChatControl.FORCE_COMMAND_PREFIX;
import static baritone.api.utils.command.manager.CommandManager.getCommand;
import static java.util.Arrays.asList;
import static java.util.Objects.isNull;
public class HelpCommand extends Command {
public HelpCommand() {
super(asList("help", "?"), "View all commands or help on specific ones");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(1);
if (!args.has() || args.is(Integer.class)) {
Paginator.paginate(
args, new Paginator<>(
CommandManager.REGISTRY.descendingStream()
.filter(command -> !command.hiddenFromHelp())
.collect(Collectors.toCollection(ArrayList::new))
),
() -> logDirect("All Baritone commands (clickable):"),
command -> {
String names = String.join("/", command.names);
String name = command.names.get(0);
return new TextComponentString(name) {{
getStyle()
.setColor(TextFormatting.GRAY)
.setHoverEvent(new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new TextComponentString("") {{
getStyle().setColor(TextFormatting.GRAY);
appendSibling(new TextComponentString(names + "\n") {{
getStyle().setColor(TextFormatting.WHITE);
}});
appendText(command.shortDesc);
appendText("\n\nClick to view full help");
}}
))
.setClickEvent(new ClickEvent(
ClickEvent.Action.RUN_COMMAND,
FORCE_COMMAND_PREFIX + String.format("help %s", command.names.get(0))
));
appendSibling(new TextComponentString(" - " + command.shortDesc) {{
getStyle().setColor(TextFormatting.DARK_GRAY);
}});
}};
},
FORCE_COMMAND_PREFIX + "help %d"
);
} else {
String commandName = args.getS().toLowerCase();
Command command = getCommand(commandName);
if (isNull(command)) {
throw new CommandNotFoundException(commandName);
}
logDirect(String.format("%s - %s", String.join(" / ", command.names), command.shortDesc));
logDirect("");
command.getLongDesc().forEach(this::logDirect);
logDirect("");
logDirect(new TextComponentString("Click to return to the help menu") {{
getStyle().setClickEvent(new ClickEvent(
ClickEvent.Action.RUN_COMMAND,
FORCE_COMMAND_PREFIX + "help"
));
}});
}
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
if (args.hasExactlyOne()) {
return new TabCompleteHelper().addCommands().filterPrefix(args.getS()).stream();
}
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"Using this command, you can view detailed help information on how to use certain commands of Baritone.",
"",
"Usage:",
"> help - Lists all commands and their short descriptions.",
"> help <command> - Displays help information on a specific command."
);
}
}

View File

@ -0,0 +1,74 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalInverted;
import baritone.api.process.ICustomGoalProcess;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.exception.CommandInvalidStateException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Objects.isNull;
public class InvertCommand extends Command {
public InvertCommand() {
super("invert", "Run away from the current goal");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess();
Goal goal;
if (isNull(goal = customGoalProcess.getGoal())) {
throw new CommandInvalidStateException("No goal");
}
if (goal instanceof GoalInverted) {
goal = ((GoalInverted) goal).origin;
} else {
goal = new GoalInverted(goal);
}
customGoalProcess.setGoal(goal);
logDirect(String.format("Goal: %s", goal.toString()));
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The invert command tells Baritone to head away from the current goal rather than towards it.",
"",
"Usage:",
"> invert - Invert the current goal."
);
}
}

View File

@ -0,0 +1,69 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.BlockSelector;
import baritone.api.utils.CompositeBlockFilter;
import baritone.api.utils.IBlockFilter;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.datatypes.BlockById;
import baritone.api.utils.command.datatypes.ForBlockSelector;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class MineCommand extends Command {
public MineCommand() {
super("mine", "Mine some blocks");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
int quantity = args.getAsOrDefault(Integer.class, 0);
args.requireMin(1);
List<BlockSelector> selectors = new ArrayList<>();
while (args.has()) {
selectors.add(args.getDatatypeFor(ForBlockSelector.class));
}
IBlockFilter filter = new CompositeBlockFilter(selectors);
baritone.getMineProcess().mine(quantity, filter);
logDirect(String.format("Mining %s", filter.toString()));
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return args.tabCompleteDatatype(BlockById.class);
}
@Override
public List<String> getLongDesc() {
return asList(
"",
"",
"Usage:",
"> "
);
}
}

View File

@ -0,0 +1,92 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.pathing.goals.Goal;
import baritone.api.process.ICustomGoalProcess;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.datatypes.RelativeCoordinate;
import baritone.api.utils.command.datatypes.RelativeGoal;
import baritone.api.utils.command.exception.CommandInvalidStateException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Objects.isNull;
public class PathCommand extends Command {
public PathCommand() {
super("path", "Start heading towards a goal");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess();
Goal goal;
if (args.has()) {
args.requireMax(3);
goal = args.getDatatype(RelativeGoal.class).apply(ctx.playerFeet());
} else if (isNull(goal = customGoalProcess.getGoal())) {
throw new CommandInvalidStateException("No goal");
}
args.requireMax(0);
customGoalProcess.setGoalAndPath(goal);
logDirect("Now pathing");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
if (args.has() && !args.has(4)) {
while (args.has(2)) {
if (isNull(args.peekDatatypeOrNull(RelativeCoordinate.class))) {
break;
}
args.get();
if (!args.has(2)) {
return new TabCompleteHelper()
.append("~")
.filterPrefix(args.getS())
.stream();
}
}
}
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The path command tells Baritone to head towards the current goal.",
"",
"Usage:",
"> path - Start the pathing.",
"> path <y>",
"> path <x> <z>",
"> path <x> <y> <z> - Define the goal here"
);
}
}

View File

@ -0,0 +1,150 @@
package baritone.api.utils.command.defaults;
import baritone.api.BaritoneAPI;
import baritone.api.Settings;
import baritone.api.process.IBaritoneProcess;
import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.exception.CommandInvalidStateException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
/**
* Contains the pause, resume, and paused commands.
*
* This thing is scoped to hell, private so far you can't even access it using reflection, because you AREN'T SUPPOSED
* TO USE THIS to pause and resume Baritone. Make your own process that returns {@link PathingCommandType#REQUEST_PAUSE
* REQUEST_PAUSE}
* as needed.
*/
public class PauseResumeCommands {
public static Command pauseCommand;
public static Command resumeCommand;
public static Command pausedCommand;
static {
final boolean[] paused = {false};
BaritoneAPI.getProvider().getPrimaryBaritone().getPathingControlManager().registerProcess(
new IBaritoneProcess() {
@Override
public boolean isActive() {
return paused[0];
}
@Override
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
}
@Override
public boolean isTemporary() {
return true;
}
@Override
public void onLostControl() {
}
@Override
public double priority() {
return DEFAULT_PRIORITY + 1;
}
@Override
public String displayName0() {
return "Pause/Resume Commands";
}
}
);
pauseCommand = new Command("pause", "Pauses Baritone until you use resume") {
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
if (paused[0]) {
throw new CommandInvalidStateException("Already paused");
}
paused[0] = true;
logDirect("Paused");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The pause command tells Baritone to temporarily stop whatever it's doing.",
"",
"This can be used to pause pathing, building, following, whatever. A single use of the resume command will start it right back up again!",
"",
"Usage:",
"> pause"
);
}
};
resumeCommand = new Command("resume", "Resumes Baritone after a pause") {
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
if (!paused[0]) {
throw new CommandInvalidStateException("Not paused");
}
paused[0] = false;
logDirect("Resumed");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The resume command tells Baritone to resume whatever it was doing when you last used pause.",
"",
"Usage:",
"> resume"
);
}
};
pausedCommand = new Command("paused", "Tells you if Baritone is paused") {
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
logDirect(String.format("Baritone is %spaused", paused[0] ? "" : "not "));
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The paused command tells you if Baritone is currently paused by use of the pause command.",
"",
"Usage:",
"> paused"
);
}
};
}
}

View File

@ -0,0 +1,83 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.pathing.calc.IPathingControlManager;
import baritone.api.process.IBaritoneProcess;
import baritone.api.process.PathingCommand;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.exception.CommandInvalidStateException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Objects.isNull;
public class ProcCommand extends Command {
public ProcCommand() {
super("proc", "View process state information");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
IPathingControlManager pathingControlManager = baritone.getPathingControlManager();
IBaritoneProcess process = pathingControlManager.mostRecentInControl().orElse(null);
if (isNull(process)) {
throw new CommandInvalidStateException("No process in control");
}
logDirect(String.format(
"Class: %s\n" +
"Priority: %s\n" +
"Temporary: %s\n" +
"Display name: %s\n" +
"Last command: %s",
process.getClass().getTypeName(),
Double.toString(process.priority()),
Boolean.toString(process.isTemporary()),
process.displayName(),
pathingControlManager
.mostRecentCommand()
.map(PathingCommand::toString)
.orElse("None")
));
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The proc command provides miscellaneous information about the process currently controlling Baritone.",
"",
"You are not expected to understand this if you aren't familiar with how Baritone works.",
"",
"Usage:",
"> proc - View process information, if present"
);
}
}

View File

@ -0,0 +1,55 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class ReloadAllCommand extends Command {
public ReloadAllCommand() {
super("reloadall", "Reloads Baritone's cache for this world");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
ctx.worldData().getCachedWorld().reloadAllFromDisk();
logDirect("Reloaded");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The reloadall command reloads Baritone's world cache.",
"",
"Usage:",
"> reloadall"
);
}
}

View File

@ -0,0 +1,67 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class RenderCommand extends Command {
public RenderCommand() {
super("render", "Fix glitched chunks");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
BetterBlockPos origin = ctx.playerFeet();
int renderDistance = (MC.gameSettings.renderDistanceChunks + 1) * 16;
MC.renderGlobal.markBlockRangeForRenderUpdate(
origin.x - renderDistance,
0,
origin.z - renderDistance,
origin.x + renderDistance,
255,
origin.z + renderDistance
);
logDirect("Done");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The render command fixes glitched chunk rendering without having to reload all of them.",
"",
"Usage:",
"> render"
);
}
}

View File

@ -0,0 +1,78 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.cache.ICachedWorld;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.IChunkProvider;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Objects.nonNull;
public class RepackCommand extends Command {
public RepackCommand() {
super(asList("repack", "rescan"), "Re-cache chunks");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
IChunkProvider chunkProvider = ctx.world().getChunkProvider();
ICachedWorld cachedWorld = ctx.worldData().getCachedWorld();
BetterBlockPos playerPos = ctx.playerFeet();
int playerChunkX = playerPos.getX() >> 4;
int playerChunkZ = playerPos.getZ() >> 4;
int queued = 0;
for (int x = playerChunkX - 40; x <= playerChunkX + 40; x++) {
for (int z = playerChunkZ - 40; z <= playerChunkZ + 40; z++) {
Chunk chunk = chunkProvider.getLoadedChunk(x, z);
if (nonNull(chunk) && !chunk.isEmpty()) {
queued++;
cachedWorld.queueForPacking(chunk);
}
}
}
logDirect(String.format("Queued %d chunks for repacking", queued));
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"Repack chunks around you. This basically re-caches them.",
"",
"Usage:",
"> repack - Repack chunks."
);
}
}

View File

@ -0,0 +1,55 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class SaveAllCommand extends Command {
public SaveAllCommand() {
super("saveall", "Saves Baritone's cache for this world");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
ctx.worldData().getCachedWorld().save();
logDirect("Saved");
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The saveall command saves Baritone's world cache.",
"",
"Usage:",
"> saveall"
);
}
}

View File

@ -0,0 +1,54 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class SchematicaCommand extends Command {
public SchematicaCommand() {
super("schematica", "Opens a Schematica schematic?");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
baritone.getBuilderProcess().buildOpenSchematic();
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"I'm not actually sure what this does.",
"",
"Usage:",
"> schematica"
);
}
}

View File

@ -0,0 +1,275 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.exception.CommandInvalidTypeException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import baritone.api.utils.command.helpers.pagination.Paginator;
import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.event.ClickEvent;
import net.minecraft.util.text.event.HoverEvent;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static baritone.api.utils.SettingsUtil.settingDefaultToString;
import static baritone.api.utils.SettingsUtil.settingTypeToString;
import static baritone.api.utils.SettingsUtil.settingValueToString;
import static baritone.api.utils.command.BaritoneChatControl.FORCE_COMMAND_PREFIX;
import static java.util.Arrays.asList;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
import static java.util.stream.Stream.of;
public class SetCommand extends Command {
public SetCommand() {
super(asList("set", "setting", "settings"), "View or change settings");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
String arg = args.has() ? args.getS().toLowerCase(Locale.US) : "list";
boolean viewModified = asList("m", "mod", "modified").contains(arg);
boolean viewAll = asList("all", "l", "list").contains(arg);
boolean paginate = viewModified | viewAll;
if (paginate) {
String search = args.has() && args.peekAsOrNull(Integer.class) == null ? args.getS() : "";
args.requireMax(1);
List<? extends Settings.Setting> toPaginate =
viewModified
? SettingsUtil.modifiedSettings(settings)
: settings.allSettings.stream()
.filter(s -> !s.getName().equals("logger"))
.filter(s -> s.getName().toLowerCase(Locale.US).contains(search.toLowerCase(Locale.US)))
.collect(Collectors.toCollection(ArrayList<Settings.Setting>::new));
toPaginate.sort((setting1, setting2) -> String.CASE_INSENSITIVE_ORDER.compare(
setting1.getName(),
setting2.getName()
));
Paginator.paginate(
args,
new Paginator<>(toPaginate),
() -> logDirect(
!search.isEmpty()
? String.format("All settings containing the string '%s':", search)
: String.format("All %ssettings:", viewModified ? "modified " : "")
),
setting -> new TextComponentString(setting.getName()) {{
getStyle()
.setColor(TextFormatting.GRAY)
.setHoverEvent(new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new TextComponentString("") {{
getStyle().setColor(TextFormatting.GRAY);
appendText(setting.getName());
appendText(String.format("\nType: %s", settingTypeToString(setting)));
appendText(String.format("\n\nValue:\n%s", settingValueToString(setting)));
if (setting.value != setting.defaultValue) {
appendText(String.format("\n\nDefault:\n%s", settingDefaultToString(setting)));
}
}}
))
.setClickEvent(new ClickEvent(
ClickEvent.Action.SUGGEST_COMMAND,
settings.prefix.value + String.format("set %s ", setting.getName())
));
appendSibling(new TextComponentString(String.format(" (%s)", settingTypeToString(setting))) {{
getStyle().setColor(TextFormatting.DARK_GRAY);
}});
}},
FORCE_COMMAND_PREFIX + "set " + arg + " " + search + " %d"
);
return;
}
args.requireMax(1);
boolean resetting = arg.equalsIgnoreCase("reset");
boolean toggling = arg.equalsIgnoreCase("toggle");
boolean doingSomething = resetting || toggling;
if (resetting) {
if (!args.has()) {
logDirect("Please specify 'all' as an argument to reset to confirm you'd really like to do this");
logDirect("ALL settings will be reset. Use the 'set modified' or 'modified' commands to see what will be reset.");
logDirect("Specify a setting name instead of 'all' to only reset one setting");
} else if (args.peekS().equalsIgnoreCase("all")) {
SettingsUtil.modifiedSettings(settings).forEach(Settings.Setting::reset);
logDirect("All settings have been reset to their default values");
return;
}
}
if (toggling) {
args.requireMin(1);
}
String settingName = doingSomething ? args.getS() : arg;
Settings.Setting<?> setting = settings.allSettings.stream()
.filter(s -> s.getName().equalsIgnoreCase(settingName))
.findFirst()
.orElse(null);
if (isNull(setting)) {
throw new CommandInvalidTypeException(args.consumed(), "a valid setting");
}
if (!doingSomething && !args.has()) {
logDirect(String.format("Value of setting %s:", setting.getName()));
logDirect(settingValueToString(setting));
} else {
String oldValue = settingValueToString(setting);
if (resetting) {
setting.reset();
} else if (toggling) {
if (setting.getValueClass() != Boolean.class) {
throw new CommandInvalidTypeException(args.consumed(), "a toggleable setting", "some other setting");
}
//noinspection unchecked
((Settings.Setting<Boolean>) setting).value ^= true;
logDirect(String.format(
"Toggled setting %s to %s",
setting.getName(),
Boolean.toString((Boolean) setting.value)
));
} else {
String newValue = args.getS();
try {
SettingsUtil.parseAndApply(settings, arg, newValue);
} catch (Throwable t) {
t.printStackTrace();
throw new CommandInvalidTypeException(args.consumed(), "a valid value", t);
}
}
if (!toggling) {
logDirect(String.format(
"Successfully %s %s to %s",
resetting ? "reset" : "set",
setting.getName(),
settingValueToString(setting)
));
}
logDirect(new TextComponentString(String.format("Old value: %s", oldValue)) {{
getStyle()
.setColor(TextFormatting.GRAY)
.setHoverEvent(new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new TextComponentString("Click to set the setting back to this value")
))
.setClickEvent(new ClickEvent(
ClickEvent.Action.RUN_COMMAND,
FORCE_COMMAND_PREFIX + String.format("set %s %s", setting.getName(), oldValue)
));
}});
if ((setting.getName().equals("chatControl") && !(Boolean) setting.value && !settings.chatControlAnyway.value) ||
setting.getName().equals("chatControlAnyway") && !(Boolean) setting.value && !settings.chatControl.value) {
logDirect("Warning: Chat commands will no longer work. If you want to revert this change, use prefix control (if enabled) or click the old value listed above.", TextFormatting.RED);
} else if (setting.getName().equals("prefixControl") && !(Boolean) setting.value) {
logDirect("Warning: Prefixed commands will no longer work. If you want to revert this change, use chat control (if enabled) or click the old value listed above.", TextFormatting.RED);
}
}
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
if (args.has()) {
String arg = args.getS();
if (args.hasExactlyOne()) {
if (arg.equalsIgnoreCase("reset")) {
return new TabCompleteHelper()
.addModifiedSettings()
.prepend("all")
.filterPrefix(args.getS())
.stream();
} else if (arg.equalsIgnoreCase("toggle")) {
return new TabCompleteHelper()
.addToggleableSettings()
.filterPrefix(args.getS())
.stream();
}
Settings.Setting setting = settings.byLowerName.get(arg.toLowerCase(Locale.US));
if (nonNull(setting)) {
if (setting.getType() == Boolean.class) {
TabCompleteHelper helper = new TabCompleteHelper();
if ((Boolean) setting.value) {
helper.append(of("true", "false"));
} else {
helper.append(of("false", "true"));
}
return helper.filterPrefix(args.getS()).stream();
} else {
return Stream.of(settingValueToString(setting));
}
}
} else if (!args.has()) {
return new TabCompleteHelper()
.addSettings()
.sortAlphabetically()
.prepend("list", "modified", "reset", "toggle")
.filterPrefix(arg)
.stream();
}
}
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"Using the set command, you can manage all of Baritone's settings. Almost every aspect is controlled by these settings - go wild!",
"",
"Usage:",
"> set - Same as `set list`",
"> set list [page] - View all settings",
"> set modified [page] - View modified settings",
"> set <setting> - View the current value of a setting",
"> set <setting> <value> - Set the value of a setting",
"> set reset all - Reset ALL SETTINGS to their defaults",
"> set reset <setting> - Reset a setting to its default",
"> set toggle <setting> - Toggle a boolean setting"
);
}
}

View File

@ -0,0 +1,63 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalStrictDirection;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
public class TunnelCommand extends Command {
public TunnelCommand() {
super("tunnel", "Set a goal to tunnel in your current direction");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
Goal goal = new GoalStrictDirection(
ctx.playerFeet(),
ctx.player().getHorizontalFacing()
);
baritone.getCustomGoalProcess().setGoal(goal);
logDirect(String.format("Goal: %s", goal.toString()));
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The tunnel command sets a goal that tells Baritone to mine completely straight in the direction that you're facing.",
"",
"Usage:",
"> tunnel"
);
}
}

View File

@ -0,0 +1,63 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.exception.CommandInvalidStateException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Arrays.asList;
import static java.util.Objects.isNull;
public class VersionCommand extends Command {
public VersionCommand() {
super("version", "View the Baritone version");
}
@Override
protected void executed(String label, ArgConsumer args, Settings settings) {
args.requireMax(0);
String version = getClass().getPackage().getImplementationVersion();
if (isNull(version)) {
throw new CommandInvalidStateException("Null version (this is normal in a dev environment)");
} else {
logDirect(String.format("You are running Baritone v%s", version));
}
}
@Override
protected Stream<String> tabCompleted(String label, ArgConsumer args, Settings settings) {
return Stream.empty();
}
@Override
public List<String> getLongDesc() {
return asList(
"The version command prints the version of Baritone you're currently running.",
"",
"Usage:",
"> version - View version information, if present"
);
}
}

View File

@ -0,0 +1,37 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.exception;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.argument.CommandArgument;
import net.minecraft.util.text.TextFormatting;
import java.util.List;
import static baritone.api.utils.Helper.HELPER;
public abstract class CommandErrorMessageException extends CommandException {
protected CommandErrorMessageException(String reason) {
super(reason);
}
@Override
public void handle(Command command, List<CommandArgument> args) {
HELPER.logDirect(getMessage(), TextFormatting.RED);
}
}

View File

@ -0,0 +1,37 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.exception;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.argument.CommandArgument;
import java.util.List;
public abstract class CommandException extends RuntimeException {
protected CommandException(String reason) {
super(reason);
}
/**
* Called when this exception is thrown, to handle the exception.
*
* @param command The command that threw it.
* @param args The arguments the command was called with.
*/
public abstract void handle(Command command, List<CommandArgument> args);
}

View File

@ -0,0 +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 Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.exception;
import baritone.api.utils.command.argument.CommandArgument;
public abstract class CommandInvalidArgumentException extends CommandErrorMessageException {
public final CommandArgument arg;
protected CommandInvalidArgumentException(CommandArgument arg, String reason) {
super(String.format(
"Error at argument #%s: %s",
arg.index == -1 ? "<unknown>" : Integer.toString(arg.index + 1),
reason
));
this.arg = arg;
}
}

View File

@ -0,0 +1,24 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.exception;
public class CommandInvalidStateException extends CommandErrorMessageException {
public CommandInvalidStateException(String reason) {
super(reason);
}
}

View File

@ -0,0 +1,38 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.exception;
import baritone.api.utils.command.argument.CommandArgument;
public class CommandInvalidTypeException extends CommandInvalidArgumentException {
public CommandInvalidTypeException(CommandArgument arg, String expected) {
super(arg, String.format("Expected %s", expected));
}
public CommandInvalidTypeException(CommandArgument arg, String expected, Throwable cause) {
super(arg, String.format("Expected %s.\nMore details: %s", expected, cause.getMessage()));
}
public CommandInvalidTypeException(CommandArgument arg, String expected, String got) {
super(arg, String.format("Expected %s, but got %s instead", expected, got));
}
public CommandInvalidTypeException(CommandArgument arg, String expected, String got, Throwable cause) {
super(arg, String.format("Expected %s, but got %s instead.\nMore details: %s", expected, got, cause.getMessage()));
}
}

View File

@ -0,0 +1,27 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.exception;
public class CommandNoParserForTypeException extends CommandErrorMessageException {
public final Class<?> klass;
public CommandNoParserForTypeException(Class<?> klass) {
super(String.format("Could not find a handler for type %s", klass.getSimpleName()));
this.klass = klass;
}
}

View File

@ -0,0 +1,24 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.exception;
public class CommandNotEnoughArgumentsException extends CommandErrorMessageException {
public CommandNotEnoughArgumentsException(int minArgs) {
super(String.format("Not enough arguments (expected at least %d)", minArgs));
}
}

View File

@ -0,0 +1,39 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.exception;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.argument.CommandArgument;
import java.util.List;
import static baritone.api.utils.Helper.HELPER;
public class CommandNotFoundException extends CommandException {
public final String command;
public CommandNotFoundException(String command) {
super(String.format("Command not found: %s", command));
this.command = command;
}
@Override
public void handle(Command command, List<CommandArgument> args) {
HELPER.logDirect(getMessage());
}
}

View File

@ -0,0 +1,24 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.exception;
public class CommandTooManyArgumentsException extends CommandErrorMessageException {
public CommandTooManyArgumentsException(int maxArgs) {
super(String.format("Too many arguments (expected at most %d)", maxArgs));
}
}

View File

@ -0,0 +1,83 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.exception;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import static java.util.Arrays.asList;
public class CommandUnhandledException extends CommandErrorMessageException {
public static String getStackTrace(Throwable throwable) {
StringWriter sw = new StringWriter();
throwable.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
public static String getBaritoneStackTrace(String stackTrace) {
List<String> lines = Arrays.stream(stackTrace.split("\n"))
.collect(Collectors.toCollection(ArrayList::new));
int lastBaritoneLine = 0;
for (int i = 0; i < lines.size(); i++) {
if (lines.get(i).startsWith("\tat baritone.") && lines.get(i).contains("BaritoneChatControl")) {
lastBaritoneLine = i;
}
}
return String.join("\n", lines.subList(0, lastBaritoneLine + 1));
}
public static String getBaritoneStackTrace(Throwable throwable) {
return getBaritoneStackTrace(getStackTrace(throwable));
}
public static String getFriendlierStackTrace(String stackTrace) {
List<String> lines = asList(stackTrace.split("\n"));
for (int i = 0; i < lines.size(); i++) {
String line = lines.get(i);
if (line.startsWith("\tat ")) {
if (line.startsWith("\tat baritone.")) {
line = line.replaceFirst("^\tat [a-z.]+?([A-Z])", "\tat $1");
}
// line = line.replaceFirst("\\(([^)]+)\\)$", "\n\t . $1");
line = line.replaceFirst("\\([^:]+:(\\d+)\\)$", ":$1");
lines.set(i, line);
}
}
return String.join("\n", lines);
}
public static String getFriendlierStackTrace(Throwable throwable) {
return getFriendlierStackTrace(getBaritoneStackTrace(throwable));
}
public CommandUnhandledException(Throwable cause) {
super(String.format(
"An unhandled exception has occurred:\n\n%s",
getFriendlierStackTrace(cause)
));
}
}

View File

@ -0,0 +1,113 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.execution;
import baritone.api.BaritoneAPI;
import baritone.api.Settings;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.argument.CommandArgument;
import baritone.api.utils.command.exception.CommandException;
import baritone.api.utils.command.exception.CommandUnhandledException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import baritone.api.utils.command.manager.CommandManager;
import com.mojang.realmsclient.util.Pair;
import java.util.List;
import java.util.stream.Stream;
import static java.util.Objects.isNull;
public class CommandExecution {
/**
* The command itself
*/
private final Command command;
/**
* The name this command was called with
*/
public final String label;
/**
* The arg consumer
*/
public final ArgConsumer args;
/**
* The Baritone settings
*/
public final Settings settings = BaritoneAPI.getSettings();
public CommandExecution(Command command, String label, ArgConsumer args) {
this.command = command;
this.label = label;
this.args = args;
}
public static String getLabel(String string) {
return string.split("\\s", 2)[0];
}
public static Pair<String, List<CommandArgument>> expand(String string, boolean preserveEmptyLast) {
String label = getLabel(string);
List<CommandArgument> args = CommandArgument.from(string.substring(label.length()), preserveEmptyLast);
return Pair.of(label, args);
}
public static Pair<String, List<CommandArgument>> expand(String string) {
return expand(string, false);
}
public void execute() {
try {
command.execute(this);
} catch (CommandException e) {
e.handle(command, args.args);
} catch (Throwable t) {
t.printStackTrace();
new CommandUnhandledException(t).handle(command, args.args);
}
}
public Stream<String> tabComplete() {
return command.tabComplete(this);
}
public static CommandExecution from(String label, ArgConsumer args) {
Command command = CommandManager.getCommand(label);
if (isNull(command)) {
return null;
}
return new CommandExecution(
command,
label,
args
);
}
public static CommandExecution from(Pair<String, List<CommandArgument>> pair) {
return from(pair.first(), new ArgConsumer(pair.second()));
}
public static CommandExecution from(String string) {
return from(expand(string));
}
}

View File

@ -0,0 +1,310 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.helpers.arguments;
import baritone.api.utils.command.argument.CommandArgument;
import baritone.api.utils.command.datatypes.IDatatype;
import baritone.api.utils.command.datatypes.IDatatypeFor;
import baritone.api.utils.command.datatypes.IDatatypePost;
import baritone.api.utils.command.exception.CommandException;
import baritone.api.utils.command.exception.CommandInvalidTypeException;
import baritone.api.utils.command.exception.CommandNotEnoughArgumentsException;
import baritone.api.utils.command.exception.CommandTooManyArgumentsException;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Deque;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.stream.Stream;
public class ArgConsumer {
public final List<CommandArgument> args;
public final Deque<CommandArgument> consumed;
private ArgConsumer(List<CommandArgument> args, Deque<CommandArgument> consumed) {
this.args = new ArrayList<>(args);
this.consumed = new LinkedList<>(consumed);
}
public ArgConsumer(List<CommandArgument> args) {
this(args, new LinkedList<>());
}
public boolean has(int num) {
return args.size() >= num;
}
public boolean has() {
return has(1);
}
public boolean hasAtMost(int num) {
return args.size() <= num;
}
public boolean hasAtMostOne() {
return hasAtMost(1);
}
public boolean hasExactly(int num) {
return args.size() == num;
}
public boolean hasExactlyOne() {
return hasExactly(1);
}
public CommandArgument peek(int index) {
requireMin(1);
return args.get(index);
}
public CommandArgument peek() {
return peek(0);
}
public boolean is(Class<?> type) {
return peek().is(type);
}
public String peekS(int index) {
return peek(index).value;
}
public String peekS() {
return peekS(0);
}
public <E extends Enum<?>> E peekE(Class<E> enumClass) {
return peek().getE(enumClass);
}
public <E extends Enum<?>> E peekEOrNull(Class<E> enumClass) {
try {
return peekE(enumClass);
} catch (NoSuchElementException e) {
return null;
}
}
public <T> T peekAs(Class<T> type, int index) {
return peek(index).getAs(type);
}
public <T> T peekAs(Class<T> type) {
return peekAs(type, 0);
}
public <T> T peekAsOrDefault(Class<T> type, T def, int index) {
try {
return peekAs(type, index);
} catch (CommandInvalidTypeException e) {
return def;
}
}
public <T> T peekAsOrDefault(Class<T> type, T def) {
return peekAsOrDefault(type, def, 0);
}
public <T> T peekAsOrNull(Class<T> type, int index) {
return peekAsOrDefault(type, null, 0);
}
public <T> T peekAsOrNull(Class<T> type) {
return peekAsOrNull(type, 0);
}
public <T extends IDatatype> T peekDatatype(Class<T> datatype) {
return clone().getDatatype(datatype);
}
public <T extends IDatatype> T peekDatatypeOrNull(Class<T> datatype) {
return new ArgConsumer(args, consumed).getDatatypeOrNull(datatype);
}
public <T, O, D extends IDatatypePost<T, O>> T peekDatatypePost(Class<D> datatype, O original) {
return new ArgConsumer(args, consumed).getDatatypePost(datatype, original);
}
public <T, O, D extends IDatatypePost<T, O>> T peekDatatypePostOrDefault(Class<D> datatype, O original, T def) {
return new ArgConsumer(args, consumed).getDatatypePostOrDefault(datatype, original, def);
}
public <T, O, D extends IDatatypePost<T, O>> T peekDatatypePostOrNull(Class<D> datatype, O original) {
return peekDatatypePostOrDefault(datatype, original, null);
}
public <T, D extends IDatatypeFor<T>> T peekDatatypeFor(Class<D> datatype) {
return new ArgConsumer(args, consumed).peekDatatypeFor(datatype);
}
public <T, D extends IDatatypeFor<T>> T peekDatatypeForOrDefault(Class<D> datatype, T def) {
return new ArgConsumer(args, consumed).peekDatatypeForOrDefault(datatype, def);
}
public <T, D extends IDatatypeFor<T>> T peekDatatypeForOrNull(Class<D> datatype, T def) {
return peekDatatypeForOrDefault(datatype, null);
}
public CommandArgument get() {
requireMin(1);
CommandArgument arg = args.remove(0);
consumed.add(arg);
return arg;
}
public String getS() {
return get().value;
}
public <E extends Enum<?>> E getE(Class<E> enumClass) {
try {
return get().getE(enumClass);
} catch (NoSuchElementException e) {
throw new CommandInvalidTypeException(consumed(), enumClass.getSimpleName());
}
}
public <E extends Enum<?>> E getEOrNull(Class<E> enumClass) {
try {
peekE(enumClass);
return getE(enumClass);
} catch (CommandInvalidTypeException e) {
return null;
}
}
public <T> T getAs(Class<T> type) {
return get().getAs(type);
}
public <T> T getAsOrDefault(Class<T> type, T def) {
try {
T val = peek().getAs(type);
get();
return val;
} catch (CommandInvalidTypeException e) {
return def;
}
}
public <T> T getAsOrNull(Class<T> type) {
return getAsOrDefault(type, null);
}
public <T extends IDatatype> T getDatatype(Class<T> datatype) {
try {
return datatype.getConstructor(ArgConsumer.class).newInstance(this);
} catch (RuntimeException | NoSuchMethodException | IllegalAccessException | InstantiationException | InvocationTargetException e) {
throw new CommandInvalidTypeException(has() ? peek() : consumed(), datatype.getSimpleName());
}
}
public <T extends IDatatype> T getDatatypeOrNull(Class<T> datatype) {
try {
return getDatatype(datatype);
} catch (CommandInvalidTypeException e) {
return null;
}
}
public <T, O, D extends IDatatypePost<T, O>> T getDatatypePost(Class<D> datatype, O original) {
return getDatatype(datatype).apply(original);
}
public <T, O, D extends IDatatypePost<T, O>> T getDatatypePostOrDefault(Class<D> datatype, O original, T def) {
try {
return getDatatypePost(datatype, original);
} catch (CommandException e) {
return def;
}
}
public <T, O, D extends IDatatypePost<T, O>> T getDatatypePostOrNull(Class<D> datatype, O original) {
return getDatatypePostOrDefault(datatype, original, null);
}
public <T, D extends IDatatypeFor<T>> T getDatatypeFor(Class<D> datatype) {
return getDatatype(datatype).get();
}
public <T, D extends IDatatypeFor<T>> T getDatatypeForOrDefault(Class<D> datatype, T def) {
try {
return getDatatypeFor(datatype);
} catch (CommandInvalidTypeException e) {
return def;
}
}
public <T, D extends IDatatypeFor<T>> T getDatatypeForOrNull(Class<D> datatype) {
return getDatatypeForOrDefault(datatype, null);
}
public <T extends IDatatype> Stream<String> tabCompleteDatatype(Class<T> datatype) {
try {
return datatype.getConstructor().newInstance().tabComplete(this);
} catch (InstantiationException | IllegalAccessException | InvocationTargetException | NoSuchMethodException e) {
e.printStackTrace();
} catch (CommandException ignored) {
}
return Stream.empty();
}
public String rawRest() {
return args.size() > 0 ? args.get(0).rawRest : "";
}
public void requireMin(int min) {
if (args.size() < min) {
throw new CommandNotEnoughArgumentsException(min + consumed.size());
}
}
public void requireMax(int max) {
if (args.size() > max) {
throw new CommandTooManyArgumentsException(max + consumed.size());
}
}
public void requireExactly(int args) {
requireMin(args);
requireMax(args);
}
public boolean hasConsumed() {
return !consumed.isEmpty();
}
public CommandArgument consumed() {
return consumed.size() > 0 ? consumed.getLast() : CommandArgument.unknown();
}
@SuppressWarnings("MethodDoesntCallSuperMethod")
@Override
public ArgConsumer clone() {
return new ArgConsumer(args, consumed);
}
public static ArgConsumer from(String string) {
return new ArgConsumer(CommandArgument.from(string));
}
}

View File

@ -0,0 +1,162 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.helpers.pagination;
import baritone.api.utils.Helper;
import baritone.api.utils.command.exception.CommandInvalidTypeException;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
import net.minecraft.util.text.event.ClickEvent;
import net.minecraft.util.text.event.HoverEvent;
import java.util.List;
import java.util.function.Function;
import static java.util.Objects.nonNull;
public class Paginator<E> implements Helper {
public final List<E> entries;
public int pageSize = 8;
public int page = 1;
public Paginator(List<E> entries) {
this.entries = entries;
}
public Paginator<E> setPageSize(int pageSize) {
this.pageSize = pageSize;
return this;
}
public int getMaxPage() {
return (entries.size() - 1) / pageSize + 1;
}
public boolean validPage(int page) {
return page > 0 && page <= getMaxPage();
}
public Paginator<E> skipPages(int pages) {
page += pages;
return this;
}
public void display(Function<E, ITextComponent> transform, String commandFormat) {
int offset = (page - 1) * pageSize;
for (int i = offset; i < offset + pageSize; i++) {
if (i < entries.size()) {
logDirect(transform.apply(entries.get(i)));
} else {
logDirect("--", TextFormatting.DARK_GRAY);
}
}
boolean hasPrevPage = nonNull(commandFormat) && validPage(page - 1);
boolean hasNextPage = nonNull(commandFormat) && validPage(page + 1);
logDirect(new TextComponentString("") {{
getStyle().setColor(TextFormatting.GRAY);
appendSibling(new TextComponentString("<<") {{
if (hasPrevPage) {
getStyle()
.setClickEvent(new ClickEvent(
ClickEvent.Action.RUN_COMMAND,
String.format(commandFormat, page - 1)
))
.setHoverEvent(new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new TextComponentString("Click to view previous page")
));
} else {
getStyle().setColor(TextFormatting.DARK_GRAY);
}
}});
appendText(" | ");
appendSibling(new TextComponentString(">>") {{
if (hasNextPage) {
getStyle()
.setClickEvent(new ClickEvent(
ClickEvent.Action.RUN_COMMAND,
String.format(commandFormat, page + 1)
))
.setHoverEvent(new HoverEvent(
HoverEvent.Action.SHOW_TEXT,
new TextComponentString("Click to view next page")
));
} else {
getStyle().setColor(TextFormatting.DARK_GRAY);
}
}});
appendText(String.format(" %d/%d", page, getMaxPage()));
}});
}
public void display(Function<E, ITextComponent> transform) {
display(transform, null);
}
public static <T> void paginate(ArgConsumer consumer, Paginator<T> pagi, Runnable pre, Function<T, ITextComponent> transform, String commandFormat) {
int page = 1;
consumer.requireMax(1);
if (consumer.has()) {
page = consumer.getAs(Integer.class);
if (!pagi.validPage(page)) {
throw new CommandInvalidTypeException(
consumer.consumed(),
String.format(
"a valid page (1-%d)",
pagi.getMaxPage()
),
consumer.consumed().value
);
}
}
pagi.skipPages(page - pagi.page);
if (nonNull(pre)) {
pre.run();
}
pagi.display(transform, commandFormat);
}
public static <T> void paginate(ArgConsumer consumer, Paginator<T> pagi, Function<T, ITextComponent> transform, String commandName) {
paginate(consumer, pagi, null, transform, commandName);
}
public static <T> void paginate(ArgConsumer consumer, Paginator<T> pagi, Runnable pre, Function<T, ITextComponent> transform) {
paginate(consumer, pagi, pre, transform, null);
}
public static <T> void paginate(ArgConsumer consumer, Paginator<T> pagi, Function<T, ITextComponent> transform) {
paginate(consumer, pagi, null, transform, null);
}
}

View File

@ -0,0 +1,158 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.helpers.tabcomplete;
import baritone.api.BaritoneAPI;
import baritone.api.Settings;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.command.manager.CommandManager;
import net.minecraft.util.ResourceLocation;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Locale;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import static java.util.stream.Stream.concat;
import static java.util.stream.Stream.of;
public class TabCompleteHelper {
private Stream<String> stream;
public TabCompleteHelper(String[] base) {
stream = Arrays.stream(base);
}
public TabCompleteHelper(List<String> base) {
stream = base.stream();
}
public TabCompleteHelper() {
this(new String[0]);
}
public TabCompleteHelper append(Stream<String> source) {
stream = concat(stream, source);
return this;
}
public TabCompleteHelper append(String... source) {
return append(of(source));
}
public TabCompleteHelper append(Class<? extends Enum<?>> num) {
return append(
Arrays.stream(num.getEnumConstants())
.map(Enum::name)
.map(String::toLowerCase)
);
}
public TabCompleteHelper prepend(Stream<String> source) {
stream = concat(source, stream);
return this;
}
public TabCompleteHelper prepend(String... source) {
return prepend(of(source));
}
public TabCompleteHelper prepend(Class<? extends Enum<?>> num) {
return prepend(
Arrays.stream(num.getEnumConstants())
.map(Enum::name)
.map(String::toLowerCase)
);
}
public TabCompleteHelper map(Function<String, String> transform) {
stream = stream.map(transform);
return this;
}
public TabCompleteHelper filter(Predicate<String> filter) {
stream = stream.filter(filter);
return this;
}
public TabCompleteHelper sort(Comparator<String> comparator) {
stream = stream.sorted(comparator);
return this;
}
public TabCompleteHelper sortAlphabetically() {
return sort(String.CASE_INSENSITIVE_ORDER);
}
public TabCompleteHelper filterPrefix(String prefix) {
return filter(x -> x.toLowerCase(Locale.US).startsWith(prefix.toLowerCase(Locale.US)));
}
public TabCompleteHelper filterPrefixNamespaced(String prefix) {
return filterPrefix(new ResourceLocation(prefix).toString());
}
public String[] build() {
return stream.toArray(String[]::new);
}
public Stream<String> stream() {
return stream;
}
public TabCompleteHelper addCommands() {
return append(
CommandManager.REGISTRY.descendingStream()
.flatMap(command -> command.names.stream())
.distinct()
);
}
public TabCompleteHelper addSettings() {
return append(
BaritoneAPI.getSettings().allSettings.stream()
.map(Settings.Setting::getName)
.filter(s -> !s.equalsIgnoreCase("logger"))
.sorted(String.CASE_INSENSITIVE_ORDER)
);
}
public TabCompleteHelper addModifiedSettings() {
return append(
SettingsUtil.modifiedSettings(BaritoneAPI.getSettings()).stream()
.map(Settings.Setting::getName)
.sorted(String.CASE_INSENSITIVE_ORDER)
);
}
public TabCompleteHelper addToggleableSettings() {
return append(
BaritoneAPI.getSettings().getAllValuesByType(Boolean.class).stream()
.map(Settings.Setting::getName)
.sorted(String.CASE_INSENSITIVE_ORDER)
);
}
}

View File

@ -0,0 +1,93 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.manager;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.argument.CommandArgument;
import baritone.api.utils.command.defaults.DefaultCommands;
import baritone.api.utils.command.execution.CommandExecution;
import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper;
import baritone.api.utils.command.registry.Registry;
import com.mojang.realmsclient.util.Pair;
import java.util.List;
import java.util.Locale;
import java.util.stream.Stream;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
public class CommandManager {
public static final Registry<Command> REGISTRY = new Registry<>();
static {
DefaultCommands.commands.forEach(REGISTRY::register);
}
/**
* @param name The command name to search for.
* @return The command, if found.
*/
public static Command getCommand(String name) {
for (Command command : REGISTRY.entries) {
if (command.names.contains(name.toLowerCase(Locale.US))) {
return command;
}
}
return null;
}
public static void execute(CommandExecution execution) {
execution.execute();
}
public static boolean execute(String string) {
CommandExecution execution = CommandExecution.from(string);
if (nonNull(execution)) {
execution.execute();
}
return nonNull(execution);
}
public static Stream<String> tabComplete(CommandExecution execution) {
return execution.tabComplete();
}
public static Stream<String> tabComplete(Pair<String, List<CommandArgument>> pair) {
CommandExecution execution = CommandExecution.from(pair);
return isNull(execution) ? Stream.empty() : tabComplete(execution);
}
public static Stream<String> tabComplete(String prefix) {
Pair<String, List<CommandArgument>> pair = CommandExecution.expand(prefix, true);
String label = pair.first();
List<CommandArgument> args = pair.second();
if (args.isEmpty()) {
return new TabCompleteHelper()
.addCommands()
.filterPrefix(label)
.stream();
} else {
return tabComplete(pair);
}
}
}

View File

@ -0,0 +1,148 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils.command.registry;
import java.util.Collection;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.function.Consumer;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
/**
* This registry class allows for registration and unregistration of a certain type. This is mainly designed for use by
* event handlers where newly registered ones are encountered first during iteration and can therefore override older
* ones. In Baritone, this is used for commands and argument parsers so that mods and addons can extend Baritone's
* functionality without resorting to hacks, wrappers, or mixins.
*
* @param <V> The entry type that will be stored in this registry. This can be anything, really - preferably anything
* that works as a HashMap key, as that's what's used to keep track of which entries are registered or not.
*/
@SuppressWarnings({"unused", "UnusedReturnValue"})
public class Registry<V> {
/**
* An internal linked list of all the entries that are currently registered. This is a linked list so that entries
* can be inserted at the beginning, which means that newer entries are encountered first during iteration. This is
* an important property of the registry that makes it more useful than a simple list, and also the reason it does
* not just use a map.
*/
private final Deque<V> _entries = new LinkedList<>();
/**
* A HashMap containing keys for every entry currently registered. Map entries are added to this map when something
* is registered and removed from the map when they are unregistered. An entry simply being present in this map
* indicates that it is currently registered and therefore can be removed and should not be reregistered.
*/
private final Map<V, Boolean> registered = new HashMap<>();
/**
* The collection of entries that are currently in this registry. This is a collection (and not a list) because,
* internally, entries are stored in a linked list, which is not the same as a normal list.
*/
public final Collection<V> entries = Collections.unmodifiableCollection(_entries);
/**
* @param entry The entry to check.
* @return If this entry is currently registered in this registry.
*/
public boolean registered(V entry) {
return registered.containsKey(entry);
}
/**
* Ensures that the entry {@code entry} is registered.
*
* @param entry The entry to register.
* @return A boolean indicating whether or not this is a new registration. No matter the value of this boolean, the
* entry is always guaranteed to now be in this registry. This boolean simply indicates if the entry was <i>not</i>
* in the map prior to this method call.
*/
public boolean register(V entry) {
if (!registered(entry)) {
_entries.addFirst(entry);
registered.put(entry, true);
return true;
}
return false;
}
/**
* Unregisters this entry from this registry. After this method call, the entry is guaranteed to be removed from the
* registry, since each entry only ever appears once.
*
* @param entry The entry to unregister.
*/
public void unregister(V entry) {
if (registered(entry)) {
return;
}
_entries.remove(entry);
registered.remove(entry);
}
/**
* Returns an iterator that iterates over each entry in this registry, with the newest elements iterated over first.
* Internally, as new elements are prepended to the registry rather than appended to the end, this order is the best
* way to search through the registry if you want to discover newer items first.
*/
public Iterator<V> iterator() {
return _entries.iterator();
}
/**
* Returns an iterator that iterates over each entry in this registry, in the order they were added. Internally,
* this iterates through the registry backwards, as new elements are prepended to the registry rather than appended
* to the end. You should only do this when you need to, for example, list elements in order - it is almost always
* fine to simply use {@link Iterable#forEach(Consumer) forEach} on the {@link #entries} collection instead.
*/
public Iterator<V> descendingIterator() {
return _entries.descendingIterator();
}
/**
* Returns a stream that contains each entry in this registry, with the newest elements ordered first. Internally,
* as new elements are prepended to the registry rather than appended to the end, this order is the best way to
* search through the registry if you want to discover newer items first.
*/
public Stream<V> stream() {
return _entries.stream();
}
/**
* Returns a stream that returns each entry in this registry, in the order they were added. Internally, this orders
* the registry backwards, as new elements are prepended to the registry rather than appended to the end. You should
* only use this when you need to, for example, list elements in order - it is almost always fine to simply use the
* regular {@link #stream()} method instead.
*/
public Stream<V> descendingStream() {
return StreamSupport.stream(Spliterators.spliterator(
descendingIterator(),
_entries.size(),
Spliterator.SIZED | Spliterator.SUBSIZED
), false);
}
}

View File

@ -0,0 +1,20 @@
package baritone.launch.mixins;
import net.minecraft.client.gui.GuiChat;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(GuiChat.ChatTabCompleter.class)
public abstract class MixinChatTabCompleter extends MixinTabCompleter {
@Inject(method = "<init>*", at = @At("RETURN"))
private void onConstruction(CallbackInfo ci) {
isChatCompleter = true;
}
@Inject(method = "complete", at = @At("HEAD"), cancellable = true)
private void onComplete(CallbackInfo ci) {
if (dontComplete) ci.cancel();
}
}

View File

@ -0,0 +1,23 @@
package baritone.launch.mixins;
import baritone.utils.accessor.ITabCompleter;
import net.minecraft.client.gui.GuiChat;
import net.minecraft.util.TabCompleter;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(GuiChat.class)
public abstract class MixinGuiChat implements net.minecraft.util.ITabCompleter {
@Shadow
private TabCompleter tabCompleter;
@Inject(method = "setCompletions", at = @At("HEAD"), cancellable = true)
private void onSetCompletions(String[] newCompl, CallbackInfo ci) {
if (((ITabCompleter) tabCompleter).onGuiChatSetCompletions(newCompl)) {
ci.cancel();
}
}
}

View File

@ -0,0 +1,15 @@
package baritone.launch.mixins;
import baritone.api.utils.command.Lol;
import net.minecraft.client.gui.GuiScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.net.URI;
@Mixin(GuiScreen.class)
public abstract class MixinGuiScreen implements Lol {
@Override
@Invoker("openWebLink")
public abstract void openLink(URI url);
}

View File

@ -0,0 +1,115 @@
package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.event.events.TabCompleteEvent;
import baritone.utils.accessor.ITabCompleter;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiTextField;
import net.minecraft.util.TabCompleter;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static java.util.Objects.isNull;
@Mixin(TabCompleter.class)
public abstract class MixinTabCompleter implements ITabCompleter {
@Shadow
@Final
protected GuiTextField textField;
@Shadow
protected boolean requestedCompletions;
@Shadow
public abstract void setCompletions(String... newCompl);
@Unique
protected boolean isChatCompleter = false;
@Unique
protected boolean dontComplete = false;
@Override
public String getPrefix() {
return textField.getText().substring(0, textField.getCursorPosition());
}
@Override
public void setPrefix(String prefix) {
textField.setText(prefix + textField.getText().substring(textField.getCursorPosition()));
textField.setCursorPosition(prefix.length());
}
@Inject(method = "requestCompletions", at = @At("HEAD"), cancellable = true)
private void onRequestCompletions(String prefix, CallbackInfo ci) {
if (!isChatCompleter) {
return;
}
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(Minecraft.getMinecraft().player);
if (isNull(baritone)) {
return;
}
TabCompleteEvent.Pre event = new TabCompleteEvent.Pre(prefix);
baritone.getGameEventHandler().onPreTabComplete(event);
if (event.isCancelled()) {
ci.cancel();
return;
}
if (event.prefix.wasModified()) {
setPrefix(event.prefix.get());
}
if (event.completions.wasModified()) {
ci.cancel();
dontComplete = true;
try {
requestedCompletions = true;
setCompletions(event.completions.get());
} finally {
dontComplete = false;
}
}
}
@Override
public boolean onGuiChatSetCompletions(String[] newCompl) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(Minecraft.getMinecraft().player);
if (isNull(baritone)) {
return false;
}
TabCompleteEvent.Post event = new TabCompleteEvent.Post(getPrefix(), newCompl);
baritone.getGameEventHandler().onPostTabComplete(event);
if (event.isCancelled()) {
return true;
}
if (event.prefix.wasModified()) {
String prefix = event.prefix.get();
textField.setText(prefix + textField.getText().substring(textField.getCursorPosition()));
textField.setCursorPosition(prefix.length());
}
if (event.completions.wasModified()) {
setCompletions(event.completions.get());
return true;
}
return false;
}
}

View File

@ -23,6 +23,10 @@
"MixinRenderChunk",
"MixinRenderList",
"MixinVboRenderList",
"MixinWorldClient"
"MixinWorldClient",
"MixinTabCompleter",
"MixinGuiChat",
"MixinChatTabCompleter",
"MixinGuiScreen"
]
}

View File

@ -21,7 +21,7 @@ import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.Settings;
import baritone.api.event.listener.IEventBus;
import baritone.api.utils.ExampleBaritoneControl;
import baritone.api.utils.command.BaritoneChatControl;
import baritone.api.utils.Helper;
import baritone.api.utils.IPlayerContext;
import baritone.behavior.*;
@ -109,7 +109,7 @@ public class Baritone implements IBaritone {
memoryBehavior = new MemoryBehavior(this);
inventoryBehavior = new InventoryBehavior(this);
inputOverrideHandler = new InputOverrideHandler(this);
new ExampleBaritoneControl(this);
new BaritoneChatControl(this);
}
this.pathingControlManager = new PathingControlManager(this);

View File

@ -19,7 +19,11 @@ package baritone.behavior;
import baritone.Baritone;
import baritone.api.behavior.IPathingBehavior;
import baritone.api.event.events.*;
import baritone.api.event.events.PathEvent;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.RenderEvent;
import baritone.api.event.events.SprintStateEvent;
import baritone.api.event.events.TickEvent;
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalXZ;
@ -55,6 +59,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
private boolean safeToCancel;
private boolean pauseRequestedLastTick;
private boolean unpausedLastTick;
private boolean pausedThisTick;
private boolean cancelRequested;
private boolean calcFailedLastTick;
@ -108,6 +113,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
}
private void tickPath() {
pausedThisTick = false;
if (pauseRequestedLastTick && safeToCancel) {
pauseRequestedLastTick = false;
if (unpausedLastTick) {
@ -115,6 +121,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
baritone.getInputOverrideHandler().getBlockBreakHelper().stopBreakingBlock();
}
unpausedLastTick = false;
pausedThisTick = true;
return;
}
unpausedLastTick = true;
@ -130,8 +137,8 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
BetterBlockPos calcFrom = inProgress.getStart();
Optional<IPath> currentBest = inProgress.bestPathSoFar();
if ((current == null || !current.getPath().getDest().equals(calcFrom)) // if current ends in inProgress's start, then we're ok
&& !calcFrom.equals(ctx.playerFeet()) && !calcFrom.equals(expectedSegmentStart) // if current starts in our playerFeet or pathStart, then we're ok
&& (!currentBest.isPresent() || (!currentBest.get().positions().contains(ctx.playerFeet()) && !currentBest.get().positions().contains(expectedSegmentStart))) // if
&& !calcFrom.equals(ctx.playerFeet()) && !calcFrom.equals(expectedSegmentStart) // if current starts in our playerFeet or pathStart, then we're ok
&& (!currentBest.isPresent() || (!currentBest.get().positions().contains(ctx.playerFeet()) && !currentBest.get().positions().contains(expectedSegmentStart))) // if
) {
// when it was *just* started, currentBest will be empty so we need to also check calcFrom since that's always present
inProgress.cancel(); // cancellation doesn't dispatch any events
@ -279,6 +286,16 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
return goal;
}
@Override
public boolean isPathing() {
return hasPath() && !pausedThisTick;
}
@Override
public boolean hasPath() {
return current != null;
}
@Override
public PathExecutor getCurrent() {
return current;

View File

@ -18,6 +18,7 @@
package baritone.cache;
import baritone.api.cache.IWorldScanner;
import baritone.api.utils.IBlockFilter;
import baritone.api.utils.IPlayerContext;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
@ -38,14 +39,8 @@ public enum WorldScanner implements IWorldScanner {
private static final int[] DEFAULT_COORDINATE_ITERATION_ORDER = IntStream.range(0, 16).toArray();
@Override
public List<BlockPos> scanChunkRadius(IPlayerContext ctx, List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius) {
if (blocks.contains(null)) {
throw new IllegalStateException("Invalid block name should have been caught earlier: " + blocks.toString());
}
public List<BlockPos> scanChunkRadius(IPlayerContext ctx, IBlockFilter filter, int max, int yLevelThreshold, int maxSearchRadius) {
ArrayList<BlockPos> res = new ArrayList<>();
if (blocks.isEmpty()) {
return res;
}
ChunkProviderClient chunkProvider = (ChunkProviderClient) ctx.world().getChunkProvider();
int maxSearchRadiusSq = maxSearchRadius * maxSearchRadius;
@ -75,7 +70,7 @@ public enum WorldScanner implements IWorldScanner {
continue;
}
allUnloaded = false;
if (scanChunkInto(chunkX << 4, chunkZ << 4, chunk, blocks, res, max, yLevelThreshold, playerY, coordinateIterationOrder)) {
if (scanChunkInto(chunkX << 4, chunkZ << 4, chunk, filter, res, max, yLevelThreshold, playerY, coordinateIterationOrder)) {
foundWithinY = true;
}
}
@ -91,11 +86,7 @@ public enum WorldScanner implements IWorldScanner {
}
@Override
public List<BlockPos> scanChunk(IPlayerContext ctx, List<Block> blocks, ChunkPos pos, int max, int yLevelThreshold) {
if (blocks.isEmpty()) {
return Collections.emptyList();
}
public List<BlockPos> scanChunk(IPlayerContext ctx, IBlockFilter filter, ChunkPos pos, int max, int yLevelThreshold) {
ChunkProviderClient chunkProvider = (ChunkProviderClient) ctx.world().getChunkProvider();
Chunk chunk = chunkProvider.getLoadedChunk(pos.x, pos.z);
int playerY = ctx.playerFeet().getY();
@ -105,11 +96,11 @@ public enum WorldScanner implements IWorldScanner {
}
ArrayList<BlockPos> res = new ArrayList<>();
scanChunkInto(pos.x << 4, pos.z << 4, chunk, blocks, res, max, yLevelThreshold, playerY, DEFAULT_COORDINATE_ITERATION_ORDER);
scanChunkInto(pos.x << 4, pos.z << 4, chunk, filter, res, max, yLevelThreshold, playerY, DEFAULT_COORDINATE_ITERATION_ORDER);
return res;
}
private boolean scanChunkInto(int chunkX, int chunkZ, Chunk chunk, List<Block> search, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY, int[] coordinateIterationOrder) {
private boolean scanChunkInto(int chunkX, int chunkZ, Chunk chunk, IBlockFilter filter, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY, int[] coordinateIterationOrder) {
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
boolean foundWithinY = false;
for (int yIndex = 0; yIndex < 16; yIndex++) {
@ -126,7 +117,7 @@ public enum WorldScanner implements IWorldScanner {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
IBlockState state = bsc.get(x, y, z);
if (search.contains(state.getBlock())) {
if (filter.selected(state)) {
int yy = yReal | y;
if (result.size() >= max) {
if (Math.abs(yy - playerY) < yLevelThreshold) {

View File

@ -69,6 +69,16 @@ public final class GameEventHandler implements IEventBus, Helper {
listeners.forEach(l -> l.onSendChatMessage(event));
}
@Override
public void onPreTabComplete(TabCompleteEvent.Pre event) {
listeners.forEach(l -> l.onPreTabComplete(event));
}
@Override
public void onPostTabComplete(TabCompleteEvent.Post event) {
listeners.forEach(l -> l.onPostTabComplete(event));
}
@Override
public final void onChunkEvent(ChunkEvent event) {
EventState state = event.getState();

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