diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 1bdb1e39..2952ed64 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -495,7 +495,7 @@ public final class Settings { /** * Render the path as a line instead of a frickin thingy */ - public final Setting renderPathAsLine = new Setting<>(true); + public final Setting renderPathAsLine = new Setting<>(false); /** * Render the goal diff --git a/src/api/java/baritone/api/utils/command/Lol.java b/src/api/java/baritone/api/accessor/IGuiScreen.java similarity index 92% rename from src/api/java/baritone/api/utils/command/Lol.java rename to src/api/java/baritone/api/accessor/IGuiScreen.java index 47bb8336..3eed255f 100644 --- a/src/api/java/baritone/api/utils/command/Lol.java +++ b/src/api/java/baritone/api/accessor/IGuiScreen.java @@ -15,10 +15,10 @@ * along with Baritone. If not, see . */ -package baritone.api.utils.command; +package baritone.api.accessor; import java.net.URI; -public interface Lol { +public interface IGuiScreen { void openLink(URI url); } diff --git a/src/api/java/baritone/api/behavior/IPathingBehavior.java b/src/api/java/baritone/api/behavior/IPathingBehavior.java index 8890fdc3..5444bb83 100644 --- a/src/api/java/baritone/api/behavior/IPathingBehavior.java +++ b/src/api/java/baritone/api/behavior/IPathingBehavior.java @@ -74,7 +74,9 @@ public interface IPathingBehavior extends IBehavior { * is a pause in effect. * @see #isPathing() */ - boolean hasPath(); + default boolean hasPath() { + return getCurrent() != null; + } /** * Cancels the pathing behavior or the current path calculation, and all processes that could be controlling path. diff --git a/src/api/java/baritone/api/cache/IWaypoint.java b/src/api/java/baritone/api/cache/IWaypoint.java index 23df5d39..238b4d88 100644 --- a/src/api/java/baritone/api/cache/IWaypoint.java +++ b/src/api/java/baritone/api/cache/IWaypoint.java @@ -18,11 +18,14 @@ package baritone.api.cache; import baritone.api.utils.BetterBlockPos; -import org.apache.commons.lang3.ArrayUtils; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; + +import static java.util.Arrays.asList; /** * A marker for a position in the world. @@ -99,13 +102,41 @@ public interface IWaypoint { } /** - * Finds a tag from one of the names that could be used to identify said tag. - * - * @param name The name of the tag - * @return The tag, if one is found, otherwise, {@code null} + * @return A name that can be passed to {@link #getByName(String)} to retrieve this tag */ - public static Tag fromString(String name) { - return TAG_LIST.stream().filter(tag -> ArrayUtils.contains(tag.names, name.toLowerCase())).findFirst().orElse(null); + public String getName() { + return names[0]; + } + + /** + * Gets a tag by one of its names. + * + * @param name The name to search for. + * @return The tag, if found, or null. + */ + public static Tag getByName(String name) { + for (Tag action : Tag.values()) { + for (String alias : action.names) { + if (alias.equalsIgnoreCase(name)) { + return action; + } + } + } + + return null; + } + + /** + * @return All tag names. + */ + public static String[] getAllNames() { + Set names = new HashSet<>(); + + for (Tag tag : Tag.values()) { + names.addAll(asList(tag.names)); + } + + return names.toArray(new String[0]); } } } diff --git a/src/api/java/baritone/api/cache/IWorldScanner.java b/src/api/java/baritone/api/cache/IWorldScanner.java index 009268fb..325d4bd0 100644 --- a/src/api/java/baritone/api/cache/IWorldScanner.java +++ b/src/api/java/baritone/api/cache/IWorldScanner.java @@ -34,12 +34,11 @@ public interface IWorldScanner { /** * Scans the world, up to the specified max chunk radius, for the specified blocks. * - * @param ctx The {@link IPlayerContext} containing player and world info that the - * scan is based upon + * @param ctx The {@link IPlayerContext} containing player and world info that the scan is based upon * @param filter The blocks to scan for * @param max The maximum number of blocks to scan before cutoff - * @param yLevelThreshold If a block is found within this Y level, the current result will be - * returned, if the value is negative, then this condition doesn't apply. + * @param 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 */ @@ -52,14 +51,36 @@ public interface IWorldScanner { /** * 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 ctx The {@link IPlayerContext} containing player and world info that the scan is based upon * @param filter The blocks 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. + * @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 scanChunk(IPlayerContext ctx, BlockOptionalMetaLookup filter, ChunkPos pos, int max, int yLevelThreshold); + + /** + * 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 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 + */ + default List scanChunk(IPlayerContext ctx, List blocks, ChunkPos pos, int max, int yLevelThreshold) { + return scanChunk(ctx, new BlockOptionalMetaLookup(blocks), pos, max, yLevelThreshold); + } + + /** + * Repacks 40 chunks around the player. + * + * @param ctx The player context for that player. + * @return The number of chunks queued for repacking. + */ + int repack(IPlayerContext ctx); } diff --git a/src/api/java/baritone/api/event/events/type/Overrideable.java b/src/api/java/baritone/api/event/events/type/Overrideable.java index 1ec29c67..7690ee8f 100644 --- a/src/api/java/baritone/api/event/events/type/Overrideable.java +++ b/src/api/java/baritone/api/event/events/type/Overrideable.java @@ -44,8 +44,8 @@ public class Overrideable { @Override public String toString() { return String.format( - "Overrideable{modified=%s,value=%s}", - Boolean.toString(modified), + "Overrideable{modified=%b,value=%s}", + modified, value.toString() ); } diff --git a/src/api/java/baritone/api/pathing/goals/GoalInverted.java b/src/api/java/baritone/api/pathing/goals/GoalInverted.java index dfe5c770..7f072c4d 100644 --- a/src/api/java/baritone/api/pathing/goals/GoalInverted.java +++ b/src/api/java/baritone/api/pathing/goals/GoalInverted.java @@ -18,7 +18,12 @@ package baritone.api.pathing.goals; /** - * Invert any goal + * Invert any goal. + * + * In the old chat control system, #invert just tried to pick a {@link GoalRunAway} that effectively inverted the + * current goal. This goal just reverses the heuristic to act as a TRUE invert. Inverting a Y level? Baritone tries to + * get away from that Y level. Inverting a GoalBlock? Baritone will try to make distance whether it's in the X, Y or Z + * directions. And of course, you can always invert a GoalXZ. * * @author LoganDark */ diff --git a/src/api/java/baritone/api/process/IBuilderProcess.java b/src/api/java/baritone/api/process/IBuilderProcess.java index 5ca5f804..c48c2a04 100644 --- a/src/api/java/baritone/api/process/IBuilderProcess.java +++ b/src/api/java/baritone/api/process/IBuilderProcess.java @@ -18,11 +18,13 @@ package baritone.api.process; import baritone.api.utils.ISchematic; +import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3i; import java.io.File; +import java.util.List; /** * @author Brady @@ -63,4 +65,11 @@ public interface IBuilderProcess extends IBaritoneProcess { void resume(); void clearArea(BlockPos corner1, BlockPos corner2); + + /** + * @return A list of block states that are estimated to be placeable by this builder process. You can use this in + * schematics, for example, to pick a state that the builder process will be happy with, because any variation will + * cause it to give up. This is updated every tick, but only while the builder process is active. + */ + List getApproxPlaceable(); } diff --git a/src/api/java/baritone/api/schematic/AbstractSchematic.java b/src/api/java/baritone/api/schematic/AbstractSchematic.java index cee9ff9a..27bf6936 100644 --- a/src/api/java/baritone/api/schematic/AbstractSchematic.java +++ b/src/api/java/baritone/api/schematic/AbstractSchematic.java @@ -40,7 +40,7 @@ public abstract class AbstractSchematic implements ISchematic { protected int y; protected int z; - public AbstractSchematic(@Nullable IBaritone baritone, int x, int y, int z) { + public AbstractSchematic(IBaritone baritone, int x, int y, int z) { this.baritone = baritone; this.ctx = baritone == null ? null : baritone.getPlayerContext(); this.x = x; @@ -62,36 +62,4 @@ public abstract class AbstractSchematic implements ISchematic { public int lengthZ() { return z; } - - protected IBlockState[] approxPlaceable() { - EntityPlayerSP player = ctx.player(); - NonNullList inventory = player.inventory.mainInventory; - List placeable = new ArrayList<>(); - placeable.add(Blocks.AIR.getDefaultState()); - - // 27 + 9 - for (int i = 0; i < 36; i++) { - ItemStack stack = inventory.get(i); - Item item = stack.getItem(); - - if (!stack.isEmpty() && stack.getItem() instanceof ItemBlock) { - ItemBlock itemBlock = (ItemBlock) item; - - // - placeable.add(itemBlock.getBlock().getStateForPlacement( - ctx.world(), - ctx.playerFeet(), - EnumFacing.UP, - (float) player.posX, - (float) player.posY, - (float) player.posZ, - itemBlock.getMetadata(stack.getMetadata()), - player - )); - // - } - } - - return placeable.toArray(new IBlockState[0]); - } } diff --git a/src/api/java/baritone/api/schematic/CompositeSchematic.java b/src/api/java/baritone/api/schematic/CompositeSchematic.java index bb4c6cc1..d278fa4c 100644 --- a/src/api/java/baritone/api/schematic/CompositeSchematic.java +++ b/src/api/java/baritone/api/schematic/CompositeSchematic.java @@ -67,13 +67,13 @@ public class CompositeSchematic extends AbstractSchematic { } @Override - public IBlockState desiredState(int x, int y, int z, IBlockState current) { + public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { CompositeSchematicEntry entry = getSchematic(x, y, z, current); if (entry == null) { throw new IllegalStateException("couldn't find schematic for this position"); } - return entry.schematic.desiredState(x - entry.x, y - entry.y, z - entry.z, current); + return entry.schematic.desiredState(x - entry.x, y - entry.y, z - entry.z, current, approxPlaceable); } } diff --git a/src/api/java/baritone/api/schematic/FillBomSchematic.java b/src/api/java/baritone/api/schematic/FillSchematic.java similarity index 84% rename from src/api/java/baritone/api/schematic/FillBomSchematic.java rename to src/api/java/baritone/api/schematic/FillSchematic.java index 6fc9eff8..8a55376f 100644 --- a/src/api/java/baritone/api/schematic/FillBomSchematic.java +++ b/src/api/java/baritone/api/schematic/FillSchematic.java @@ -22,10 +22,12 @@ import baritone.api.utils.BlockOptionalMeta; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; -public class FillBomSchematic extends AbstractSchematic { +import java.util.List; + +public class FillSchematic extends AbstractSchematic { private final BlockOptionalMeta bom; - public FillBomSchematic(IBaritone baritone, int x, int y, int z, BlockOptionalMeta bom) { + public FillSchematic(IBaritone baritone, int x, int y, int z, BlockOptionalMeta bom) { super(baritone, x, y, z); this.bom = bom; } @@ -35,14 +37,14 @@ public class FillBomSchematic extends AbstractSchematic { } @Override - public IBlockState desiredState(int x, int y, int z, IBlockState current) { + public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { if (bom.matches(current)) { return current; } else if (current.getBlock() != Blocks.AIR) { return Blocks.AIR.getDefaultState(); } - for (IBlockState placeable : approxPlaceable()) { + for (IBlockState placeable : approxPlaceable) { if (bom.matches(placeable)) { return placeable; } diff --git a/src/api/java/baritone/api/schematic/MaskSchematic.java b/src/api/java/baritone/api/schematic/MaskSchematic.java index 34b1478b..63a4f86f 100644 --- a/src/api/java/baritone/api/schematic/MaskSchematic.java +++ b/src/api/java/baritone/api/schematic/MaskSchematic.java @@ -21,6 +21,8 @@ import baritone.api.IBaritone; import baritone.api.utils.ISchematic; import net.minecraft.block.state.IBlockState; +import java.util.List; + public abstract class MaskSchematic extends AbstractSchematic { private final ISchematic schematic; @@ -37,7 +39,7 @@ public abstract class MaskSchematic extends AbstractSchematic { } @Override - public IBlockState desiredState(int x, int y, int z, IBlockState current) { - return schematic.desiredState(x, y, z, current); + public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { + return schematic.desiredState(x, y, z, current, approxPlaceable); } } diff --git a/src/api/java/baritone/api/schematic/ReplaceSchematic.java b/src/api/java/baritone/api/schematic/ReplaceSchematic.java index 4c7ee546..b74c564f 100644 --- a/src/api/java/baritone/api/schematic/ReplaceSchematic.java +++ b/src/api/java/baritone/api/schematic/ReplaceSchematic.java @@ -24,15 +24,17 @@ import net.minecraft.block.state.IBlockState; public class ReplaceSchematic extends MaskSchematic { private final BlockOptionalMetaLookup filter; - private final boolean[][][] cache; + private final Boolean[][][] cache; public ReplaceSchematic(IBaritone baritone, ISchematic schematic, BlockOptionalMetaLookup filter) { super(baritone, schematic); this.filter = filter; - this.cache = new boolean[widthX()][heightY()][lengthZ()]; + this.cache = new Boolean[widthX()][heightY()][lengthZ()]; } protected boolean partOfMask(int x, int y, int z, IBlockState currentState) { - return cache[x][y][z] || (cache[x][y][z] = filter.has(currentState)); + return cache[x][y][z] == null + ? cache[x][y][z] = filter.has(currentState) + : cache[x][y][z]; } } diff --git a/src/api/java/baritone/api/utils/BlockOptionalMeta.java b/src/api/java/baritone/api/utils/BlockOptionalMeta.java index bd17307c..3776baf3 100644 --- a/src/api/java/baritone/api/utils/BlockOptionalMeta.java +++ b/src/api/java/baritone/api/utils/BlockOptionalMeta.java @@ -56,6 +56,7 @@ import net.minecraft.util.ResourceLocation; import javax.annotation.Nonnull; import javax.annotation.Nullable; +import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Map; @@ -79,6 +80,42 @@ public final class BlockOptionalMeta { private static final Pattern pattern = Pattern.compile("^(.+?)(?::(\\d+))?$"); private static final Map normalizations; + public BlockOptionalMeta(@Nonnull Block block, @Nullable Integer meta) { + this.block = block; + this.noMeta = isNull(meta); + this.meta = noMeta ? 0 : meta; + this.blockstates = getStates(block, meta); + this.stateHashes = getStateHashes(blockstates); + this.stackHashes = getStackHashes(blockstates); + } + + public BlockOptionalMeta(@Nonnull Block block) { + this(block, null); + } + + public BlockOptionalMeta(@Nonnull String selector) { + Matcher matcher = pattern.matcher(selector); + + if (!matcher.find()) { + throw new IllegalArgumentException("invalid block selector"); + } + + MatchResult matchResult = matcher.toMatchResult(); + noMeta = matchResult.group(2) == null; + + ResourceLocation id = new ResourceLocation(matchResult.group(1)); + + if (!Block.REGISTRY.containsKey(id)) { + throw new IllegalArgumentException("Invalid block ID"); + } + + block = Block.REGISTRY.getObject(id); + meta = noMeta ? 0 : Integer.parseInt(matchResult.group(2)); + blockstates = getStates(block, getMeta()); + stateHashes = getStateHashes(blockstates); + stackHashes = getStackHashes(blockstates); + } + static { Map _normalizations = new HashMap<>(); Consumer put = instance -> _normalizations.put(instance.getClass(), instance); @@ -172,7 +209,7 @@ public final class BlockOptionalMeta { _normalizations.put(BlockWall.EAST, false); _normalizations.put(BlockWall.WEST, false); _normalizations.put(BlockWall.SOUTH, false); - normalizations = _normalizations; + normalizations = Collections.unmodifiableMap(_normalizations); } private static , P extends IProperty> P castToIProperty(Object value) { @@ -180,7 +217,6 @@ public final class BlockOptionalMeta { return (P) value; } - @SuppressWarnings("unused") private static , P extends IProperty> C castToIPropertyValue(P iproperty, Object value) { //noinspection unchecked return (C) value; @@ -225,7 +261,7 @@ public final class BlockOptionalMeta { private static Set getStates(@Nonnull Block block, @Nullable Integer meta) { return block.getBlockState().getValidStates().stream() .filter(blockstate -> meta == null || stateMeta(blockstate) == meta) - .collect(Collectors.toCollection(HashSet::new)); + .collect(Collectors.toSet()); } private static ImmutableSet getStateHashes(Set blockstates) { @@ -249,42 +285,6 @@ public final class BlockOptionalMeta { ); } - public BlockOptionalMeta(@Nonnull Block block, @Nullable Integer meta) { - this.block = block; - this.noMeta = isNull(meta); - this.meta = noMeta ? 0 : meta; - this.blockstates = getStates(block, meta); - this.stateHashes = getStateHashes(blockstates); - this.stackHashes = getStackHashes(blockstates); - } - - public BlockOptionalMeta(@Nonnull Block block) { - this(block, null); - } - - public BlockOptionalMeta(@Nonnull String selector) { - Matcher matcher = pattern.matcher(selector); - - if (!matcher.find()) { - throw new IllegalArgumentException("invalid block selector"); - } - - MatchResult matchResult = matcher.toMatchResult(); - noMeta = matchResult.group(2) == null; - - ResourceLocation id = new ResourceLocation(matchResult.group(1)); - - if (!Block.REGISTRY.containsKey(id)) { - throw new IllegalArgumentException("Invalid block ID"); - } - - block = Block.REGISTRY.getObject(id); - meta = noMeta ? 0 : Integer.parseInt(matchResult.group(2)); - blockstates = getStates(block, getMeta()); - stateHashes = getStateHashes(blockstates); - stackHashes = getStackHashes(blockstates); - } - public Block getBlock() { return block; } diff --git a/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java b/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java index 44c756d1..963d147c 100644 --- a/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java +++ b/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java @@ -45,6 +45,12 @@ public class BlockOptionalMetaLookup { .toArray(BlockOptionalMeta[]::new); } + public BlockOptionalMetaLookup(String... blocks) { + this.boms = Arrays.stream(blocks) + .map(BlockOptionalMeta::new) + .toArray(BlockOptionalMeta[]::new); + } + public boolean has(Block block) { for (BlockOptionalMeta bom : boms) { if (bom.getBlock() == block) { diff --git a/src/api/java/baritone/api/utils/BlockUtils.java b/src/api/java/baritone/api/utils/BlockUtils.java index 7d148c9f..633e3acb 100644 --- a/src/api/java/baritone/api/utils/BlockUtils.java +++ b/src/api/java/baritone/api/utils/BlockUtils.java @@ -22,7 +22,6 @@ import net.minecraft.util.ResourceLocation; import java.util.HashMap; import java.util.Map; -import java.util.Objects; public class BlockUtils { private static transient Map resourceCache = new HashMap<>(); @@ -39,7 +38,11 @@ public class BlockUtils { public static Block stringToBlockRequired(String name) { Block block = stringToBlockNullable(name); - Objects.requireNonNull(block, String.format("Invalid block name %s", name)); + + if (block == null) { + throw new NullPointerException(String.format("Invalid block name %s", name)); + } + return block; } diff --git a/src/api/java/baritone/api/utils/ExampleBaritoneControlOld.java b/src/api/java/baritone/api/utils/ExampleBaritoneControlOld.java deleted file mode 100644 index 998a981f..00000000 --- a/src/api/java/baritone/api/utils/ExampleBaritoneControlOld.java +++ /dev/null @@ -1,770 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Baritone. If not, see . - */ - -package baritone.api.utils; - -import baritone.api.BaritoneAPI; -import baritone.api.IBaritone; -import baritone.api.Settings; -import baritone.api.behavior.IPathingBehavior; -import baritone.api.cache.IRememberedInventory; -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.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; -import net.minecraft.block.Block; -import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ChunkProviderClient; -import net.minecraft.crash.CrashReport; -import net.minecraft.entity.Entity; -import net.minecraft.entity.item.EntityItem; -import net.minecraft.entity.player.EntityPlayer; -import net.minecraft.item.ItemStack; -import net.minecraft.util.ReportedException; -import net.minecraft.util.math.BlockPos; -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.world.DimensionType; -import net.minecraft.world.chunk.Chunk; - -import java.nio.file.Path; -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 ExampleBaritoneControlOld implements Helper, AbstractGameEventListener { - private static final String COMMAND_PREFIX = "#"; - - public final IBaritone baritone; - public final IPlayerContext ctx; - - public ExampleBaritoneControlOld(IBaritone baritone) { - this.baritone = baritone; - this.ctx = baritone.getPlayerContext(); - baritone.getGameEventHandler().registerEventListener(this); - } - - @Override - public void onSendChatMessage(ChatEvent event) { - String msg = event.getMessage(); - if (BaritoneAPI.getSettings().prefixControl.value && msg.startsWith(COMMAND_PREFIX)) { - if (!runCommand(msg.substring(COMMAND_PREFIX.length()))) { - logDirect("Invalid command"); - } - event.cancel(); // always cancel if using prefixControl - return; - } - if (!BaritoneAPI.getSettings().chatControl.value && !BaritoneAPI.getSettings().chatControlAnyway.value) { - return; - } - if (runCommand(msg)) { - event.cancel(); - } - } - - public boolean runCommand(String msg0) { // you may think this can be private, but impcat calls it from .b =) - String msg = msg0.toLowerCase(Locale.US).trim(); // don't reassign the argument LOL - IPathingBehavior pathingBehavior = baritone.getPathingBehavior(); - ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); - List> toggleable = BaritoneAPI.getSettings().getAllValuesByType(Boolean.class); - for (Settings.Setting setting : toggleable) { - if (msg.equalsIgnoreCase(setting.getName())) { - setting.value ^= true; - logDirect("Toggled " + setting.getName() + " to " + setting.value); - SettingsUtil.save(BaritoneAPI.getSettings()); - return true; - } - } - if (msg.equals("baritone") || msg.equals("modifiedsettings") || msg.startsWith("settings m") || msg.equals("modified")) { - logDirect("All settings that have been modified from their default values:"); - for (Settings.Setting setting : SettingsUtil.modifiedSettings(BaritoneAPI.getSettings())) { - logDirect(setting.toString()); - } - return true; - } - if (msg.startsWith("settings")) { - String rest = msg.substring("settings".length()); - try { - int page = Integer.parseInt(rest.trim()); - int min = page * 10; - int max = Math.min(BaritoneAPI.getSettings().allSettings.size(), (page + 1) * 10); - logDirect("Settings " + min + " to " + (max - 1) + ":"); - for (int i = min; i < max; i++) { - logDirect(BaritoneAPI.getSettings().allSettings.get(i).toString()); - } - } catch (Exception ex) { // NumberFormatException | ArrayIndexOutOfBoundsException and probably some others I'm forgetting lol - ex.printStackTrace(); - logDirect("All settings:"); - for (Settings.Setting setting : BaritoneAPI.getSettings().allSettings) { - logDirect(setting.toString()); - } - logDirect("To get one page of ten settings at a time, do settings "); - } - return true; - } - if (msg.equals("") || msg.equals("help") || msg.equals("?")) { - 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")); - component.appendSibling(helpLink); - BaritoneAPI.getSettings().logger.value.accept(component); - return true; - } - if (msg.contains(" ")) { - String settingName = msg.substring(0, msg.indexOf(' ')); - String settingValue = msg.substring(msg.indexOf(' ') + 1); - Settings.Setting setting = BaritoneAPI.getSettings().byLowerName.get(settingName); - if (setting != null) { - if (settingValue.equals("reset")) { - logDirect("Resetting setting " + settingName + " to default value."); - setting.reset(); - } else { - try { - SettingsUtil.parseAndApply(BaritoneAPI.getSettings(), settingName, settingValue); - } catch (Exception ex) { - logDirect("Unable to parse setting"); - return true; - } - } - SettingsUtil.save(BaritoneAPI.getSettings()); - logDirect(setting.toString()); - return true; - } - } - if (BaritoneAPI.getSettings().byLowerName.containsKey(msg)) { - Settings.Setting setting = BaritoneAPI.getSettings().byLowerName.get(msg); - logDirect(setting.toString()); - return true; - } - - if (msg.startsWith("goal")) { - String rest = msg.substring(4).trim(); - Goal goal; - if (rest.equals("clear") || rest.equals("none")) { - goal = null; - } else { - String[] params = rest.split(" "); - if (params[0].equals("")) { - params = new String[] {}; - } - goal = parseGoal(params); - if (goal == null) { - return true; - } - } - customGoalProcess.setGoal(goal); - logDirect("Goal: " + goal); - return true; - } - if (msg.equals("crash")) { - StringBuilder meme = new StringBuilder(); - CrashReport rep = new CrashReport("Manually triggered debug crash", new Throwable()); - mc.addGraphicsAndWorldToCrashReport(rep); - new ReportedException(rep).printStackTrace(); - rep.getSectionsInStringBuilder(meme); - System.out.println(meme); - logDirect(meme.toString()); - logDirect("ok"); - return true; - } - if (msg.equals("path")) { - if (pathingBehavior.getGoal() == null) { - logDirect("No goal."); - } else if (pathingBehavior.getGoal().isInGoal(ctx.playerFeet())) { - logDirect("Already in goal"); - } else if (pathingBehavior.isPathing()) { - logDirect("Currently executing a path. Please cancel it first."); - } else { - customGoalProcess.setGoalAndPath(pathingBehavior.getGoal()); - } - return true; - } - /*if (msg.equals("fullpath")) { - if (pathingBehavior.getGoal() == null) { - logDirect("No goal."); - } else { - logDirect("Started segmented calculator"); - SegmentedCalculator.calculateSegmentsThreaded(pathingBehavior.pathStart(), pathingBehavior.getGoal(), new CalculationContext(baritone, true), ipath -> { - logDirect("Found a path"); - logDirect("Ends at " + ipath.getDest()); - logDirect("Length " + ipath.length()); - logDirect("Estimated time " + ipath.ticksRemainingFrom(0)); - pathingBehavior.secretCursedFunctionDoNotCall(ipath); // it's okay when *I* do it - }, () -> { - logDirect("Path calculation failed, no path"); - }); - } - return true; - }*/ - if (msg.equals("proc")) { - Optional proc = baritone.getPathingControlManager().mostRecentInControl(); - if (!proc.isPresent()) { - logDirect("No process is in control"); - return true; - } - IBaritoneProcess p = proc.get(); - logDirect("Class: " + p.getClass()); - logDirect("Priority: " + p.priority()); - logDirect("Temporary: " + p.isTemporary()); - logDirect("Display name: " + p.displayName()); - logDirect("Command: " + baritone.getPathingControlManager().mostRecentCommand()); - return true; - } - if (msg.equals("version")) { - String version = ExampleBaritoneControlOld.class.getPackage().getImplementationVersion(); - if (version == null) { - logDirect("No version detected. Either dev environment or broken install."); - } else { - logDirect("You are using Baritone v" + version); - } - return true; - } - if (msg.equals("repack") || msg.equals("rescan")) { - logDirect("Queued " + repack() + " chunks for repacking"); - return true; - } - if (msg.startsWith("build")) { - String file; - BlockPos origin; - try { - String[] coords = msg.substring("build".length()).trim().split(" "); - file = coords[0] + ".schematic"; - origin = new BlockPos(parseOrDefault(coords[1], ctx.playerFeet().x, 1), parseOrDefault(coords[2], ctx.playerFeet().y, 1), parseOrDefault(coords[3], ctx.playerFeet().z, 1)); - } catch (Exception ex) { - file = msg.substring(5).trim() + ".schematic"; - origin = ctx.playerFeet(); - } - logDirect("Loading '" + file + "' to build from origin " + origin); - boolean success = baritone.getBuilderProcess().build(file, origin); - logDirect(success ? "Loaded" : "Unable to load"); - return true; - } - if (msg.startsWith("schematica")) { - baritone.getBuilderProcess().buildOpenSchematic(); - return true; - } - if (msg.equals("come")) { - customGoalProcess.setGoalAndPath(new GoalBlock(new BlockPos(Helper.mc.getRenderViewEntity()))); - logDirect("Coming"); - return true; - } - if (msg.equals("axis") || msg.equals("highway")) { - customGoalProcess.setGoalAndPath(new GoalAxis()); - return true; - } - if (msg.equals("cancel") || msg.equals("stop")) { - pathingBehavior.cancelEverything(); - logDirect("ok canceled"); - return true; - } - if (msg.equals("forcecancel")) { - pathingBehavior.cancelEverything(); - pathingBehavior.forceCancel(); - logDirect("ok force canceled"); - return true; - } - if (msg.equals("gc")) { - System.gc(); - logDirect("Called System.gc();"); - return true; - } - if (msg.equals("invert")) { - Goal goal = pathingBehavior.getGoal(); - BlockPos runAwayFrom; - if (goal instanceof GoalXZ) { - runAwayFrom = new BlockPos(((GoalXZ) goal).getX(), 0, ((GoalXZ) goal).getZ()); - } else if (goal instanceof GoalBlock) { - runAwayFrom = ((GoalBlock) goal).getGoalPos(); - } else { - logDirect("Goal must be GoalXZ or GoalBlock to invert"); - logDirect("Inverting goal of player feet"); - runAwayFrom = ctx.playerFeet(); - } - customGoalProcess.setGoalAndPath(new GoalRunAway(1, runAwayFrom) { - @Override - public boolean isInGoal(int x, int y, int z) { - return false; - } - }); - return true; - } - if (msg.startsWith("cleararea")) { - String suffix = msg.substring("cleararea".length()); - BlockPos corner1; - BlockPos corner2; - if (suffix.isEmpty()) { - // clear the area from the current goal to here - Goal goal = baritone.getPathingBehavior().getGoal(); - if (!(goal instanceof GoalBlock)) { - logDirect("Need to specify goal of opposite corner"); - return true; - } - corner1 = ((GoalBlock) goal).getGoalPos(); - corner2 = ctx.playerFeet(); - } else { - try { - String[] spl = suffix.split(" "); - corner1 = ctx.playerFeet(); - corner2 = new BlockPos(Integer.parseInt(spl[0]), Integer.parseInt(spl[1]), Integer.parseInt(spl[2])); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException | NullPointerException ex) { - logDirect("unable to parse"); - return true; - } - } - baritone.getBuilderProcess().clearArea(corner1, corner2); - return true; - } - if (msg.equals("resume")) { - baritone.getBuilderProcess().resume(); - logDirect("resumed"); - return true; - } - if (msg.equals("pause")) { - baritone.getBuilderProcess().pause(); - logDirect("paused"); - return true; - } - if (msg.equals("reset")) { - for (Settings.Setting setting : BaritoneAPI.getSettings().allSettings) { - setting.reset(); - } - SettingsUtil.save(BaritoneAPI.getSettings()); - logDirect("Baritone settings reset"); - return true; - } - if (msg.equals("tunnel")) { - customGoalProcess.setGoalAndPath(new GoalStrictDirection(ctx.playerFeet(), ctx.player().getHorizontalFacing())); - logDirect("tunneling"); - return true; - } - if (msg.equals("render")) { - BetterBlockPos pf = ctx.playerFeet(); - int dist = (Minecraft.getMinecraft().gameSettings.renderDistanceChunks + 1) * 16; - Minecraft.getMinecraft().renderGlobal.markBlockRangeForRenderUpdate(pf.x - dist, pf.y - 256, pf.z - dist, pf.x + dist, pf.y + 256, pf.z + dist); - logDirect("okay"); - return true; - } - if (msg.equals("farm")) { - baritone.getFarmProcess().farm(); - logDirect("farming"); - return true; - } - if (msg.equals("chests")) { - for (Map.Entry entry : baritone.getWorldProvider().getCurrentWorld().getContainerMemory().getRememberedInventories().entrySet()) { - logDirect(BetterBlockPos.from(entry.getKey()) + ""); - log(entry.getValue().getContents()); - } - return true; - } - if (msg.startsWith("followentities")) { - baritone.getFollowProcess().follow(Entity.class::isInstance); - logDirect("Following any entities"); - return true; - } - if (msg.startsWith("followplayers")) { - baritone.getFollowProcess().follow(EntityPlayer.class::isInstance); // O P P A - logDirect("Following any players"); - return true; - } - if (msg.startsWith("followentity")) { - String name = msg.substring(12).trim(); - Optional toFollow = Optional.empty(); - for (Entity entity : ctx.world().loadedEntityList) { - String entityName = entity.getName().trim().toLowerCase(); - if ((entityName.contains(name) || name.contains(entityName)) && !(entity instanceof EntityItem || entity instanceof EntityPlayer)) { // We dont want it following players while `#follow` exists. - toFollow = Optional.of(entity); - } - } - if (!toFollow.isPresent()) { - logDirect("Entity not found"); - return true; - } - Entity effectivelyFinal = toFollow.get(); - baritone.getFollowProcess().follow(effectivelyFinal::equals); - logDirect("Following entity " + toFollow.get()); - return true; - } - if (msg.startsWith("follow")) { - String name = msg.substring(6).trim(); - Optional toFollow = Optional.empty(); - if (name.length() == 0) { - toFollow = ctx.getSelectedEntity(); - } else { - for (EntityPlayer pl : ctx.world().playerEntities) { - String theirName = pl.getName().trim().toLowerCase(); - if (!theirName.equals(ctx.player().getName().trim().toLowerCase()) && (theirName.contains(name) || name.contains(theirName))) { // don't follow ourselves lol - toFollow = Optional.of(pl); - } - } - } - if (!toFollow.isPresent()) { - logDirect("Not found"); - return true; - } - Entity effectivelyFinal = toFollow.get(); - baritone.getFollowProcess().follow(effectivelyFinal::equals); - logDirect("Following " + toFollow.get()); - return true; - } - if (msg.startsWith("explorefilter")) { - // explorefilter blah.json - // means that entries in blah.json are already explored - // explorefilter blah.json invert - // means that entries in blah.json are NOT already explored - String path = msg.substring("explorefilter".length()).trim(); - String[] parts = path.split(" "); - Path path1 = Minecraft.getMinecraft().gameDir.toPath().resolve(parts[0]); - boolean invert = parts.length > 1; - try { - baritone.getExploreProcess().applyJsonFilter(path1, invert); - logDirect("Loaded filter. Inverted: " + invert); - if (invert) { - logDirect("Chunks on this list will be treated as possibly unexplored, all others will be treated as certainly explored"); - } else { - logDirect("Chunks on this list will be treated as certainly explored, all others will be treated as possibly unexplored"); - } - } catch (Exception e) { - e.printStackTrace(); - logDirect("Unable to load " + path1); - } - return true; - } - if (msg.equals("reloadall")) { - baritone.getWorldProvider().getCurrentWorld().getCachedWorld().reloadAllFromDisk(); - logDirect("ok"); - return true; - } - if (msg.equals("saveall")) { - baritone.getWorldProvider().getCurrentWorld().getCachedWorld().save(); - logDirect("ok"); - return true; - } - if (msg.startsWith("explore")) { - String rest = msg.substring("explore".length()).trim(); - int centerX; - int centerZ; - try { - centerX = Integer.parseInt(rest.split(" ")[0]); - centerZ = Integer.parseInt(rest.split(" ")[1]); - } catch (Exception ex) { - centerX = ctx.playerFeet().x; - centerZ = ctx.playerFeet().z; - } - baritone.getExploreProcess().explore(centerX, centerZ); - logDirect("Exploring from " + centerX + "," + centerZ); - return true; - } - if (msg.equals("blacklist")) { - IGetToBlockProcess proc = baritone.getGetToBlockProcess(); - if (!proc.isActive()) { - logDirect("GetToBlockProcess is not currently active"); - return true; - } - if (proc.blacklistClosest()) { - logDirect("Blacklisted closest instances"); - } else { - logDirect("No known locations, unable to blacklist"); - } - return true; - } - if (msg.startsWith("find")) { - repack(); - String blockType = msg.substring(4).trim(); - ArrayList locs = baritone.getWorldProvider().getCurrentWorld().getCachedWorld().getLocationsOf(blockType, 1, ctx.playerFeet().getX(), ctx.playerFeet().getZ(), 4); - logDirect("Have " + locs.size() + " locations"); - for (BlockPos pos : locs) { - Block actually = ctx.world().getBlockState(pos).getBlock(); - if (!BlockUtils.blockToString(actually).equalsIgnoreCase(blockType)) { - logDebug("Was looking for " + blockType + " but actually found " + actually + " " + BlockUtils.blockToString(actually)); - } - } - return true; - } - if (msg.startsWith("mine")) { - repack(); - String[] blockTypes = msg.substring(4).trim().split(" "); - try { - int quantity = Integer.parseInt(blockTypes[1]); - Block block = BlockUtils.stringToBlockRequired(blockTypes[0]); - baritone.getMineProcess().mine(quantity, block); - logDirect("Will mine " + quantity + " " + blockTypes[0]); - return true; - } catch (NumberFormatException | ArrayIndexOutOfBoundsException | NullPointerException ex) { - } - for (String s : blockTypes) { - if (BlockUtils.stringToBlockNullable(s) == null) { - logDirect(s + " isn't a valid block name"); - return true; - } - - } - baritone.getMineProcess().mineByName(0, blockTypes); - logDirect("Started mining blocks of type " + Arrays.toString(blockTypes)); - return true; - } - if (msg.equals("click")) { - baritone.openClick(); - logDirect("aight dude"); - return true; - } - if (msg.startsWith("thisway") || msg.startsWith("forward")) { - try { - Goal goal = GoalXZ.fromDirection(ctx.playerFeetAsVec(), ctx.player().rotationYaw, Double.parseDouble(msg.substring(7).trim())); - customGoalProcess.setGoal(goal); - logDirect("Goal: " + goal); - } catch (NumberFormatException ex) { - logDirect("Error unable to parse '" + msg.substring(7).trim() + "' to a double."); - } - return true; - } - if (msg.startsWith("list") || msg.startsWith("get ") || msg.startsWith("show")) { - String waypointType = msg.substring(4).trim(); - if (waypointType.endsWith("s")) { - // for example, "show deaths" - waypointType = waypointType.substring(0, waypointType.length() - 1); - } - IWaypoint.Tag tag = IWaypoint.Tag.fromString(waypointType); - if (tag == null) { - logDirect("Not a valid tag. Tags are: " + Arrays.asList(IWaypoint.Tag.values()).toString().toLowerCase()); - return true; - } - Set waypoints = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getByTag(tag); - // might as well show them from oldest to newest - List sorted = new ArrayList<>(waypoints); - sorted.sort(Comparator.comparingLong(IWaypoint::getCreationTimestamp)); - logDirect("Waypoints under tag " + tag + ":"); - for (IWaypoint waypoint : sorted) { - logDirect(waypoint.toString()); - } - return true; - } - if (msg.startsWith("save")) { - String name = msg.substring(4).trim(); - BetterBlockPos pos = ctx.playerFeet(); - if (name.contains(" ")) { - logDirect("Name contains a space, assuming it's in the format 'save waypointName X Y Z'"); - String[] parts = name.split(" "); - if (parts.length != 4) { - logDirect("Unable to parse, expected four things"); - return true; - } - try { - pos = new BetterBlockPos(Integer.parseInt(parts[1]), Integer.parseInt(parts[2]), Integer.parseInt(parts[3])); - } catch (NumberFormatException ex) { - logDirect("Unable to parse coordinate integers"); - return true; - } - name = parts[0]; - } - for (IWaypoint.Tag tag : IWaypoint.Tag.values()) { - if (tag.name().equalsIgnoreCase(name)) { - logDirect("Unable to use tags as name. Tags are: " + Arrays.asList(IWaypoint.Tag.values()).toString().toLowerCase()); - return true; - } - } - baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(new Waypoint(name, IWaypoint.Tag.USER, pos)); - logDirect("Saved user defined position " + pos + " under name '" + name + "'. Say 'goto " + name + "' to set goal, say 'list user' to list custom waypoints."); - return true; - } - if (msg.startsWith("delete")) { - String name = msg.substring(6).trim(); - IWaypoint waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getAllWaypoints().stream().filter(w -> w.getTag() == IWaypoint.Tag.USER && w.getName().equalsIgnoreCase(name)).findFirst().orElse(null); - if (waypoint == null) { - logDirect("No user defined position under the name '" + name + "' found."); - return true; - } - baritone.getWorldProvider().getCurrentWorld().getWaypoints().removeWaypoint(waypoint); - logDirect("Deleted user defined position under name '" + name + "'."); - return true; - } - if (msg.startsWith("goto")) { - repack(); - String waypointType = msg.substring(4).trim(); - if (waypointType.endsWith("s") && IWaypoint.Tag.fromString(waypointType.substring(0, waypointType.length() - 1)) != null) { - // for example, "show deaths" - waypointType = waypointType.substring(0, waypointType.length() - 1); - } - IWaypoint.Tag tag = IWaypoint.Tag.fromString(waypointType); - IWaypoint waypoint; - if (tag == null) { - String mining = waypointType; - Block block = BlockUtils.stringToBlockNullable(mining); - //logDirect("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase()); - if (block == null) { - waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getAllWaypoints().stream().filter(w -> w.getName().equalsIgnoreCase(mining)).max(Comparator.comparingLong(IWaypoint::getCreationTimestamp)).orElse(null); - if (waypoint == null) { - Goal goal = parseGoal(waypointType.split(" ")); - if (goal != null) { - logDirect("Going to " + goal); - customGoalProcess.setGoalAndPath(goal); - } - return true; - } - } else { - baritone.getGetToBlockProcess().getToBlock(block); - return true; - } - } else { - waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getMostRecentByTag(tag); - if (waypoint == null) { - logDirect("None saved for tag " + tag); - return true; - } - } - Goal goal = waypoint.getTag() == IWaypoint.Tag.BED ? new GoalGetToBlock(waypoint.getLocation()) : new GoalBlock(waypoint.getLocation()); - customGoalProcess.setGoalAndPath(goal); - return true; - } - if (msg.equals("spawn") || msg.equals("bed")) { - IWaypoint waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getMostRecentByTag(IWaypoint.Tag.BED); - if (waypoint == null) { - BlockPos spawnPoint = ctx.player().getBedLocation(); - // for some reason the default spawnpoint is underground sometimes - Goal goal = new GoalXZ(spawnPoint.getX(), spawnPoint.getZ()); - logDirect("spawn not saved, defaulting to world spawn. set goal to " + goal); - customGoalProcess.setGoalAndPath(goal); - } else { - Goal goal = new GoalGetToBlock(waypoint.getLocation()); - customGoalProcess.setGoalAndPath(goal); - logDirect("Set goal to most recent bed " + goal); - } - return true; - } - if (msg.equals("sethome")) { - baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("", IWaypoint.Tag.HOME, ctx.playerFeet())); - logDirect("Saved. Say home to set goal."); - return true; - } - if (msg.equals("home")) { - IWaypoint waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getMostRecentByTag(IWaypoint.Tag.HOME); - if (waypoint == null) { - logDirect("home not saved"); - } else { - Goal goal = new GoalBlock(waypoint.getLocation()); - customGoalProcess.setGoalAndPath(goal); - logDirect("Going to saved home " + goal); - } - return true; - } - if (msg.equals("damn")) { - logDirect("daniel"); - } - return false; - } - - private int repack() { - ChunkProviderClient cli = (ChunkProviderClient) ctx.world().getChunkProvider(); - int playerChunkX = ctx.playerFeet().getX() >> 4; - int playerChunkZ = ctx.playerFeet().getZ() >> 4; - int count = 0; - for (int x = playerChunkX - 40; x <= playerChunkX + 40; x++) { - for (int z = playerChunkZ - 40; z <= playerChunkZ + 40; z++) { - Chunk chunk = cli.getLoadedChunk(x, z); - if (chunk != null && !chunk.isEmpty()) { - count++; - baritone.getWorldProvider().getCurrentWorld().getCachedWorld().queueForPacking(chunk); - } - } - } - return count; - } - - private int parseOrDefault(String str, int i, double dimensionFactor) { - return str.equals("~") ? i : str.startsWith("~") ? (int) (Integer.parseInt(str.substring(1)) * dimensionFactor) + i : (int) (Integer.parseInt(str) * dimensionFactor); - } - - private void log(List stacks) { - for (ItemStack stack : stacks) { - if (!stack.isEmpty()) { - logDirect(stack.getCount() + "x " + stack.getDisplayName() + "@" + stack.getItemDamage()); - } - } - } - - private Goal parseGoal(String[] params) { - Goal goal; - try { - BetterBlockPos playerFeet = ctx.playerFeet(); - - int length = params.length - 1; // length has to be smaller when a dimension parameter is added - if (params.length < 1 || (isCreatable(params[params.length - 1]) || params[params.length - 1].startsWith("~"))) { - length = params.length; - } - switch (length) { - case 0: - goal = new GoalBlock(playerFeet); - break; - case 1: - goal = new GoalYLevel(parseOrDefault(params[0], playerFeet.y, 1)); - break; - case 2: - goal = new GoalXZ(parseOrDefault(params[0], playerFeet.x, calculateDimensionFactor(params[params.length - 1])), parseOrDefault(params[1], playerFeet.z, calculateDimensionFactor(params[params.length - 1]))); - break; - case 3: - goal = new GoalBlock(new BlockPos(parseOrDefault(params[0], playerFeet.x, calculateDimensionFactor(params[params.length - 1])), parseOrDefault(params[1], playerFeet.y, 1), parseOrDefault(params[2], playerFeet.z, calculateDimensionFactor(params[params.length - 1])))); - break; - default: - logDirect("unable to understand lol"); - return null; - } - } catch (NumberFormatException ex) { - logDirect("unable to parse integer " + ex); - return null; - } - return goal; - } - - - private double calculateDimensionFactor(String to) { - return Math.pow(8, ctx.world().provider.getDimensionType().getId() - getDimensionByName(to.toLowerCase()).getId()); - } - - private DimensionType getDimensionByName(String name) { - if ("the_end".contains(name)) { - return DimensionType.THE_END; - } - if ("the_overworld".contains(name) || "surface".contains(name)) { - return DimensionType.OVERWORLD; - } - if ("the_nether".contains(name) || "hell".contains(name)) { - return DimensionType.NETHER; - } - return ctx.world().provider.getDimensionType(); - } - -} diff --git a/src/api/java/baritone/api/utils/Helper.java b/src/api/java/baritone/api/utils/Helper.java index 9bb573be..87884cd2 100755 --- a/src/api/java/baritone/api/utils/Helper.java +++ b/src/api/java/baritone/api/utils/Helper.java @@ -39,14 +39,15 @@ public interface Helper { Helper HELPER = new Helper() {}; 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("]")); - }}; + ITextComponent baritone = new TextComponentString(BaritoneAPI.getSettings().shortBaritonePrefix.value ? "B" : "Baritone"); + baritone.getStyle().setColor(TextFormatting.LIGHT_PURPLE); + ITextComponent prefix = new TextComponentString(""); + prefix.getStyle().setColor(TextFormatting.DARK_PURPLE); + prefix.appendText("["); + prefix.appendSibling(baritone); + prefix.appendText("]"); + + return prefix; } Minecraft mc = Minecraft.getMinecraft(); @@ -71,31 +72,31 @@ public interface Helper { * @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); - }}; - + ITextComponent component = new TextComponentString(""); + component.appendSibling(getPrefix()); + component.appendSibling(new TextComponentString(" ")); + asList(components).forEach(component::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) + * 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); - }}) - ); + Arrays.stream(message.split("\\n")).forEach(line -> { + ITextComponent component = new TextComponentString(line.replace("\t", " ")); + component.getStyle().setColor(color); + logDirect(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) + * 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 */ diff --git a/src/api/java/baritone/api/utils/IPlayerContext.java b/src/api/java/baritone/api/utils/IPlayerContext.java index 457af87b..b461c389 100644 --- a/src/api/java/baritone/api/utils/IPlayerContext.java +++ b/src/api/java/baritone/api/utils/IPlayerContext.java @@ -48,6 +48,14 @@ public interface IPlayerContext { // TODO find a better way to deal with soul sand!!!!! BetterBlockPos feet = new BetterBlockPos(player().posX, player().posY + 0.1251, player().posZ); + // sometimes when calling this from another thread or while world is null, it'll throw a NullPointerException + // that causes the game to immediately crash + // + // so of course crashing on 2b is horribly bad due to queue times and logout spot + // catch the NPE and ignore it if it does happen + // + // this does not impact performance at all since we're not null checking constantly + // if there is an exception, the only overhead is Java generating the exception object... so we can ignore it try { if (world().getBlockState(feet).getBlock() instanceof BlockSlab) { return feet.up(); diff --git a/src/api/java/baritone/api/utils/ISchematic.java b/src/api/java/baritone/api/utils/ISchematic.java index 0b2f92d9..b2dfc308 100644 --- a/src/api/java/baritone/api/utils/ISchematic.java +++ b/src/api/java/baritone/api/utils/ISchematic.java @@ -20,9 +20,11 @@ package baritone.api.utils; import net.minecraft.block.state.IBlockState; import net.minecraft.util.EnumFacing; +import java.util.List; + /** - * Basic representation of a schematic. Provides the dimensions and - * the desired statefor a given position relative to the origin. + * Basic representation of a schematic. Provides the dimensions and the desired statefor a given position relative to + * the origin. * * @author leijurv */ @@ -62,13 +64,14 @@ public interface ISchematic { /** * Returns the desired block state at a given (X, Y, Z) position relative to the origin (0, 0, 0). * - * @param x The x position of the block, relative to the origin - * @param y The y position of the block, relative to the origin - * @param z The z position of the block, relative to the origin - * @param current The current state of that block in the world, or null + * @param x The x position of the block, relative to the origin + * @param y The y position of the block, relative to the origin + * @param z The z position of the block, relative to the origin + * @param current The current state of that block in the world, or null + * @param approxPlaceable The list of blockstates estimated to be placeable * @return The desired block state at the specified position */ - IBlockState desiredState(int x, int y, int z, IBlockState current); + IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable); /** * @return The width (X axis length) of this schematic diff --git a/src/api/java/baritone/api/utils/SettingsUtil.java b/src/api/java/baritone/api/utils/SettingsUtil.java index e726a9cc..5c8ab83f 100644 --- a/src/api/java/baritone/api/utils/SettingsUtil.java +++ b/src/api/java/baritone/api/utils/SettingsUtil.java @@ -121,6 +121,15 @@ public class SettingsUtil { return modified; } + /** + * Gets the type of a setting and returns it as a string, with package names stripped. + * + * For example, if the setting type is {@code java.util.List}, this function returns + * {@code List}. + * + * @param setting The setting + * @return The type + */ public static String settingTypeToString(Settings.Setting setting) { return setting.getType().getTypeName() .replaceAll("(?:\\w+\\.)+(\\w+)", "$1"); diff --git a/src/api/java/baritone/api/utils/command/BaritoneChatControl.java b/src/api/java/baritone/api/utils/command/BaritoneChatControl.java index a06887b2..df7bab65 100644 --- a/src/api/java/baritone/api/utils/command/BaritoneChatControl.java +++ b/src/api/java/baritone/api/utils/command/BaritoneChatControl.java @@ -20,6 +20,7 @@ package baritone.api.utils.command; import baritone.api.BaritoneAPI; import baritone.api.IBaritone; import baritone.api.Settings; +import baritone.api.accessor.IGuiScreen; import baritone.api.event.events.ChatEvent; import baritone.api.event.events.TabCompleteEvent; import baritone.api.event.listener.AbstractGameEventListener; @@ -33,6 +34,7 @@ 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.ITextComponent; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.event.ClickEvent; @@ -47,7 +49,6 @@ 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; @@ -67,10 +68,6 @@ public class BaritoneChatControl implements Helper, AbstractGameEventListener { 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(); @@ -79,11 +76,7 @@ public class BaritoneChatControl implements Helper, AbstractGameEventListener { 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)) { + } else if ((settings.chatControl.value || settings.chatControlAnyway.value) && runCommand(msg)) { event.cancel(); } } @@ -92,18 +85,20 @@ public class BaritoneChatControl implements Helper, AbstractGameEventListener { if (settings.echoCommands.value) { String msg = command + rest; String toDisplay = settings.censorRanCommands.value ? command + " ..." : msg; - logDirect(new TextComponentString(String.format("> %s", toDisplay)) {{ - 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 - )); - }}); + + ITextComponent component = new TextComponentString(String.format("> %s", toDisplay)); + component.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 + )); + + logDirect(component); } } @@ -113,7 +108,7 @@ public class BaritoneChatControl implements Helper, AbstractGameEventListener { return false; } else if (msg.trim().equalsIgnoreCase("orderpizza")) { try { - ((Lol) mc.currentScreen).openLink(new URI("https://www.dominos.com/en/pages/order/")); + ((IGuiScreen) mc.currentScreen).openLink(new URI("https://www.dominos.com/en/pages/order/")); } catch (NullPointerException | URISyntaxException ignored) {} return false; @@ -129,22 +124,18 @@ public class BaritoneChatControl implements Helper, AbstractGameEventListener { ArgConsumer argc = new ArgConsumer(pair.second()); if (!argc.has()) { - for (Settings.Setting setting : settings.allSettings) { - if (setting.getName().equals("logger")) { - continue; + Settings.Setting setting = settings.byLowerName.get(command.toLowerCase(Locale.US)); + + if (setting != null) { + logRanCommand(command, rest); + + if (setting.getValueClass() == Boolean.class) { + CommandManager.execute(String.format("set toggle %s", setting.getName())); + } else { + CommandManager.execute(String.format("set %s", setting.getName())); } - if (setting.getName().equalsIgnoreCase(command)) { - logRanCommand(command, rest); - - 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; - } + return true; } } else if (argc.hasExactlyOne()) { for (Settings.Setting setting : settings.allSettings) { @@ -217,14 +208,14 @@ public class BaritoneChatControl implements Helper, AbstractGameEventListener { TabCompleteHelper helper = new TabCompleteHelper(); if ((Boolean) setting.value) { - helper.append(of("true", "false")); + helper.append(Stream.of("true", "false")); } else { - helper.append(of("false", "true")); + helper.append(Stream.of("false", "true")); } return helper.filterPrefix(argc.getString()).stream(); } else { - return of(SettingsUtil.settingValueToString(setting)); + return Stream.of(SettingsUtil.settingValueToString(setting)); } } } diff --git a/src/api/java/baritone/api/utils/command/Command.java b/src/api/java/baritone/api/utils/command/Command.java index 7fa3b2a8..410a34a9 100644 --- a/src/api/java/baritone/api/utils/command/Command.java +++ b/src/api/java/baritone/api/utils/command/Command.java @@ -27,8 +27,6 @@ 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; @@ -46,27 +44,20 @@ public abstract class Command implements Helper, AbstractGameEventListener { */ public final List names; - /** - * A single-line 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 single-line string containing a short description of this command's purpose. + * @param names The names of this command. This is what you put after the command prefix. */ - protected Command(List names, String shortDesc) { + protected Command(List names) { this.names = names.stream() .map(s -> s.toLowerCase(Locale.US)) - .collect(Collectors.toCollection(ArrayList::new)); - this.shortDesc = shortDesc; + .collect(Collectors.toList()); baritone.getGameEventHandler().registerEventListener(this); } - protected Command(String name, String shortDesc) { - this(Collections.singletonList(name), shortDesc); + protected Command(String name) { + this(Collections.singletonList(name)); } /** @@ -88,7 +79,7 @@ public abstract class Command implements Helper, AbstractGameEventListener { try { return tabCompleted(execution.label, execution.args, execution.settings); } catch (Throwable t) { - return Arrays.stream(new String[0]); + return Stream.empty(); } } @@ -103,6 +94,11 @@ public abstract class Command implements Helper, AbstractGameEventListener { */ protected abstract Stream tabCompleted(String label, ArgConsumer args, Settings settings); + /** + * @return A single-line string containing a short description of this command's purpose. + */ + public abstract String getShortDesc(); + /** * @return A list of lines that will be printed by the help command when the user wishes to view them. */ diff --git a/src/api/java/baritone/api/utils/command/argparser/ArgParserManager.java b/src/api/java/baritone/api/utils/command/argparser/ArgParserManager.java index 6b5d4761..619fa67a 100644 --- a/src/api/java/baritone/api/utils/command/argparser/ArgParserManager.java +++ b/src/api/java/baritone/api/utils/command/argparser/ArgParserManager.java @@ -22,8 +22,6 @@ 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 { @@ -38,16 +36,13 @@ public class ArgParserManager { * @return A parser that can parse arguments into this class, if found. */ public static ArgParser.Stateless getParserStateless(Class klass) { - for (Iterator it = REGISTRY.descendingIterator(); it.hasNext(); ) { - ArgParser parser = it.next(); - - if (parser instanceof ArgParser.Stateless && parser.getKlass().isAssignableFrom(klass)) { - //noinspection unchecked - return (ArgParser.Stateless) parser; - } - } - - return null; + //noinspection unchecked + return REGISTRY.descendingStream() + .filter(ArgParser.Stateless.class::isInstance) + .map(ArgParser.Stateless.class::cast) + .filter(parser -> parser.getKlass().isAssignableFrom(klass)) + .findFirst() + .orElse(null); } /** @@ -55,21 +50,27 @@ public class ArgParserManager { * @return A parser that can parse arguments into this class, if found. */ public static ArgParser.Stated getParserStated(Class klass, Class stateKlass) { - for (Iterator 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) parser; - } - } - - return null; + //noinspection unchecked + return REGISTRY.descendingStream() + .filter(ArgParser.Stated.class::isInstance) + .map(ArgParser.Stated.class::cast) + .filter(parser -> parser.getKlass().isAssignableFrom(klass)) + .filter(parser -> parser.getStateKlass().isAssignableFrom(stateKlass)) + .map(ArgParser.Stated.class::cast) + .findFirst() + .orElse(null); } + /** + * Attempt to parse the specified argument with a stateless {@link ArgParser} that outputs the specified class. + * + * @param klass The class to parse the argument into. + * @param arg The argument to parse. + * @return An instance of the specified class. + * @throws CommandNoParserForTypeException If no parser exists for that type + * @throws CommandInvalidTypeException If the parsing failed + * @see ArgParser.Stateless + */ public static T parseStateless(Class klass, CommandArgument arg) { ArgParser.Stateless parser = getParserStateless(klass); @@ -84,6 +85,17 @@ public class ArgParserManager { } } + /** + * Attempt to parse the specified argument with a stated {@link ArgParser} that outputs the specified class. + * + * @param klass The class to parse the argument into. + * @param arg The argument to parse. + * @param state The state to pass to the {@link ArgParser.Stated}. + * @return An instance of the specified class. + * @throws CommandNoParserForTypeException If no parser exists for that type + * @throws CommandInvalidTypeException If the parsing failed + * @see ArgParser.Stated + */ public static T parseStated(Class klass, Class stateKlass, CommandArgument arg, S state) { ArgParser.Stated parser = getParserStated(klass, stateKlass); diff --git a/src/api/java/baritone/api/utils/command/argparser/DefaultArgParsers.java b/src/api/java/baritone/api/utils/command/argparser/DefaultArgParsers.java index ae80734d..fe964bce 100644 --- a/src/api/java/baritone/api/utils/command/argparser/DefaultArgParsers.java +++ b/src/api/java/baritone/api/utils/command/argparser/DefaultArgParsers.java @@ -19,7 +19,6 @@ 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; @@ -114,11 +113,11 @@ public class DefaultArgParsers { } } - public static final List> all = Collections.unmodifiableList(asList( + public static final List> all = asList( IntArgumentParser.INSTANCE, LongArgumentParser.INSTANCE, FloatArgumentParser.INSTANCE, DoubleArgumentParser.INSTANCE, BooleanArgumentParser.INSTANCE - )); + ); } diff --git a/src/api/java/baritone/api/utils/command/argparser/IArgParser.java b/src/api/java/baritone/api/utils/command/argparser/IArgParser.java index 1d8890ed..c8ac7630 100644 --- a/src/api/java/baritone/api/utils/command/argparser/IArgParser.java +++ b/src/api/java/baritone/api/utils/command/argparser/IArgParser.java @@ -25,6 +25,11 @@ public interface IArgParser { */ Class getKlass(); + /** + * A stateless argument parser is just that. It takes a {@link CommandArgument} and outputs its type. + * + * @see ArgParserManager#REGISTRY + */ interface Stateless extends IArgParser { /** * @param arg The argument to parse. @@ -35,6 +40,12 @@ public interface IArgParser { T parseArg(CommandArgument arg) throws RuntimeException; } + /** + * A stated argument parser is similar to a stateless one. It also takes a {@link CommandArgument}, but it also + * takes a second argument that can be any type, referred to as the state. + * + * @see ArgParserManager#REGISTRY + */ interface Stated extends IArgParser { Class getStateKlass(); diff --git a/src/api/java/baritone/api/utils/command/argument/CommandArgument.java b/src/api/java/baritone/api/utils/command/argument/CommandArgument.java index 8309e696..5d297528 100644 --- a/src/api/java/baritone/api/utils/command/argument/CommandArgument.java +++ b/src/api/java/baritone/api/utils/command/argument/CommandArgument.java @@ -17,16 +17,27 @@ package baritone.api.utils.command.argument; +import baritone.api.utils.command.argparser.ArgParser; import baritone.api.utils.command.argparser.ArgParserManager; +import baritone.api.utils.command.exception.CommandInvalidArgumentException; import baritone.api.utils.command.exception.CommandInvalidTypeException; +import baritone.api.utils.command.exception.CommandNoParserForTypeException; +import baritone.api.utils.command.helpers.arguments.ArgConsumer; +import net.minecraft.util.EnumFacing; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.NoSuchElementException; import java.util.regex.Matcher; import java.util.regex.Pattern; -@SuppressWarnings("UnusedReturnValue") +/** + * A {@link CommandArgument} is an immutable object representing one command argument. It contains data on the index of + * that argument, its value, and the rest of the string that argument was found in + *

+ * You're recommended to use {@link ArgConsumer}s to handle these. Check out {@link ArgConsumer#from(String)} + */ public class CommandArgument { public final int index; public final String value; @@ -39,18 +50,54 @@ public class CommandArgument { this.rawRest = rawRest; } + /** + * Gets an enum value from the enum class with the same name as this argument's value + *

+ * For example if you getEnum as an {@link EnumFacing}, and this argument's value is "up", it will return {@link + * EnumFacing#UP} + * + * @param enumClass The enum class to search + * @return An enum constant of that class with the same name as this argument's value + * @throws CommandInvalidTypeException If the constant couldn't be found + * @see ArgConsumer#peekEnum(Class) + * @see ArgConsumer#peekEnum(Class, int) + * @see ArgConsumer#peekEnumOrNull(Class) + * @see ArgConsumer#peekEnumOrNull(Class, int) + * @see ArgConsumer#getEnum(Class) + * @see ArgConsumer#getEnumOrNull(Class) + */ public > E getEnum(Class enumClass) { - //noinspection OptionalGetWithoutIsPresent - return Arrays.stream(enumClass.getEnumConstants()) - .filter(e -> e.name().equalsIgnoreCase(value)) - .findFirst() - .get(); + try { + //noinspection OptionalGetWithoutIsPresent + return Arrays.stream(enumClass.getEnumConstants()) + .filter(e -> e.name().equalsIgnoreCase(value)) + .findFirst() + .get(); + } catch (NoSuchElementException e) { + throw new CommandInvalidTypeException(this, enumClass.getSimpleName()); + } } + /** + * Tries to use a stateless {@link ArgParser} to parse this argument into the specified class + * + * @param type The class to parse this argument into + * @return An instance of the specified type + * @throws CommandNoParserForTypeException If no parser exists for that type + * @throws CommandInvalidTypeException If the parsing failed + * @see ArgParser.Stateless + */ public T getAs(Class type) { return ArgParserManager.parseStateless(type, this); } + /** + * Tries to use a stateless {@link ArgParser} to parse this argument into the specified class + * + * @param type The class to parse this argument into + * @return If the parser succeeded + * @see ArgParser.Stateless + */ public boolean is(Class type) { try { getAs(type); @@ -60,10 +107,27 @@ public class CommandArgument { } } + /** + * Tries to use a stated {@link ArgParser} to parse this argument into the specified class + * + * @param type The class to parse this argument into + * @return An instance of the specified type + * @throws CommandNoParserForTypeException If no parser exists for that type + * @throws CommandInvalidTypeException If the parsing failed + * @see ArgParser.Stated + */ + @SuppressWarnings("UnusedReturnValue") public T getAs(Class type, Class stateType, S state) { return ArgParserManager.parseStated(type, stateType, this, state); } + /** + * Tries to use a stated {@link ArgParser} to parse this argument into the specified class + * + * @param type The class to parse this argument into + * @return If the parser succeeded + * @see ArgParser.Stated + */ public boolean is(Class type, Class stateType, S state) { try { getAs(type, stateType, state); @@ -73,6 +137,14 @@ public class CommandArgument { } } + /** + * Turn a string into a list of {@link CommandArgument}s. This is needed because of {@link CommandArgument#rawRest} + * + * @param string The string to convert + * @param preserveEmptyLast If the string ends with whitespace, add an empty {@link CommandArgument} to the end This + * is useful for tab completion + * @return A list of {@link CommandArgument}s + */ public static List from(String string, boolean preserveEmptyLast) { List args = new ArrayList<>(); Matcher argMatcher = argPattern.matcher(string); @@ -94,10 +166,19 @@ public class CommandArgument { return args; } + /** + * @see #from(String, boolean) + */ public static List from(String string) { return from(string, false); } + /** + * Returns an "unknown" {@link CommandArgument}. This shouldn't be used unless you absolutely have no information - + * ESPECIALLY not with {@link CommandInvalidArgumentException}s + * + * @return The unknown {@link CommandArgument} + */ public static CommandArgument unknown() { return new CommandArgument(-1, "", ""); } diff --git a/src/api/java/baritone/api/utils/command/datatypes/BlockById.java b/src/api/java/baritone/api/utils/command/datatypes/BlockById.java index 13e3d686..617ccb57 100644 --- a/src/api/java/baritone/api/utils/command/datatypes/BlockById.java +++ b/src/api/java/baritone/api/utils/command/datatypes/BlockById.java @@ -36,7 +36,7 @@ public class BlockById implements IDatatypeFor { ResourceLocation id = new ResourceLocation(consumer.getString()); if ((block = Block.REGISTRY.getObject(id)) == Blocks.AIR) { - throw new RuntimeException("no block found by that id"); + throw new IllegalArgumentException("no block found by that id"); } } diff --git a/src/api/java/baritone/api/utils/command/datatypes/EntityClassById.java b/src/api/java/baritone/api/utils/command/datatypes/EntityClassById.java index ea22dc90..09cdbb92 100644 --- a/src/api/java/baritone/api/utils/command/datatypes/EntityClassById.java +++ b/src/api/java/baritone/api/utils/command/datatypes/EntityClassById.java @@ -38,7 +38,7 @@ public class EntityClassById implements IDatatypeFor> { ResourceLocation id = new ResourceLocation(consumer.getString()); if (isNull(entity = EntityList.REGISTRY.getObject(id))) { - throw new RuntimeException("no entity found by that id"); + throw new IllegalArgumentException("no entity found by that id"); } } diff --git a/src/api/java/baritone/api/utils/command/datatypes/ForWaypoints.java b/src/api/java/baritone/api/utils/command/datatypes/ForWaypoints.java index 90a1c71c..47b63480 100644 --- a/src/api/java/baritone/api/utils/command/datatypes/ForWaypoints.java +++ b/src/api/java/baritone/api/utils/command/datatypes/ForWaypoints.java @@ -29,8 +29,6 @@ import java.util.HashSet; import java.util.Set; import java.util.stream.Stream; -import static java.util.Arrays.asList; - public class ForWaypoints implements IDatatypeFor { private final IWaypoint[] waypoints; @@ -39,7 +37,7 @@ public class ForWaypoints implements IDatatypeFor { } public ForWaypoints(String arg) { - IWaypoint.Tag tag = getTagByName(arg); + IWaypoint.Tag tag = IWaypoint.Tag.getByName(arg); waypoints = tag == null ? getWaypointsByName(arg) : getWaypointsByTag(tag); } @@ -57,7 +55,7 @@ public class ForWaypoints implements IDatatypeFor { return new TabCompleteHelper() .append(getWaypointNames()) .sortAlphabetically() - .prepend(getTagNames()) + .prepend(IWaypoint.Tag.getAllNames()) .filterPrefix(consumer.getString()) .stream(); } @@ -70,28 +68,6 @@ public class ForWaypoints implements IDatatypeFor { .getWaypoints(); } - public static String[] getTagNames() { - Set names = new HashSet<>(); - - for (IWaypoint.Tag tag : IWaypoint.Tag.values()) { - names.addAll(asList(tag.names)); - } - - return names.toArray(new String[0]); - } - - public static IWaypoint.Tag getTagByName(String name) { - for (IWaypoint.Tag tag : IWaypoint.Tag.values()) { - for (String alias : tag.names) { - if (alias.equalsIgnoreCase(name)) { - return tag; - } - } - } - - return null; - } - public static IWaypoint[] getWaypoints() { return waypoints().getAllWaypoints().stream() .sorted(Comparator.comparingLong(IWaypoint::getCreationTimestamp).reversed()) diff --git a/src/api/java/baritone/api/utils/command/datatypes/IDatatype.java b/src/api/java/baritone/api/utils/command/datatypes/IDatatype.java index 1684fd2f..5af2a0b8 100644 --- a/src/api/java/baritone/api/utils/command/datatypes/IDatatype.java +++ b/src/api/java/baritone/api/utils/command/datatypes/IDatatype.java @@ -17,6 +17,7 @@ package baritone.api.utils.command.datatypes; +import baritone.api.utils.command.argparser.ArgParser; import baritone.api.utils.command.exception.CommandInvalidArgumentException; import baritone.api.utils.command.helpers.arguments.ArgConsumer; @@ -24,11 +25,23 @@ 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. + * 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 { + /** + * One benefit over datatypes over {@link ArgParser}s is that instead of each command trying to guess what values + * the datatype will accept, or simply not tab completing at all, datatypes that support tab completion can provide + * accurate information using the same methods used to parse arguments in the first place. + *

+ * See {@link RelativeFile} for a very advanced example of tab completion. You wouldn't want this pasted into every + * command that uses files - right? Right? + * + * @param consumer The argument consumer to tab complete + * @return A stream representing the strings that can be tab completed. DO NOT INCLUDE SPACES IN ANY STRINGS. + * @see ArgConsumer#tabCompleteDatatype(Class) + */ Stream tabComplete(ArgConsumer consumer); } diff --git a/src/api/java/baritone/api/utils/command/datatypes/PlayerByUsername.java b/src/api/java/baritone/api/utils/command/datatypes/PlayerByUsername.java index f38028bd..a3c54b48 100644 --- a/src/api/java/baritone/api/utils/command/datatypes/PlayerByUsername.java +++ b/src/api/java/baritone/api/utils/command/datatypes/PlayerByUsername.java @@ -46,7 +46,7 @@ public class PlayerByUsername implements IDatatypeFor { .findFirst() .orElse(null) )) { - throw new RuntimeException("no player found by that username"); + throw new IllegalArgumentException("no player found by that username"); } } diff --git a/src/api/java/baritone/api/utils/command/datatypes/RelativeCoordinate.java b/src/api/java/baritone/api/utils/command/datatypes/RelativeCoordinate.java index 8d5cc70b..866017c7 100644 --- a/src/api/java/baritone/api/utils/command/datatypes/RelativeCoordinate.java +++ b/src/api/java/baritone/api/utils/command/datatypes/RelativeCoordinate.java @@ -36,14 +36,10 @@ public class RelativeCoordinate implements IDatatypePost { } public RelativeCoordinate(ArgConsumer consumer) { - if (!consumer.has()) { - throw new RuntimeException("relative coordinate requires an argument"); - } - Matcher matcher = PATTERN.matcher(consumer.getString()); if (!matcher.matches()) { - throw new RuntimeException("pattern doesn't match"); + throw new IllegalArgumentException("pattern doesn't match"); } isRelative = !matcher.group(1).isEmpty(); diff --git a/src/api/java/baritone/api/utils/command/datatypes/RelativeFile.java b/src/api/java/baritone/api/utils/command/datatypes/RelativeFile.java index afc82978..fa0be0b4 100644 --- a/src/api/java/baritone/api/utils/command/datatypes/RelativeFile.java +++ b/src/api/java/baritone/api/utils/command/datatypes/RelativeFile.java @@ -42,7 +42,7 @@ public class RelativeFile implements IDatatypePost { try { path = FileSystems.getDefault().getPath(consumer.getString()); } catch (InvalidPathException e) { - throw new RuntimeException("invalid path"); + throw new IllegalArgumentException("invalid path"); } } diff --git a/src/api/java/baritone/api/utils/command/datatypes/RelativeGoalBlock.java b/src/api/java/baritone/api/utils/command/datatypes/RelativeGoalBlock.java index 1a907135..0730b517 100644 --- a/src/api/java/baritone/api/utils/command/datatypes/RelativeGoalBlock.java +++ b/src/api/java/baritone/api/utils/command/datatypes/RelativeGoalBlock.java @@ -17,7 +17,6 @@ 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; diff --git a/src/api/java/baritone/api/utils/command/exception/CommandUnhandledException.java b/src/api/java/baritone/api/utils/command/exception/CommandUnhandledException.java index dba4513e..9de56284 100644 --- a/src/api/java/baritone/api/utils/command/exception/CommandUnhandledException.java +++ b/src/api/java/baritone/api/utils/command/exception/CommandUnhandledException.java @@ -19,7 +19,6 @@ 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; @@ -35,7 +34,7 @@ public class CommandUnhandledException extends CommandErrorMessageException { public static String getBaritoneStackTrace(String stackTrace) { List lines = Arrays.stream(stackTrace.split("\n")) - .collect(Collectors.toCollection(ArrayList::new)); + .collect(Collectors.toList()); int lastBaritoneLine = 0; for (int i = 0; i < lines.size(); i++) { diff --git a/src/api/java/baritone/api/utils/command/helpers/arguments/ArgConsumer.java b/src/api/java/baritone/api/utils/command/helpers/arguments/ArgConsumer.java index 3cf823a0..c68b77c2 100644 --- a/src/api/java/baritone/api/utils/command/helpers/arguments/ArgConsumer.java +++ b/src/api/java/baritone/api/utils/command/helpers/arguments/ArgConsumer.java @@ -17,102 +17,328 @@ package baritone.api.utils.command.helpers.arguments; +import baritone.api.utils.Helper; +import baritone.api.utils.command.Command; +import baritone.api.utils.command.argparser.ArgParser; 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.datatypes.RelativeFile; import baritone.api.utils.command.exception.CommandException; import baritone.api.utils.command.exception.CommandInvalidTypeException; +import baritone.api.utils.command.exception.CommandNoParserForTypeException; import baritone.api.utils.command.exception.CommandNotEnoughArgumentsException; import baritone.api.utils.command.exception.CommandTooManyArgumentsException; import baritone.api.utils.command.exception.CommandUnhandledException; +import net.minecraft.util.EnumFacing; 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 args; +/** + * The {@link ArgConsumer} is how {@link Command}s read the arguments passed to them. This class has many benefits: + * + *

    + *
  • Mutability. The whole concept of the {@link ArgConsumer} is to let you gradually consume arguments in any way + * you'd like. You can change your consumption based on earlier arguments, for subcommands for example.
  • + *
  • You don't need to keep track of your consumption. The {@link ArgConsumer} keeps track of the arguments you + * consume so that it can throw detailed exceptions whenever something is out of the ordinary. Additionally, if you + * need to retrieve an argument after you've already consumed it - look no further than {@link #consumed()}!
  • + *
  • Easy retrieval of many different types. If you need to retrieve an instance of an int or float for example, + * look no further than {@link #getAs(Class)}. If you need a more powerful way of retrieving data, try out the many + * {@link #getDatatype(Class)} methods.
  • + *
  • It's very easy to throw detailed exceptions. The {@link ArgConsumer} has many different methods that can + * enforce the number of arguments, the type of arguments, and more, throwing different types of + * {@link CommandException}s if something seems off. You're recommended to do all validation and store all needed + * data in variables BEFORE logging any data to chat via {@link Helper#logDirect(String)}, so that the error + * handlers can do their job and log the error to chat.
  • + *
+ */ +public class ArgConsumer implements Cloneable { + /** + * The list of arguments in this ArgConsumer + */ + public final LinkedList args; + + /** + * The list of consumed arguments for this ArgConsumer. The most recently consumed argument is the last one + */ public final Deque consumed; - private ArgConsumer(List args, Deque consumed) { - this.args = new ArrayList<>(args); + private ArgConsumer(Deque args, Deque consumed) { + this.args = new LinkedList<>(args); this.consumed = new LinkedList<>(consumed); } public ArgConsumer(List args) { - this(args, new LinkedList<>()); + this(new LinkedList<>(args), new LinkedList<>()); } + /** + * @param num The number of arguments to check for + * @return {@code true} if there are at least {@code num} arguments left in this {@link ArgConsumer} + * @see #has() + * @see #hasAtMost(int) + * @see #hasExactly(int) + */ public boolean has(int num) { return args.size() >= num; } + /** + * @return {@code true} if there is at least 1 argument left in this {@link ArgConsumer} + * @see #has(int) + * @see #hasAtMostOne() + * @see #hasExactlyOne() + */ public boolean has() { return has(1); } + /** + * @param num The number of arguments to check for + * @return {@code true} if there are at most {@code num} arguments left in this {@link ArgConsumer} + * @see #has(int) + * @see #hasAtMost(int) + * @see #hasExactly(int) + */ public boolean hasAtMost(int num) { return args.size() <= num; } + /** + * @return {@code true} if there is at most 1 argument left in this {@link ArgConsumer} + * @see #has() + * @see #hasAtMostOne() + * @see #hasExactlyOne() + */ public boolean hasAtMostOne() { return hasAtMost(1); } + /** + * @param num The number of arguments to check for + * @return {@code true} if there are exactly {@code num} arguments left in this {@link ArgConsumer} + * @see #has(int) + * @see #hasAtMost(int) + */ public boolean hasExactly(int num) { return args.size() == num; } + /** + * @return {@code true} if there is exactly 1 argument left in this {@link ArgConsumer} + * @see #has() + * @see #hasAtMostOne() + */ public boolean hasExactlyOne() { return hasExactly(1); } + /** + * @param index The index to peek + * @return The argument at index {@code index} in this {@link ArgConsumer}, with 0 being the next one. This does not + * mutate the {@link ArgConsumer} + * @throws CommandNotEnoughArgumentsException If there is less than {@code index + 1} arguments left + * @see #peek() + * @see #peekString(int) + * @see #peekAs(Class, int) + * @see #get() + */ public CommandArgument peek(int index) { - requireMin(1); + requireMin(index + 1); return args.get(index); } + /** + * @return The next argument in this {@link ArgConsumer}. This does not mutate the {@link ArgConsumer} + * @throws CommandNotEnoughArgumentsException If there is less than one argument left + * @see #peek(int) + * @see #peekString() + * @see #peekAs(Class) + * @see #peekDatatype(Class) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypePost(Class, Object) + * @see #get() + */ public CommandArgument peek() { return peek(0); } - public boolean is(Class type) { - return peek().is(type); + /** + * @param index The index to peek + * @param type The type to check for + * @return If an {@link ArgParser.Stateless} for the specified {@code type} would succeed in parsing the next + * argument + * @throws CommandNotEnoughArgumentsException If there is less than {@code index + 1} arguments left + * @see #peek() + * @see #getAs(Class) + */ + public boolean is(Class type, int index) { + return peek(index).is(type); } + /** + * @param type The type to check for + * @return If an {@link ArgParser.Stateless} for the specified {@code type} would succeed in parsing the next + * argument + * @throws CommandNotEnoughArgumentsException If there is less than one argument left + * @see #peek() + * @see #getAs(Class) + */ + public boolean is(Class type) { + return is(type, 0); + } + + /** + * @param index The index to peek + * @return The value of the argument at index {@code index} in this {@link ArgConsumer}, with 0 being the next one + * This does not mutate the {@link ArgConsumer} + * @throws CommandNotEnoughArgumentsException If there is less than {@code index + 1} arguments left + * @see #peek() + * @see #peekString() + */ public String peekString(int index) { return peek(index).value; } + /** + * @return The value of the next argument in this {@link ArgConsumer}. This does not mutate the {@link ArgConsumer} + * @throws CommandNotEnoughArgumentsException If there is less than one argument left + * @see #peekString(int) + * @see #getString() + */ public String peekString() { return peekString(0); } - public > E peekEnum(Class enumClass) { - return peek().getEnum(enumClass); + /** + * @param index The index to peek + * @param enumClass The class to search + * @return From the specified enum class, an enum constant of that class. The enum constant's name will match the + * next argument's value + * @throws java.util.NoSuchElementException If the constant couldn't be found + * @see #peekEnumOrNull(Class) + * @see #getEnum(Class) + * @see CommandArgument#getEnum(Class) + */ + public > E peekEnum(Class enumClass, int index) { + return peek(index).getEnum(enumClass); } - public > E peekEnumOrNull(Class enumClass) { + /** + * @param enumClass The class to search + * @return From the specified enum class, an enum constant of that class. The enum constant's name will match the + * next argument's value + * @throws CommandInvalidTypeException If the constant couldn't be found + * @see #peekEnumOrNull(Class) + * @see #getEnum(Class) + * @see CommandArgument#getEnum(Class) + */ + public > E peekEnum(Class enumClass) { + return peekEnum(enumClass, 0); + } + + /** + * @param index The index to peek + * @param enumClass The class to search + * @return From the specified enum class, an enum constant of that class. The enum constant's name will match the + * next argument's value. If no constant could be found, null + * @see #peekEnum(Class) + * @see #getEnumOrNull(Class) + * @see CommandArgument#getEnum(Class) + */ + public > E peekEnumOrNull(Class enumClass, int index) { try { - return peekEnum(enumClass); - } catch (NoSuchElementException e) { + return peekEnum(enumClass, index); + } catch (CommandInvalidTypeException e) { return null; } } + /** + * @param enumClass The class to search + * @return From the specified enum class, an enum constant of that class. The enum constant's name will match the + * next argument's value. If no constant could be found, null + * @see #peekEnum(Class) + * @see #getEnumOrNull(Class) + * @see CommandArgument#getEnum(Class) + */ + public > E peekEnumOrNull(Class enumClass) { + try { + return peekEnumOrNull(enumClass, 0); + } catch (CommandInvalidTypeException e) { + return null; + } + } + + /** + * Tries to use a stateless {@link ArgParser} to parse the argument at the specified index into the specified + * class + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param type The type to peek as + * @param index The index to peek + * @return An instance of the specified type + * @throws CommandNoParserForTypeException If no parser exists for that type + * @throws CommandInvalidTypeException If the parsing failed + * @see ArgParser + * @see ArgParser.Stateless + * @see #peekAs(Class) + * @see #peekAsOrDefault(Class, Object, int) + * @see #peekAsOrNull(Class, int) + */ public T peekAs(Class type, int index) { return peek(index).getAs(type); } + /** + * Tries to use a stateless {@link ArgParser} to parse the next argument into the specified class + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param type The type to peek as + * @return An instance of the specified type + * @throws CommandNoParserForTypeException If no parser exists for that type + * @throws CommandInvalidTypeException If the parsing failed + * @see ArgParser + * @see ArgParser.Stateless + * @see #peekAs(Class, int) + * @see #peekAsOrDefault(Class, Object) + * @see #peekAsOrNull(Class) + */ public T peekAs(Class type) { return peekAs(type, 0); } + /** + * Tries to use a stateless {@link ArgParser} to parse the argument at the specified index into the specified + * class + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param type The type to peek as + * @param def The value to return if the argument can't be parsed + * @param index The index to peek + * @return An instance of the specified type, or {@code def} if it couldn't be parsed + * @see ArgParser + * @see ArgParser.Stateless + * @see #peekAsOrDefault(Class, Object) + * @see #peekAs(Class, int) + * @see #peekAsOrNull(Class, int) + */ public T peekAsOrDefault(Class type, T def, int index) { try { return peekAs(type, index); @@ -121,82 +347,466 @@ public class ArgConsumer { } } + /** + * Tries to use a stateless {@link ArgParser} to parse the next argument into the specified class + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param type The type to peek as + * @param def The value to return if the argument can't be parsed + * @return An instance of the specified type, or {@code def} if it couldn't be parsed + * @see ArgParser + * @see ArgParser.Stateless + * @see #peekAsOrDefault(Class, Object, int) + * @see #peekAs(Class) + * @see #peekAsOrNull(Class) + */ public T peekAsOrDefault(Class type, T def) { return peekAsOrDefault(type, def, 0); } + + /** + * Tries to use a stateless {@link ArgParser} to parse the argument at the specified index into the specified + * class + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param type The type to peek as + * @param index The index to peek + * @return An instance of the specified type, or {@code null} if it couldn't be parsed + * @see ArgParser + * @see ArgParser.Stateless + * @see #peekAsOrNull(Class) + * @see #peekAs(Class, int) + * @see #peekAsOrDefault(Class, Object, int) + */ public T peekAsOrNull(Class type, int index) { - return peekAsOrDefault(type, null, 0); + return peekAsOrDefault(type, null, index); } + /** + * Tries to use a stateless {@link ArgParser} to parse the next argument into the specified class + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param type The type to peek as + * @return An instance of the specified type, or {@code null} if it couldn't be parsed + * @see ArgParser + * @see ArgParser.Stateless + * @see #peekAsOrNull(Class, int) + * @see #peekAs(Class) + * @see #peekAsOrDefault(Class, Object) + */ public T peekAsOrNull(Class type) { return peekAsOrNull(type, 0); } + /** + * Attempts to get the specified datatype from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * Since this is a peek operation, this ArgConsumer will not be mutated by any call to this method. + * + * @param datatype The datatype to get + * @return The datatype instance + * @see IDatatype + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + */ public T peekDatatype(Class datatype) { return clone().getDatatype(datatype); } + /** + * Attempts to get the specified datatype from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * Since this is a peek operation, this ArgConsumer will not be mutated by any call to this method. + * + * @param datatype The datatype to get + * @return The datatype instance, or {@code null} if it throws an exception + * @see IDatatype + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + */ public T peekDatatypeOrNull(Class datatype) { - return new ArgConsumer(args, consumed).getDatatypeOrNull(datatype); + return clone().getDatatypeOrNull(datatype); } + /** + * Attempts to get the specified {@link IDatatypePost} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * Since this is a peek operation, this ArgConsumer will not be mutated by any call to this method. + * + * @param datatype The datatype to get + * @return The datatype instance + * @see IDatatype + * @see IDatatypePost + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + */ public > T peekDatatypePost(Class datatype, O original) { - return new ArgConsumer(args, consumed).getDatatypePost(datatype, original); + return clone().getDatatypePost(datatype, original); } + /** + * Attempts to get the specified {@link IDatatypePost} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * Since this is a peek operation, this ArgConsumer will not be mutated by any call to this method. + * + * @param datatype The datatype to get + * @param def The default value + * @return The datatype instance, or {@code def} if it throws an exception + * @see IDatatype + * @see IDatatypePost + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + */ public > T peekDatatypePostOrDefault(Class datatype, O original, T def) { - return new ArgConsumer(args, consumed).getDatatypePostOrDefault(datatype, original, def); + return clone().getDatatypePostOrDefault(datatype, original, def); } + /** + * Attempts to get the specified {@link IDatatypePost} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * Since this is a peek operation, this ArgConsumer will not be mutated by any call to this method. + * + * @param datatype The datatype to get + * @return The datatype instance, or {@code null} if it throws an exception + * @see IDatatype + * @see IDatatypePost + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + */ public > T peekDatatypePostOrNull(Class datatype, O original) { return peekDatatypePostOrDefault(datatype, original, null); } + /** + * Attempts to get the specified {@link IDatatypeFor} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * Since this is a peek operation, this ArgConsumer will not be mutated by any call to this method. + * + * @param datatype The datatype to get + * @return The datatype instance + * @see IDatatype + * @see IDatatypeFor + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + */ public > T peekDatatypeFor(Class datatype) { - return new ArgConsumer(args, consumed).peekDatatypeFor(datatype); + return clone().peekDatatypeFor(datatype); } + /** + * Attempts to get the specified {@link IDatatypeFor} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * Since this is a peek operation, this ArgConsumer will not be mutated by any call to this method. + * + * @param datatype The datatype to get + * @param def The default value + * @return The datatype instance, or {@code def} if it throws an exception + * @see IDatatype + * @see IDatatypeFor + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + */ public > T peekDatatypeForOrDefault(Class datatype, T def) { - return new ArgConsumer(args, consumed).peekDatatypeForOrDefault(datatype, def); + return clone().peekDatatypeForOrDefault(datatype, def); } - public > T peekDatatypeForOrNull(Class datatype, T def) { + /** + * Attempts to get the specified {@link IDatatypeFor} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * Since this is a peek operation, this ArgConsumer will not be mutated by any call to this method. + * + * @param datatype The datatype to get + * @return The datatype instance, or {@code null} if it throws an exception + * @see IDatatype + * @see IDatatypeFor + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + */ + public > T peekDatatypeForOrNull(Class datatype) { return peekDatatypeForOrDefault(datatype, null); } + /** + * Gets the next argument and returns it. This consumes the first argument so that subsequent calls will return + * later arguments + * + * @return The next argument + * @throws CommandNotEnoughArgumentsException If there's less than one argument left + */ public CommandArgument get() { requireMin(1); - CommandArgument arg = args.remove(0); + CommandArgument arg = args.removeFirst(); consumed.add(arg); return arg; } + /** + * Gets the value of the next argument and returns it. This consumes the first argument so that subsequent calls + * will return later arguments + * + * @return The value of the next argument + * @throws CommandNotEnoughArgumentsException If there's less than one argument left + */ public String getString() { return get().value; } + /** + * Gets an enum value from the enum class with the same name as the next argument's value + *

+ * For example if you getEnum as an {@link EnumFacing}, and the next argument's value is "up", this will return + * {@link EnumFacing#UP} + * + * @param enumClass The enum class to search + * @return An enum constant of that class with the same name as the next argument's value + * @throws CommandInvalidTypeException If the constant couldn't be found + * @see #peekEnum(Class) + * @see #getEnumOrNull(Class) + * @see CommandArgument#getEnum(Class) + */ public > E getEnum(Class enumClass) { - try { - return get().getEnum(enumClass); - } catch (NoSuchElementException e) { - throw new CommandInvalidTypeException(consumed(), enumClass.getSimpleName()); - } + return get().getEnum(enumClass); } - public > E getEnumOrNull(Class enumClass) { + /** + * Gets an enum value from the enum class with the same name as the next argument's value + *

+ * For example if you getEnum as an {@link EnumFacing}, and the next argument's value is "up", this will return + * {@link EnumFacing#UP} + * + * @param enumClass The enum class to search + * @param def The default value + * @return An enum constant of that class with the same name as the next argument's value, or {@code def} if it + * couldn't be found + * @see #getEnum(Class) + * @see #getEnumOrNull(Class) + * @see #peekEnumOrNull(Class) + * @see CommandArgument#getEnum(Class) + */ + public > E getEnumOrDefault(Class enumClass, E def) { try { peekEnum(enumClass); return getEnum(enumClass); } catch (CommandInvalidTypeException e) { - return null; + return def; } } + /** + * Gets an enum value from the enum class with the same name as the next argument's value + *

+ * For example if you getEnum as an {@link EnumFacing}, and the next argument's value is "up", this will return + * {@link EnumFacing#UP} + * + * @param enumClass The enum class to search + * @return An enum constant of that class with the same name as the next argument's value, or {@code null} if it + * couldn't be found + * @see #getEnum(Class) + * @see #getEnumOrDefault(Class, Enum) + * @see #peekEnumOrNull(Class) + * @see CommandArgument#getEnum(Class) + */ + public > E getEnumOrNull(Class enumClass) { + return getEnumOrDefault(enumClass, null); + } + + /** + * Tries to use a stateless {@link ArgParser} to parse the next argument into the specified class + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param type The type to peek as + * @return An instance of the specified type + * @throws CommandNoParserForTypeException If no parser exists for that type + * @throws CommandInvalidTypeException If the parsing failed + * @see ArgParser + * @see ArgParser.Stateless + * @see #get() + * @see #getAsOrDefault(Class, Object) + * @see #getAsOrNull(Class) + * @see #peekAs(Class) + * @see #peekAsOrDefault(Class, Object, int) + * @see #peekAsOrNull(Class, int) + */ public T getAs(Class type) { return get().getAs(type); } + /** + * Tries to use a stateless {@link ArgParser} to parse the next argument into the specified class + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param type The type to peek as + * @param def The default value + * @return An instance of the specified type, or {@code def} if it couldn't be parsed + * @see ArgParser + * @see ArgParser.Stateless + * @see #get() + * @see #getAs(Class) + * @see #getAsOrNull(Class) + * @see #peekAs(Class) + * @see #peekAsOrDefault(Class, Object, int) + * @see #peekAsOrNull(Class, int) + */ public T getAsOrDefault(Class type, T def) { try { T val = peek().getAs(type); @@ -207,10 +817,55 @@ public class ArgConsumer { } } + /** + * Tries to use a stateless {@link ArgParser} to parse the next argument into the specified class + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param type The type to peek as + * @return An instance of the specified type, or {@code null} if it couldn't be parsed + * @see ArgParser + * @see ArgParser.Stateless + * @see #get() + * @see #getAs(Class) + * @see #getAsOrDefault(Class, Object) + * @see #peekAs(Class) + * @see #peekAsOrDefault(Class, Object, int) + * @see #peekAsOrNull(Class, int) + */ public T getAsOrNull(Class type) { return getAsOrDefault(type, null); } + /** + * Attempts to get the specified datatype from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param datatype The datatype to get + * @return The datatype instance + * @see IDatatype + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + */ public T getDatatype(Class datatype) { try { return datatype.getConstructor(ArgConsumer.class).newInstance(this); @@ -221,46 +876,289 @@ public class ArgConsumer { } } + /** + * Attempts to get the specified datatype from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * The state of this {@link ArgConsumer} is restored if the datatype could not be gotten. + * + * @param datatype The datatype to get + * @return The datatype instance, or {@code null} if it throws an exception + * @see IDatatype + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + */ public T getDatatypeOrNull(Class datatype) { + List argsSnapshot = new ArrayList<>(args); + List consumedSnapshot = new ArrayList<>(consumed); + try { return getDatatype(datatype); } catch (CommandInvalidTypeException e) { + args.clear(); + args.addAll(argsSnapshot); + consumed.clear(); + consumed.addAll(consumedSnapshot); + return null; } } + /** + * Attempts to get the specified {@link IDatatypePost} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param datatype The datatype to get + * @return The datatype instance + * @see IDatatype + * @see IDatatypePost + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + */ public > T getDatatypePost(Class datatype, O original) { return getDatatype(datatype).apply(original); } + /** + * Attempts to get the specified {@link IDatatypePost} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * The state of this {@link ArgConsumer} is restored if the datatype could not be gotten. + * + * @param datatype The datatype to get + * @param def The default value + * @return The datatype instance, or {@code def} if it throws an exception + * @see IDatatype + * @see IDatatypePost + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + */ public > T getDatatypePostOrDefault(Class datatype, O original, T def) { + List argsSnapshot = new ArrayList<>(args); + List consumedSnapshot = new ArrayList<>(consumed); + try { return getDatatypePost(datatype, original); } catch (CommandException e) { + args.clear(); + args.addAll(argsSnapshot); + consumed.clear(); + consumed.addAll(consumedSnapshot); + return def; } } + /** + * Attempts to get the specified {@link IDatatypePost} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * The state of this {@link ArgConsumer} is restored if the datatype could not be gotten. + * + * @param datatype The datatype to get + * @return The datatype instance, or {@code null} if it throws an exception + * @see IDatatype + * @see IDatatypePost + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + */ public > T getDatatypePostOrNull(Class datatype, O original) { return getDatatypePostOrDefault(datatype, original, null); } + /** + * Attempts to get the specified {@link IDatatypeFor} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + * + * @param datatype The datatype to get + * @return The datatype instance + * @see IDatatype + * @see IDatatypeFor + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + */ public > T getDatatypeFor(Class datatype) { return getDatatype(datatype).get(); } + /** + * Attempts to get the specified {@link IDatatypeFor} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * The state of this {@link ArgConsumer} is restored if the datatype could not be gotten. + * + * @param datatype The datatype to get + * @param def The default value + * @return The datatype instance, or {@code def} if it throws an exception + * @see IDatatype + * @see IDatatypeFor + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + */ public > T getDatatypeForOrDefault(Class datatype, T def) { + List argsSnapshot = new ArrayList<>(args); + List consumedSnapshot = new ArrayList<>(consumed); + try { return getDatatypeFor(datatype); } catch (CommandInvalidTypeException e) { + args.clear(); + args.addAll(argsSnapshot); + consumed.clear(); + consumed.addAll(consumedSnapshot); + return def; } } + /** + * Attempts to get the specified {@link IDatatypeFor} from this ArgConsumer + *

+ * A critical difference between {@link IDatatype}s and {@link ArgParser}s is how many arguments they can take. + * While {@link ArgParser}s always operate on a single argument's value, {@link IDatatype}s get access to the entire + * {@link ArgConsumer}. + *

+ * The state of this {@link ArgConsumer} is restored if the datatype could not be gotten. + * + * @param datatype The datatype to get + * @return The datatype instance, or {@code null} if it throws an exception + * @see IDatatype + * @see IDatatypeFor + * @see #getDatatype(Class) + * @see #getDatatypeOrNull(Class) + * @see #getDatatypePost(Class, Object) + * @see #getDatatypePostOrDefault(Class, Object, Object) + * @see #getDatatypePostOrNull(Class, Object) + * @see #getDatatypeFor(Class) + * @see #getDatatypeForOrDefault(Class, Object) + * @see #getDatatypeForOrNull(Class) + * @see #peekDatatype(Class) + * @see #peekDatatypeOrNull(Class) + * @see #peekDatatypePost(Class, Object) + * @see #peekDatatypePostOrDefault(Class, Object, Object) + * @see #peekDatatypePostOrNull(Class, Object) + * @see #peekDatatypeFor(Class) + * @see #peekDatatypeForOrDefault(Class, Object) + * @see #peekDatatypeForOrNull(Class) + */ public > T getDatatypeForOrNull(Class datatype) { return getDatatypeForOrDefault(datatype, null); } + /** + * One benefit over datatypes over {@link ArgParser}s is that instead of each command trying to guess what values + * the datatype will accept, or simply not tab completing at all, datatypes that support tab completion can provide + * accurate information using the same methods used to parse arguments in the first place. + *

+ * See {@link RelativeFile} for a very advanced example of tab completion. You wouldn't want this pasted into every + * command that uses files - right? Right? + * + * @param datatype The datatype to get tab completions from + * @return A stream representing the strings that can be tab completed. DO NOT INCLUDE SPACES IN ANY STRINGS. + * @see IDatatype#tabComplete(ArgConsumer) + */ public Stream tabCompleteDatatype(Class datatype) { try { return datatype.getConstructor().newInstance().tabComplete(this); @@ -271,45 +1169,104 @@ public class ArgConsumer { return Stream.empty(); } + /** + * Returns the "raw rest" of the string. For example, from a string arg1 arg2  arg3, split + * into three {@link CommandArgument}s {@code "arg1"}, {@code "arg2"}, and {@code "arg3"}: + * + *

    + *
  • {@code rawRest()} would return arg1 arg2  arg3
  • + *
  • After calling {@link #get()}, {@code rawRest()} would return arg2  arg3 (note the + * double space - it is preserved!)
  • + *
  • After calling {@link #get()} again, {@code rawRest()} would return {@code "arg3"}
  • + *
  • After calling {@link #get()} one last time, {@code rawRest()} would return {@code ""}
  • + *
+ * + * @return The "raw rest" of the string. + */ public String rawRest() { - return args.size() > 0 ? args.get(0).rawRest : ""; + return args.size() > 0 ? args.getFirst().rawRest : ""; } + /** + * @param min The minimum amount of arguments to require. + * @throws CommandNotEnoughArgumentsException If there are less than {@code min} arguments left. + * @see #requireMax(int) + * @see #requireExactly(int) + */ public void requireMin(int min) { if (args.size() < min) { throw new CommandNotEnoughArgumentsException(min + consumed.size()); } } + /** + * @param max The maximum amount of arguments allowed. + * @throws CommandNotEnoughArgumentsException If there are more than {@code max} arguments left. + * @see #requireMin(int) + * @see #requireExactly(int) + */ public void requireMax(int max) { if (args.size() > max) { throw new CommandTooManyArgumentsException(max + consumed.size()); } } + /** + * @param args The exact amount of arguments to require. + * @throws CommandNotEnoughArgumentsException If there are less than {@code args} arguments left. + * @throws CommandTooManyArgumentsException If there are more than {@code args} arguments left. + * @see #requireMin(int) + * @see #requireMax(int) + */ public void requireExactly(int args) { requireMin(args); requireMax(args); } + /** + * @return If this {@link ArgConsumer} has consumed at least one argument. + * @see #consumed() + * @see #consumedString() + */ public boolean hasConsumed() { return !consumed.isEmpty(); } + /** + * @return The last argument this {@link ArgConsumer} has consumed, or the {@link CommandArgument#unknown() unknown} + * argument if no arguments have been consumed yet. + * @see #consumedString() + * @see #hasConsumed() + */ public CommandArgument consumed() { return consumed.size() > 0 ? consumed.getLast() : CommandArgument.unknown(); } + /** + * @return The value of thelast argument this {@link ArgConsumer} has consumed, or an empty string if no arguments + * have been consumed yet + * @see #consumed() + * @see #hasConsumed() + */ public String consumedString() { return consumed().value; } + /** + * @return A clone of this {@link ArgConsumer}. It has the same arguments (both consumed and not), but does not + * affect or mutate this instance. Useful for the various {@code peek} functions + */ @SuppressWarnings("MethodDoesntCallSuperMethod") @Override public ArgConsumer clone() { return new ArgConsumer(args, consumed); } + /** + * @param string The string to split + * @return A new {@link ArgConsumer} constructed from the specified string + * @see CommandArgument#from(String) + */ public static ArgConsumer from(String string) { return new ArgConsumer(CommandArgument.from(string)); } diff --git a/src/api/java/baritone/api/utils/command/helpers/pagination/Paginator.java b/src/api/java/baritone/api/utils/command/helpers/pagination/Paginator.java index 24d0b6a3..2fb2f5bc 100644 --- a/src/api/java/baritone/api/utils/command/helpers/pagination/Paginator.java +++ b/src/api/java/baritone/api/utils/command/helpers/pagination/Paginator.java @@ -79,45 +79,45 @@ public class Paginator implements Helper { boolean hasPrevPage = nonNull(commandPrefix) && validPage(page - 1); boolean hasNextPage = nonNull(commandPrefix) && validPage(page + 1); - logDirect(new TextComponentString("") {{ - getStyle().setColor(TextFormatting.GRAY); + ITextComponent prevPageComponent = new TextComponentString("<<"); - appendSibling(new TextComponentString("<<") {{ - if (hasPrevPage) { - getStyle() - .setClickEvent(new ClickEvent( - ClickEvent.Action.RUN_COMMAND, - String.format("%s %d", commandPrefix, page - 1) - )) - .setHoverEvent(new HoverEvent( - HoverEvent.Action.SHOW_TEXT, - new TextComponentString("Click to view previous page") - )); - } else { - getStyle().setColor(TextFormatting.DARK_GRAY); - } - }}); + if (hasPrevPage) { + prevPageComponent.getStyle() + .setClickEvent(new ClickEvent( + ClickEvent.Action.RUN_COMMAND, + String.format("%s %d", commandPrefix, page - 1) + )) + .setHoverEvent(new HoverEvent( + HoverEvent.Action.SHOW_TEXT, + new TextComponentString("Click to view previous page") + )); + } else { + prevPageComponent.getStyle().setColor(TextFormatting.DARK_GRAY); + } - appendText(" | "); + ITextComponent nextPageComponent = new TextComponentString(">>"); - appendSibling(new TextComponentString(">>") {{ - if (hasNextPage) { - getStyle() - .setClickEvent(new ClickEvent( - ClickEvent.Action.RUN_COMMAND, - commandPrefix + " " + (page + 1) - )) - .setHoverEvent(new HoverEvent( - HoverEvent.Action.SHOW_TEXT, - new TextComponentString("Click to view next page") - )); - } else { - getStyle().setColor(TextFormatting.DARK_GRAY); - } - }}); + if (hasNextPage) { + nextPageComponent.getStyle() + .setClickEvent(new ClickEvent( + ClickEvent.Action.RUN_COMMAND, + String.format("%s %d", commandPrefix, page + 1) + )) + .setHoverEvent(new HoverEvent( + HoverEvent.Action.SHOW_TEXT, + new TextComponentString("Click to view next page") + )); + } else { + nextPageComponent.getStyle().setColor(TextFormatting.DARK_GRAY); + } - appendText(String.format(" %d/%d", page, getMaxPage())); - }}); + ITextComponent pagerComponent = new TextComponentString(""); + pagerComponent.getStyle().setColor(TextFormatting.GRAY); + pagerComponent.appendSibling(prevPageComponent); + pagerComponent.appendText(" | "); + pagerComponent.appendSibling(nextPageComponent); + pagerComponent.appendText(String.format(" %d/%d", page, getMaxPage())); + logDirect(pagerComponent); } public void display(Function transform) { diff --git a/src/api/java/baritone/api/utils/command/helpers/tabcomplete/TabCompleteHelper.java b/src/api/java/baritone/api/utils/command/helpers/tabcomplete/TabCompleteHelper.java index ce689b0b..972b634d 100644 --- a/src/api/java/baritone/api/utils/command/helpers/tabcomplete/TabCompleteHelper.java +++ b/src/api/java/baritone/api/utils/command/helpers/tabcomplete/TabCompleteHelper.java @@ -19,7 +19,10 @@ package baritone.api.utils.command.helpers.tabcomplete; import baritone.api.BaritoneAPI; import baritone.api.Settings; +import baritone.api.event.events.TabCompleteEvent; import baritone.api.utils.SettingsUtil; +import baritone.api.utils.command.execution.CommandExecution; +import baritone.api.utils.command.helpers.arguments.ArgConsumer; import baritone.api.utils.command.manager.CommandManager; import net.minecraft.util.ResourceLocation; @@ -31,9 +34,24 @@ 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; - +/** + * The {@link TabCompleteHelper} is a single-use object that helps you handle tab completion. It includes helper + * methods for appending and prepending streams, sorting, filtering by prefix, and so on. + *

+ * The recommended way to use this class is: + *

    + *
  • Create a new instance with the empty constructor
  • + *
  • Use {@code append}, {@code prepend} or {@code add} methods to add completions
  • + *
  • Sort using {@link #sort(Comparator)} or {@link #sortAlphabetically()} and then filter by prefix using + * {@link #filterPrefix(String)}
  • + *
  • Get the stream using {@link #stream()}
  • + *
  • Pass it up to whatever's calling your tab complete function (i.e. + * {@link CommandManager#tabComplete(CommandExecution)} or {@link ArgConsumer#tabCompleteDatatype(Class)})
  • + *
+ *

+ * For advanced users: if you're intercepting {@link TabCompleteEvent}s directly, use {@link #build()} instead for an + * array. + */ public class TabCompleteHelper { private Stream stream; @@ -49,16 +67,49 @@ public class TabCompleteHelper { this(new String[0]); } + /** + * Appends the specified stream to this {@link TabCompleteHelper} and returns it for chaining + * + * @param source The stream to append + * @return This {@link TabCompleteHelper} after having appended the stream + * @see #append(String...) + * @see #append(Class) + * @see #prepend(Stream) + * @see #prepend(String...) + * @see #prepend(Class) + */ public TabCompleteHelper append(Stream source) { - stream = concat(stream, source); + stream = Stream.concat(stream, source); return this; } + /** + * Appends the specified strings to this {@link TabCompleteHelper} and returns it for chaining + * + * @param source The stream to append + * @return This {@link TabCompleteHelper} after having appended the strings + * @see #append(Stream) + * @see #append(Class) + * @see #prepend(Stream) + * @see #prepend(String...) + * @see #prepend(Class) + */ public TabCompleteHelper append(String... source) { - return append(of(source)); + return append(Stream.of(source)); } + /** + * Appends all values of the specified enum to this {@link TabCompleteHelper} and returns it for chaining + * + * @param num The enum to append the values of + * @return This {@link TabCompleteHelper} after having appended the values + * @see #append(Stream) + * @see #append(String...) + * @see #prepend(Stream) + * @see #prepend(String...) + * @see #prepend(Class) + */ public TabCompleteHelper append(Class> num) { return append( Arrays.stream(num.getEnumConstants()) @@ -67,16 +118,49 @@ public class TabCompleteHelper { ); } + /** + * Prepends the specified stream to this {@link TabCompleteHelper} and returns it for chaining + * + * @param source The stream to prepend + * @return This {@link TabCompleteHelper} after having prepended the stream + * @see #append(Stream) + * @see #append(String...) + * @see #append(Class) + * @see #prepend(String...) + * @see #prepend(Class) + */ public TabCompleteHelper prepend(Stream source) { - stream = concat(source, stream); + stream = Stream.concat(source, stream); return this; } + /** + * Prepends the specified strings to this {@link TabCompleteHelper} and returns it for chaining + * + * @param source The stream to prepend + * @return This {@link TabCompleteHelper} after having prepended the strings + * @see #append(Stream) + * @see #append(String...) + * @see #append(Class) + * @see #prepend(Stream) + * @see #prepend(Class) + */ public TabCompleteHelper prepend(String... source) { - return prepend(of(source)); + return prepend(Stream.of(source)); } + /** + * Prepends all values of the specified enum to this {@link TabCompleteHelper} and returns it for chaining + * + * @param num The enum to prepend the values of + * @return This {@link TabCompleteHelper} after having prepended the values + * @see #append(Stream) + * @see #append(String...) + * @see #append(Class) + * @see #prepend(Stream) + * @see #prepend(String...) + */ public TabCompleteHelper prepend(Class> num) { return prepend( Arrays.stream(num.getEnumConstants()) @@ -85,44 +169,98 @@ public class TabCompleteHelper { ); } + /** + * Apply the specified {@code transform} to every element currently in this {@link TabCompleteHelper} and + * return this object for chaining + * + * @param transform The transform to apply + * @return This {@link TabCompleteHelper} + */ public TabCompleteHelper map(Function transform) { stream = stream.map(transform); return this; } + /** + * Apply the specified {@code filter} to every element currently in this {@link TabCompleteHelper} and return + * this object for chaining + * + * @param filter The filter to apply + * @return This {@link TabCompleteHelper} + */ public TabCompleteHelper filter(Predicate filter) { stream = stream.filter(filter); return this; } + /** + * Apply the specified {@code sort} to every element currently in this {@link TabCompleteHelper} and return + * this object for chaining + * + * @param comparator The comparator to use + * @return This {@link TabCompleteHelper} + */ public TabCompleteHelper sort(Comparator comparator) { stream = stream.sorted(comparator); return this; } + /** + * Sort every element currently in this {@link TabCompleteHelper} alphabetically and return this object for + * chaining + * + * @return This {@link TabCompleteHelper} + */ public TabCompleteHelper sortAlphabetically() { return sort(String.CASE_INSENSITIVE_ORDER); } + /** + * Filter out any element that doesn't start with {@code prefix} and return this object for chaining + * + * @param prefix The prefix to filter for + * @return This {@link TabCompleteHelper} + */ public TabCompleteHelper filterPrefix(String prefix) { return filter(x -> x.toLowerCase(Locale.US).startsWith(prefix.toLowerCase(Locale.US))); } + /** + * Filter out any element that doesn't start with {@code prefix} and return this object for chaining + *

+ * Assumes every element in this {@link TabCompleteHelper} is a {@link ResourceLocation} + * + * @param prefix The prefix to filter for + * @return This {@link TabCompleteHelper} + */ public TabCompleteHelper filterPrefixNamespaced(String prefix) { return filterPrefix(new ResourceLocation(prefix).toString()); } + /** + * @return An array containing every element in this {@link TabCompleteHelper} + * @see #stream() + */ public String[] build() { return stream.toArray(String[]::new); } + /** + * @return A stream containing every element in this {@link TabCompleteHelper} + * @see #build() + */ public Stream stream() { return stream; } + /** + * Appends every command in the {@link CommandManager#REGISTRY} to this {@link TabCompleteHelper} + * + * @return This {@link TabCompleteHelper} + */ public TabCompleteHelper addCommands() { return append( CommandManager.REGISTRY.descendingStream() @@ -131,6 +269,11 @@ public class TabCompleteHelper { ); } + /** + * Appends every setting in the {@link Settings} to this {@link TabCompleteHelper} + * + * @return This {@link TabCompleteHelper} + */ public TabCompleteHelper addSettings() { return append( BaritoneAPI.getSettings().allSettings.stream() @@ -140,6 +283,11 @@ public class TabCompleteHelper { ); } + /** + * Appends every modified setting in the {@link Settings} to this {@link TabCompleteHelper} + * + * @return This {@link TabCompleteHelper} + */ public TabCompleteHelper addModifiedSettings() { return append( SettingsUtil.modifiedSettings(BaritoneAPI.getSettings()).stream() @@ -148,6 +296,11 @@ public class TabCompleteHelper { ); } + /** + * Appends every {@link Boolean} setting in the {@link Settings} to this {@link TabCompleteHelper} + * + * @return This {@link TabCompleteHelper} + */ public TabCompleteHelper addToggleableSettings() { return append( BaritoneAPI.getSettings().getAllValuesByType(Boolean.class).stream() diff --git a/src/api/java/baritone/api/utils/command/registry/Registry.java b/src/api/java/baritone/api/utils/command/registry/Registry.java index c92d4d56..b17997d3 100644 --- a/src/api/java/baritone/api/utils/command/registry/Registry.java +++ b/src/api/java/baritone/api/utils/command/registry/Registry.java @@ -20,10 +20,10 @@ 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.HashSet; import java.util.Iterator; import java.util.LinkedList; -import java.util.Map; +import java.util.Set; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; @@ -50,11 +50,11 @@ public class Registry { private final Deque _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. + * A HashSet containing every entry currently registered. Entries are added to this set when something is registered + * and removed from the set when they are unregistered. An entry being present in this set indicates that it is + * currently registered, can be removed, and should not be reregistered until it is removed. */ - private final Map registered = new HashMap<>(); + private final Set registered = new HashSet<>(); /** * The collection of entries that are currently in this registry. This is a collection (and not a list) because, @@ -67,7 +67,7 @@ public class Registry { * @return If this entry is currently registered in this registry. */ public boolean registered(V entry) { - return registered.containsKey(entry); + return registered.contains(entry); } /** @@ -81,7 +81,7 @@ public class Registry { public boolean register(V entry) { if (!registered(entry)) { _entries.addFirst(entry); - registered.put(entry, true); + registered.add(entry); return true; } diff --git a/src/launch/java/baritone/launch/mixins/MixinChatTabCompleter.java b/src/launch/java/baritone/launch/mixins/MixinChatTabCompleter.java index 39fbb19d..1cbf32e7 100644 --- a/src/launch/java/baritone/launch/mixins/MixinChatTabCompleter.java +++ b/src/launch/java/baritone/launch/mixins/MixinChatTabCompleter.java @@ -25,13 +25,22 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(GuiChat.ChatTabCompleter.class) public abstract class MixinChatTabCompleter extends MixinTabCompleter { - @Inject(method = "*", at = @At("RETURN")) + @Inject( + method = "*", + at = @At("RETURN") + ) private void onConstruction(CallbackInfo ci) { isChatCompleter = true; } - @Inject(method = "complete", at = @At("HEAD"), cancellable = true) + @Inject( + method = "complete", + at = @At("HEAD"), + cancellable = true + ) private void onComplete(CallbackInfo ci) { - if (dontComplete) ci.cancel(); + if (dontComplete) { + ci.cancel(); + } } } diff --git a/src/launch/java/baritone/launch/mixins/MixinGuiChat.java b/src/launch/java/baritone/launch/mixins/MixinGuiChat.java index 9af0a3e9..86f2b1b0 100644 --- a/src/launch/java/baritone/launch/mixins/MixinGuiChat.java +++ b/src/launch/java/baritone/launch/mixins/MixinGuiChat.java @@ -31,7 +31,11 @@ public abstract class MixinGuiChat implements net.minecraft.util.ITabCompleter { @Shadow private TabCompleter tabCompleter; - @Inject(method = "setCompletions", at = @At("HEAD"), cancellable = true) + @Inject( + method = "setCompletions", + at = @At("HEAD"), + cancellable = true + ) private void onSetCompletions(String[] newCompl, CallbackInfo ci) { if (((ITabCompleter) tabCompleter).onGuiChatSetCompletions(newCompl)) { ci.cancel(); diff --git a/src/launch/java/baritone/launch/mixins/MixinGuiScreen.java b/src/launch/java/baritone/launch/mixins/MixinGuiScreen.java index 35fcc38b..78da7b21 100644 --- a/src/launch/java/baritone/launch/mixins/MixinGuiScreen.java +++ b/src/launch/java/baritone/launch/mixins/MixinGuiScreen.java @@ -17,7 +17,7 @@ package baritone.launch.mixins; -import baritone.api.utils.command.Lol; +import baritone.api.accessor.IGuiScreen; import net.minecraft.client.gui.GuiScreen; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; @@ -25,7 +25,7 @@ import org.spongepowered.asm.mixin.gen.Invoker; import java.net.URI; @Mixin(GuiScreen.class) -public abstract class MixinGuiScreen implements Lol { +public abstract class MixinGuiScreen implements IGuiScreen { @Override @Invoker("openWebLink") public abstract void openLink(URI url); diff --git a/src/launch/java/baritone/launch/mixins/MixinItemStack.java b/src/launch/java/baritone/launch/mixins/MixinItemStack.java index 4f27152d..03f5e25f 100644 --- a/src/launch/java/baritone/launch/mixins/MixinItemStack.java +++ b/src/launch/java/baritone/launch/mixins/MixinItemStack.java @@ -44,12 +44,18 @@ public abstract class MixinItemStack implements IItemStack { baritoneHash = item == null ? -1 : item.hashCode() + itemDamage; } - @Inject(method = "*", at = @At("RETURN")) + @Inject( + method = "*", + at = @At("RETURN") + ) private void onInit(CallbackInfo ci) { recalculateHash(); } - @Inject(method = "setItemDamage", at = @At("TAIL")) + @Inject( + method = "setItemDamage", + at = @At("TAIL") + ) private void onItemDamageSet(CallbackInfo ci) { recalculateHash(); } diff --git a/src/launch/java/baritone/launch/mixins/MixinStateImplementation.java b/src/launch/java/baritone/launch/mixins/MixinStateImplementation.java index 9e2e2396..de74a4db 100644 --- a/src/launch/java/baritone/launch/mixins/MixinStateImplementation.java +++ b/src/launch/java/baritone/launch/mixins/MixinStateImplementation.java @@ -40,7 +40,10 @@ public abstract class MixinStateImplementation { @Unique private int hashCode; - @Inject(method = "*", at = @At("RETURN")) + @Inject( + method = "*", + at = @At("RETURN") + ) private void onInit(CallbackInfo ci) { hashCode = properties.hashCode(); } diff --git a/src/launch/java/baritone/launch/mixins/MixinTabCompleter.java b/src/launch/java/baritone/launch/mixins/MixinTabCompleter.java index 6046ed21..b07dd9d0 100644 --- a/src/launch/java/baritone/launch/mixins/MixinTabCompleter.java +++ b/src/launch/java/baritone/launch/mixins/MixinTabCompleter.java @@ -63,17 +63,17 @@ public abstract class MixinTabCompleter implements ITabCompleter { textField.setCursorPosition(prefix.length()); } - @Inject(method = "requestCompletions", at = @At("HEAD"), cancellable = true) + @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; - } + IBaritone baritone = BaritoneAPI.getProvider().getPrimaryBaritone(); TabCompleteEvent.Pre event = new TabCompleteEvent.Pre(prefix); baritone.getGameEventHandler().onPreTabComplete(event); diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 0b7e614f..4b00c797 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -113,9 +113,6 @@ public class Baritone implements IBaritone { memoryBehavior = new MemoryBehavior(this); inventoryBehavior = new InventoryBehavior(this); inputOverrideHandler = new InputOverrideHandler(this); - - DefaultCommands.commands.forEach(CommandManager.REGISTRY::register); - new BaritoneChatControl(this); } this.pathingControlManager = new PathingControlManager(this); @@ -138,6 +135,9 @@ public class Baritone implements IBaritone { } this.initialized = true; + + DefaultCommands.COMMANDS.forEach(CommandManager.REGISTRY::register); + new BaritoneChatControl(this); } @Override diff --git a/src/main/java/baritone/behavior/InventoryBehavior.java b/src/main/java/baritone/behavior/InventoryBehavior.java index 0d600853..c278738a 100644 --- a/src/main/java/baritone/behavior/InventoryBehavior.java +++ b/src/main/java/baritone/behavior/InventoryBehavior.java @@ -133,7 +133,7 @@ public final class InventoryBehavior extends Behavior { } public boolean selectThrowawayForLocation(boolean select, int x, int y, int z) { - IBlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z, ctx.world().getBlockState(new BlockPos(x, y, z))); + IBlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z, baritone.bsi.get0(x, y, z)); if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof ItemBlock && maybe.equals(((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(ctx.world(), ctx.playerFeet(), EnumFacing.UP, (float) ctx.player().posX, (float) ctx.player().posY, (float) ctx.player().posZ, stack.getItem().getMetadata(stack.getMetadata()), ctx.player())))) { return true; // gotem } diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index d1d9a7d5..c3aa2ad9 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -291,11 +291,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, return hasPath() && !pausedThisTick; } - @Override - public boolean hasPath() { - return current != null; - } - @Override public PathExecutor getCurrent() { return current; diff --git a/src/main/java/baritone/cache/WorldScanner.java b/src/main/java/baritone/cache/WorldScanner.java index 3acd9661..458e7afe 100644 --- a/src/main/java/baritone/cache/WorldScanner.java +++ b/src/main/java/baritone/cache/WorldScanner.java @@ -17,7 +17,9 @@ package baritone.cache; +import baritone.api.cache.ICachedWorld; import baritone.api.cache.IWorldScanner; +import baritone.api.utils.BetterBlockPos; import baritone.api.utils.BlockOptionalMetaLookup; import baritone.api.utils.IPlayerContext; import baritone.utils.accessor.IBlockStateContainer; @@ -26,6 +28,7 @@ import net.minecraft.client.multiplayer.ChunkProviderClient; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.IChunkProvider; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import java.util.ArrayList; @@ -35,6 +38,8 @@ import java.util.Comparator; import java.util.List; import java.util.stream.IntStream; +import static java.util.Objects.nonNull; + public enum WorldScanner implements IWorldScanner { INSTANCE; @@ -44,6 +49,11 @@ public enum WorldScanner implements IWorldScanner { @Override public List scanChunkRadius(IPlayerContext ctx, BlockOptionalMetaLookup filter, int max, int yLevelThreshold, int maxSearchRadius) { ArrayList res = new ArrayList<>(); + + if (filter.blocks().isEmpty()) { + return res; + } + ChunkProviderClient chunkProvider = (ChunkProviderClient) ctx.world().getChunkProvider(); int maxSearchRadiusSq = maxSearchRadius * maxSearchRadius; @@ -79,8 +89,8 @@ public enum WorldScanner implements IWorldScanner { } } if ((allUnloaded && foundChunks) - || (res.size() >= max - && (searchRadiusSq > maxSearchRadiusSq || (searchRadiusSq > 1 && foundWithinY))) + || (res.size() >= max + && (searchRadiusSq > maxSearchRadiusSq || (searchRadiusSq > 1 && foundWithinY))) ) { return res; } @@ -90,6 +100,10 @@ public enum WorldScanner implements IWorldScanner { @Override public List scanChunk(IPlayerContext ctx, BlockOptionalMetaLookup filter, ChunkPos pos, int max, int yLevelThreshold) { + if (filter.blocks().isEmpty()) { + return Collections.emptyList(); + } + ChunkProviderClient chunkProvider = (ChunkProviderClient) ctx.world().getChunkProvider(); Chunk chunk = chunkProvider.getLoadedChunk(pos.x, pos.z); int playerY = ctx.playerFeet().getY(); @@ -121,7 +135,7 @@ public enum WorldScanner implements IWorldScanner { for (int i = 0; i < imax; i++) { IBlockState state = bsc.getAtPalette(storage[i]); if (filter.has(state)) { - int y = yReal | (i >> 8 & 15); + int y = yReal | ((i >> 8) & 15); if (result.size() >= max) { if (Math.abs(y - playerY) < yLevelThreshold) { foundWithinY = true; @@ -133,10 +147,32 @@ public enum WorldScanner implements IWorldScanner { } } } - result.add(new BlockPos(chunkX | (i & 15), y, chunkZ | (i >> 4 & 15))); + result.add(new BlockPos(chunkX | (i & 15), y, chunkZ | ((i >> 4) & 15))); } } } return foundWithinY; } + + public int repack(IPlayerContext ctx) { + IChunkProvider chunkProvider = ctx.world().getChunkProvider(); + ICachedWorld cachedWorld = ctx.worldData().getCachedWorld(); + + BetterBlockPos playerPos = ctx.playerFeet(); + int playerChunkX = playerPos.getX() >> 4; + int playerChunkZ = playerPos.getZ() >> 4; + int queued = 0; + for (int x = playerChunkX - 40; x <= playerChunkX + 40; x++) { + for (int z = playerChunkZ - 40; z <= playerChunkZ + 40; z++) { + Chunk chunk = chunkProvider.getLoadedChunk(x, z); + + if (nonNull(chunk) && !chunk.isEmpty()) { + queued++; + cachedWorld.queueForPacking(chunk); + } + } + } + + return queued; + } } diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 5bd19bc2..b8739d1c 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -177,7 +177,7 @@ public interface MovementHelper extends ActionCosts, Helper { return block.isPassable(null, null); } - static boolean isReplacable(int x, int y, int z, IBlockState state, BlockStateInterface bsi) { + static boolean isReplaceable(int x, int y, int z, IBlockState state, BlockStateInterface bsi) { // for MovementTraverse and MovementAscend // block double plant defaults to true when the block doesn't match, so don't need to check that case // all other overrides just return true or false @@ -207,6 +207,11 @@ public interface MovementHelper extends ActionCosts, Helper { return state.getMaterial().isReplaceable(); } + @Deprecated + static boolean isReplacable(int x, int y, int z, IBlockState state, BlockStateInterface bsi) { + return isReplaceable(x, y, z, state, bsi); + } + static boolean isDoorPassable(IPlayerContext ctx, BlockPos doorPos, BlockPos playerPos) { if (playerPos.equals(doorPos)) { return false; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java index cbc8cdd8..66827a35 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java @@ -73,7 +73,7 @@ public class MovementAscend extends Movement { if (additionalPlacementCost >= COST_INF) { return COST_INF; } - if (!MovementHelper.isReplacable(destX, y, destZ, toPlace, context.bsi)) { + if (!MovementHelper.isReplaceable(destX, y, destZ, toPlace, context.bsi)) { return COST_INF; } boolean foundPlaceOption = false; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index 8e660aff..41a183f8 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -152,7 +152,7 @@ public class MovementParkour extends Movement { return; } IBlockState toReplace = context.get(destX, y - 1, destZ); - if (!MovementHelper.isReplacable(destX, y - 1, destZ, toReplace, context.bsi)) { + if (!MovementHelper.isReplaceable(destX, y - 1, destZ, toReplace, context.bsi)) { return; } if (!checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java index 4eab7144..c1f5ed01 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java @@ -111,7 +111,7 @@ public class MovementTraverse extends Movement { if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) { return COST_INF; } - if (MovementHelper.isReplacable(destX, y - 1, destZ, destOn, context.bsi)) { + if (MovementHelper.isReplaceable(destX, y - 1, destZ, destOn, context.bsi)) { boolean throughWater = MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock()); if (MovementHelper.isWater(destOn.getBlock()) && throughWater) { // this happens when assume walk on water is true and this is a traverse in water, which isn't allowed diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 6bea9a7c..4d3c2e5c 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -79,6 +79,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil private int ticks; private boolean paused; private int layer; + private List approxPlaceable; public BuilderProcess(Baritone baritone) { super(baritone); @@ -147,6 +148,11 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil build("clear area", new FillSchematic(widthX, heightY, lengthZ, Blocks.AIR.getDefaultState()), origin); } + @Override + public List getApproxPlaceable() { + return new ArrayList<>(approxPlaceable); + } + private static ISchematic parse(NBTTagCompound schematic) { return Baritone.settings().mapArtMode.value ? new MapArtSchematic(schematic) : new Schematic(schematic); } @@ -163,7 +169,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil if (!schematic.inSchematic(x - origin.getX(), y - origin.getY(), z - origin.getZ(), current)) { return null; } - IBlockState state = schematic.desiredState(x - origin.getX(), y - origin.getY(), z - origin.getZ(), current); + IBlockState state = schematic.desiredState(x - origin.getX(), y - origin.getY(), z - origin.getZ(), current, this.approxPlaceable); if (state.getBlock() == Blocks.AIR) { return null; } @@ -214,7 +220,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil } } - private Optional searchForPlacables(BuilderCalculationContext bcc, List desirableOnHotbar) { + private Optional searchForPlaceables(BuilderCalculationContext bcc, List desirableOnHotbar) { BetterBlockPos center = ctx.playerFeet(); for (int dx = -5; dx <= 5; dx++) { for (int dy = -5; dy <= 1; dy++) { @@ -227,7 +233,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil continue; // irrelevant } IBlockState curr = bcc.bsi.get0(x, y, z); - if (MovementHelper.isReplacable(x, y, z, curr, bcc.bsi) && !valid(curr, desired)) { + if (MovementHelper.isReplaceable(x, y, z, curr, bcc.bsi) && !valid(curr, desired)) { if (dy == 1 && bcc.bsi.get0(x, y + 1, z).getBlock() == Blocks.AIR) { continue; } @@ -247,7 +253,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil for (EnumFacing against : EnumFacing.values()) { BetterBlockPos placeAgainstPos = new BetterBlockPos(x, y, z).offset(against); IBlockState placeAgainstState = bsi.get0(placeAgainstPos); - if (MovementHelper.isReplacable(placeAgainstPos.x, placeAgainstPos.y, placeAgainstPos.z, placeAgainstState, bsi)) { + if (MovementHelper.isReplaceable(placeAgainstPos.x, placeAgainstPos.y, placeAgainstPos.z, placeAgainstState, bsi)) { continue; } if (!ctx.world().mayPlace(toPlace.getBlock(), new BetterBlockPos(x, y, z), false, against, null)) { @@ -304,16 +310,16 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil private static Vec3d[] aabbSideMultipliers(EnumFacing side) { switch (side) { case UP: - return new Vec3d[] {new Vec3d(0.5, 1, 0.5), new Vec3d(0.1, 1, 0.5), new Vec3d(0.9, 1, 0.5), new Vec3d(0.5, 1, 0.1), new Vec3d(0.5, 1, 0.9)}; + return new Vec3d[]{new Vec3d(0.5, 1, 0.5), new Vec3d(0.1, 1, 0.5), new Vec3d(0.9, 1, 0.5), new Vec3d(0.5, 1, 0.1), new Vec3d(0.5, 1, 0.9)}; case DOWN: - return new Vec3d[] {new Vec3d(0.5, 0, 0.5), new Vec3d(0.1, 0, 0.5), new Vec3d(0.9, 0, 0.5), new Vec3d(0.5, 0, 0.1), new Vec3d(0.5, 0, 0.9)}; + return new Vec3d[]{new Vec3d(0.5, 0, 0.5), new Vec3d(0.1, 0, 0.5), new Vec3d(0.9, 0, 0.5), new Vec3d(0.5, 0, 0.1), new Vec3d(0.5, 0, 0.9)}; case NORTH: case SOUTH: case EAST: case WEST: double x = side.getXOffset() == 0 ? 0.5 : (1 + side.getXOffset()) / 2D; double z = side.getZOffset() == 0 ? 0.5 : (1 + side.getZOffset()) / 2D; - return new Vec3d[] {new Vec3d(x, 0.25, z), new Vec3d(x, 0.75, z)}; + return new Vec3d[]{new Vec3d(x, 0.25, z), new Vec3d(x, 0.75, z)}; default: // null throw new IllegalStateException(); } @@ -321,6 +327,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil @Override public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { + approxPlaceable = approxPlaceable(36); if (baritone.getInputOverrideHandler().isInputForcedDown(Input.CLICK_LEFT)) { ticks = 5; } else { @@ -348,8 +355,8 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil } schematic = new ISchematic() { @Override - public IBlockState desiredState(int x, int y, int z, IBlockState current) { - return realSchematic.desiredState(x, y, z, current); + public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { + return realSchematic.desiredState(x, y, z, current, BuilderProcess.this.approxPlaceable); } @Override @@ -416,7 +423,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } List desirableOnHotbar = new ArrayList<>(); - Optional toPlace = searchForPlacables(bcc, desirableOnHotbar); + Optional toPlace = searchForPlaceables(bcc, desirableOnHotbar); if (toPlace.isPresent() && isSafeToCancel && ctx.player().onGround && ticks <= 0) { Rotation rot = toPlace.get().rot; baritone.getLookBehavior().updateTarget(rot, true); @@ -428,14 +435,13 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } - List approxPlacable = placable(36); if (Baritone.settings().allowInventory.value) { ArrayList usefulSlots = new ArrayList<>(); List noValidHotbarOption = new ArrayList<>(); outer: for (IBlockState desired : desirableOnHotbar) { for (int i = 0; i < 9; i++) { - if (valid(approxPlacable.get(i), desired)) { + if (valid(approxPlaceable.get(i), desired)) { usefulSlots.add(i); continue outer; } @@ -446,7 +452,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil outer: for (int i = 9; i < 36; i++) { for (IBlockState desired : noValidHotbarOption) { - if (valid(approxPlacable.get(i), desired)) { + if (valid(approxPlaceable.get(i), desired)) { baritone.getInventoryBehavior().attemptToPutOnHotbar(i, usefulSlots::contains); break outer; } @@ -454,9 +460,9 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil } } - Goal goal = assemble(bcc, approxPlacable.subList(0, 9)); + Goal goal = assemble(bcc, approxPlaceable.subList(0, 9)); if (goal == null) { - goal = assemble(bcc, approxPlacable); // we're far away, so assume that we have our whole inventory to recalculate placable properly + goal = assemble(bcc, approxPlaceable); // we're far away, so assume that we have our whole inventory to recalculate placeable properly if (goal == null) { logDirect("Unable to do it. Pausing. resume to resume, cancel to cancel"); paused = true; @@ -528,7 +534,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil } if (bcc.bsi.worldContainsLoadedChunk(blockX, blockZ)) { // check if its in render distance, not if its in cache // we can directly observe this block, it is in render distance - if (valid(bcc.bsi.get0(blockX, blockY, blockZ), schematic.desiredState(x, y, z, current))) { + if (valid(bcc.bsi.get0(blockX, blockY, blockZ), schematic.desiredState(x, y, z, current, this.approxPlaceable))) { observedCompleted.add(BetterBlockPos.longHash(blockX, blockY, blockZ)); } else { incorrectPositions.add(new BetterBlockPos(blockX, blockY, blockZ)); @@ -553,14 +559,14 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil } } - private Goal assemble(BuilderCalculationContext bcc, List approxPlacable) { + private Goal assemble(BuilderCalculationContext bcc, List approxPlaceable) { List placeable = new ArrayList<>(); List breakable = new ArrayList<>(); List sourceLiquids = new ArrayList<>(); incorrectPositions.forEach(pos -> { IBlockState state = bcc.bsi.get0(pos); if (state.getBlock() instanceof BlockAir) { - if (approxPlacable.contains(bcc.getSchematic(pos.x, pos.y, pos.z, state))) { + if (approxPlaceable.contains(bcc.getSchematic(pos.x, pos.y, pos.z, state))) { placeable.add(pos); } } else { @@ -642,8 +648,8 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil if (ctx.world().getBlockState(pos).getBlock() != Blocks.AIR) { // TODO can this even happen? return new GoalPlace(pos); } - IBlockState current = ctx.world().getBlockState(pos.up()); - boolean allowSameLevel = current.getBlock() != Blocks.AIR; + boolean allowSameLevel = ctx.world().getBlockState(pos.up()).getBlock() != Blocks.AIR; + IBlockState current = ctx.world().getBlockState(pos); for (EnumFacing facing : Movement.HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP) { //noinspection ConstantConditions if (MovementHelper.canPlaceAgainst(ctx, pos.offset(facing)) && ctx.world().mayPlace(bcc.getSchematic(pos.getX(), pos.getY(), pos.getZ(), current).getBlock(), pos, false, facing, null)) { @@ -727,7 +733,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil return paused ? "Builder Paused" : "Building " + name; } - private List placable(int size) { + private List approxPlaceable(int size) { List result = new ArrayList<>(); for (int i = 0; i < size; i++) { ItemStack stack = ctx.player().inventory.mainInventory.get(i); @@ -751,7 +757,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil } public class BuilderCalculationContext extends CalculationContext { - private final List placable; + private final List placeable; private final ISchematic schematic; private final int originX; private final int originY; @@ -759,7 +765,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil public BuilderCalculationContext() { super(BuilderProcess.this.baritone, true); // wew lad - this.placable = placable(9); + this.placeable = approxPlaceable(9); this.schematic = BuilderProcess.this.schematic; this.originX = origin.getX(); this.originY = origin.getY(); @@ -771,7 +777,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil private IBlockState getSchematic(int x, int y, int z, IBlockState current) { if (schematic.inSchematic(x - originX, y - originY, z - originZ, current)) { - return schematic.desiredState(x - originX, y - originY, z - originZ, current); + return schematic.desiredState(x - originX, y - originY, z - originZ, current, BuilderProcess.this.approxPlaceable); } else { return null; } @@ -790,7 +796,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil // this won't be a schematic block, this will be a throwaway return placeBlockCost * 2; // we're going to have to break it eventually } - if (placable.contains(sch)) { + if (placeable.contains(sch)) { return 0; // thats right we gonna make it FREE to place a block where it should go in a structure // no place block penalty at all 😎 // i'm such an idiot that i just tried to copy and paste the epic gamer moment emoji too diff --git a/src/main/java/baritone/process/FollowProcess.java b/src/main/java/baritone/process/FollowProcess.java index 4defff5d..3c0ef0a2 100644 --- a/src/main/java/baritone/process/FollowProcess.java +++ b/src/main/java/baritone/process/FollowProcess.java @@ -87,7 +87,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo .filter(this::followable) .filter(this.filter) .distinct() - .collect(Collectors.toCollection(ArrayList::new)); + .collect(Collectors.toList()); } @Override diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index b7eb2bb8..a741c6d6 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -320,6 +320,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(block)) { BetterBlockPos pf = ctx.baritone.getPlayerContext().playerFeet(); + // maxRegionDistanceSq 2 means adjacent directly or adjacent diagonally; nothing further than that locs.addAll(ctx.worldData.getCachedWorld().getLocationsOf( BlockUtils.blockToString(block), Baritone.settings().maxCachedWorldScanCount.value, @@ -414,11 +415,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro @Override public void mineByName(int quantity, String... blocks) { - mine(quantity, new BlockOptionalMetaLookup( - Arrays.stream(Objects.requireNonNull(blocks)) - .map(BlockOptionalMeta::new) - .toArray(BlockOptionalMeta[]::new) - )); + mine(quantity, new BlockOptionalMetaLookup(blocks)); } @Override diff --git a/src/main/java/baritone/selection/SelectionRenderer.java b/src/main/java/baritone/selection/SelectionRenderer.java index a696fe67..435f7dc7 100644 --- a/src/main/java/baritone/selection/SelectionRenderer.java +++ b/src/main/java/baritone/selection/SelectionRenderer.java @@ -3,10 +3,12 @@ package baritone.selection; import baritone.api.event.events.RenderEvent; import baritone.api.event.listener.AbstractGameEventListener; import baritone.api.selection.ISelection; -import baritone.api.utils.IRenderer; +import baritone.utils.IRenderer; import net.minecraft.util.math.AxisAlignedBB; public class SelectionRenderer implements IRenderer, AbstractGameEventListener { + public static final double SELECTION_BOX_EXPANSION = .005D; + private final SelectionManager manager; SelectionRenderer(SelectionManager manager) { @@ -26,7 +28,7 @@ public class SelectionRenderer implements IRenderer, AbstractGameEventListener { IRenderer.startLines(settings.colorSelection.value, opacity, lineWidth, ignoreDepth); for (ISelection selection : selections) { - IRenderer.drawAABB(selection.aabb(), .005f); + IRenderer.drawAABB(selection.aabb(), SELECTION_BOX_EXPANSION); } if (settings.renderSelectionCorners.value) { diff --git a/src/main/java/baritone/utils/GuiClick.java b/src/main/java/baritone/utils/GuiClick.java index 9f805387..48b80231 100644 --- a/src/main/java/baritone/utils/GuiClick.java +++ b/src/main/java/baritone/utils/GuiClick.java @@ -22,7 +22,6 @@ import baritone.api.BaritoneAPI; import baritone.api.pathing.goals.GoalBlock; import baritone.api.pathing.goals.GoalTwoBlocks; import baritone.api.utils.BetterBlockPos; -import baritone.api.utils.IRenderer; import net.minecraft.client.gui.GuiScreen; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.entity.Entity; diff --git a/src/api/java/baritone/api/utils/IRenderer.java b/src/main/java/baritone/utils/IRenderer.java similarity index 97% rename from src/api/java/baritone/api/utils/IRenderer.java rename to src/main/java/baritone/utils/IRenderer.java index 534c509e..f9315de6 100644 --- a/src/api/java/baritone/api/utils/IRenderer.java +++ b/src/main/java/baritone/utils/IRenderer.java @@ -15,11 +15,12 @@ * along with Baritone. If not, see . */ -package baritone.api.utils; +package baritone.utils; import baritone.api.BaritoneAPI; import baritone.api.IBaritone; import baritone.api.Settings; +import baritone.api.utils.Helper; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; @@ -110,7 +111,7 @@ public interface IRenderer { tessellator.draw(); } - static void drawAABB(AxisAlignedBB aabb, float expand) { + static void drawAABB(AxisAlignedBB aabb, double expand) { drawAABB(aabb.grow(expand, expand, expand)); } } diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 3d141216..bfa0dc2d 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -29,7 +29,6 @@ import baritone.api.pathing.goals.GoalXZ; import baritone.api.pathing.goals.GoalYLevel; import baritone.api.utils.BetterBlockPos; import baritone.api.utils.Helper; -import baritone.api.utils.IRenderer; import baritone.api.utils.interfaces.IGoalRenderPos; import baritone.behavior.PathingBehavior; import baritone.pathing.path.PathExecutor; @@ -205,7 +204,7 @@ public final class PathRenderer implements IRenderer { toDraw = state.getSelectedBoundingBox(player.world, pos); } - IRenderer.drawAABB(toDraw, .002f); + IRenderer.drawAABB(toDraw, .002D); }); IRenderer.endLines(settings.renderSelectionBoxesIgnoreDepth.value); diff --git a/src/main/java/baritone/utils/command/defaults/AxisCommand.java b/src/main/java/baritone/utils/command/defaults/AxisCommand.java index 59f63867..794af0c5 100644 --- a/src/main/java/baritone/utils/command/defaults/AxisCommand.java +++ b/src/main/java/baritone/utils/command/defaults/AxisCommand.java @@ -30,7 +30,7 @@ import static java.util.Arrays.asList; public class AxisCommand extends Command { public AxisCommand() { - super(asList("axis", "highway"), "Set a goal to the axes"); + super(asList("axis", "highway")); } @Override @@ -46,6 +46,11 @@ public class AxisCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Set a goal to the axes"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/BlacklistCommand.java b/src/main/java/baritone/utils/command/defaults/BlacklistCommand.java index bb19480f..1152ee08 100644 --- a/src/main/java/baritone/utils/command/defaults/BlacklistCommand.java +++ b/src/main/java/baritone/utils/command/defaults/BlacklistCommand.java @@ -30,7 +30,7 @@ import static java.util.Arrays.asList; public class BlacklistCommand extends Command { public BlacklistCommand() { - super("blacklist", "Blacklist closest block"); + super("blacklist"); } @Override @@ -54,6 +54,11 @@ public class BlacklistCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Blacklist closest block"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/BuildCommand.java b/src/main/java/baritone/utils/command/defaults/BuildCommand.java index 1c64f118..dd789ccb 100644 --- a/src/main/java/baritone/utils/command/defaults/BuildCommand.java +++ b/src/main/java/baritone/utils/command/defaults/BuildCommand.java @@ -37,7 +37,7 @@ public class BuildCommand extends Command { private static final File schematicsDir = new File(Minecraft.getMinecraft().gameDir, "schematics"); public BuildCommand() { - super("build", "Build a schematic"); + super("build"); } @Override @@ -81,6 +81,11 @@ public class BuildCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Build a schematic"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/CancelCommand.java b/src/main/java/baritone/utils/command/defaults/CancelCommand.java index a07bfc3b..49fdc537 100644 --- a/src/main/java/baritone/utils/command/defaults/CancelCommand.java +++ b/src/main/java/baritone/utils/command/defaults/CancelCommand.java @@ -28,7 +28,7 @@ import static java.util.Arrays.asList; public class CancelCommand extends Command { public CancelCommand() { - super(asList("cancel", "stop"), "Cancel what Baritone is currently doing"); + super(asList("cancel", "stop")); } @Override @@ -43,6 +43,11 @@ public class CancelCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Cancel what Baritone is currently doing"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/ChestsCommand.java b/src/main/java/baritone/utils/command/defaults/ChestsCommand.java index 6d4fac07..72e07da1 100644 --- a/src/main/java/baritone/utils/command/defaults/ChestsCommand.java +++ b/src/main/java/baritone/utils/command/defaults/ChestsCommand.java @@ -36,7 +36,7 @@ import static java.util.Arrays.asList; public class ChestsCommand extends Command { public ChestsCommand() { - super("chests", "Display remembered inventories"); + super("chests"); } @Override @@ -69,6 +69,11 @@ public class ChestsCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Display remembered inventories"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/ClearareaCommand.java b/src/main/java/baritone/utils/command/defaults/ClearareaCommand.java index 974a9867..68fc547e 100644 --- a/src/main/java/baritone/utils/command/defaults/ClearareaCommand.java +++ b/src/main/java/baritone/utils/command/defaults/ClearareaCommand.java @@ -33,7 +33,7 @@ import static java.util.Arrays.asList; public class ClearareaCommand extends Command { public ClearareaCommand() { - super("cleararea", "Clear an area of all blocks"); + super("cleararea"); } @Override @@ -65,6 +65,11 @@ public class ClearareaCommand extends Command { return args.tabCompleteDatatype(RelativeBlockPos.class); } + @Override + public String getShortDesc() { + return "Clear an area of all blocks"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/ClickCommand.java b/src/main/java/baritone/utils/command/defaults/ClickCommand.java index 559752bd..494ae8f7 100644 --- a/src/main/java/baritone/utils/command/defaults/ClickCommand.java +++ b/src/main/java/baritone/utils/command/defaults/ClickCommand.java @@ -28,7 +28,7 @@ import static java.util.Arrays.asList; public class ClickCommand extends Command { public ClickCommand() { - super("click", "Open click"); + super("click"); } @Override @@ -43,6 +43,11 @@ public class ClickCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Open click"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/ComeCommand.java b/src/main/java/baritone/utils/command/defaults/ComeCommand.java index 0b5f40ce..cfbf1f46 100644 --- a/src/main/java/baritone/utils/command/defaults/ComeCommand.java +++ b/src/main/java/baritone/utils/command/defaults/ComeCommand.java @@ -33,7 +33,7 @@ import static java.util.Objects.isNull; public class ComeCommand extends Command { public ComeCommand() { - super("come", "Start heading towards your camera"); + super("come"); } @Override @@ -54,12 +54,17 @@ public class ComeCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Start heading towards your camera"; + } + @Override public List 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.", + "This can be useful in hacked clients where freecam doesn't move your player position.", "", "Usage:", "> come" diff --git a/src/main/java/baritone/utils/command/defaults/CommandAlias.java b/src/main/java/baritone/utils/command/defaults/CommandAlias.java index 0ffaf427..c407ca69 100644 --- a/src/main/java/baritone/utils/command/defaults/CommandAlias.java +++ b/src/main/java/baritone/utils/command/defaults/CommandAlias.java @@ -27,15 +27,18 @@ import java.util.List; import java.util.stream.Stream; public class CommandAlias extends Command { + private final String shortDesc; public final String target; public CommandAlias(List names, String shortDesc, String target) { - super(names, shortDesc); + super(names); + this.shortDesc = shortDesc; this.target = target; } public CommandAlias(String name, String shortDesc, String target) { - super(name, shortDesc); + super(name); + this.shortDesc = shortDesc; this.target = target; } @@ -49,6 +52,11 @@ public class CommandAlias extends Command { return CommandManager.tabComplete(String.format("%s %s", target, args.rawRest())); } + @Override + public String getShortDesc() { + return shortDesc; + } + @Override public List getLongDesc() { return Collections.singletonList(String.format("This command is an alias, for: %s ...", target)); diff --git a/src/main/java/baritone/utils/command/defaults/DefaultCommands.java b/src/main/java/baritone/utils/command/defaults/DefaultCommands.java index a52d252a..213bd393 100644 --- a/src/main/java/baritone/utils/command/defaults/DefaultCommands.java +++ b/src/main/java/baritone/utils/command/defaults/DefaultCommands.java @@ -18,7 +18,6 @@ package baritone.utils.command.defaults; import baritone.api.utils.command.Command; -import baritone.api.utils.command.manager.CommandManager; import java.util.Collections; import java.util.List; @@ -26,7 +25,7 @@ import java.util.List; import static java.util.Arrays.asList; public class DefaultCommands { - public static final List commands = Collections.unmodifiableList(asList( + public static final List COMMANDS = Collections.unmodifiableList(asList( new HelpCommand(), new SetCommand(), new CommandAlias(asList("modified", "mod", "baritone", "modifiedsettings"), "List modified settings", "set modified"), diff --git a/src/main/java/baritone/utils/command/defaults/EmptyCommand.java b/src/main/java/baritone/utils/command/defaults/EmptyCommand.java index 15951182..9298f32a 100644 --- a/src/main/java/baritone/utils/command/defaults/EmptyCommand.java +++ b/src/main/java/baritone/utils/command/defaults/EmptyCommand.java @@ -28,7 +28,7 @@ import static java.util.Arrays.asList; public class EmptyCommand extends Command { public EmptyCommand() { - super(asList("name1", "name2"), "Short description"); + super(asList("name1", "name2")); } @Override @@ -41,6 +41,11 @@ public class EmptyCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Short description"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/ExploreCommand.java b/src/main/java/baritone/utils/command/defaults/ExploreCommand.java index 24e02f26..c0925342 100644 --- a/src/main/java/baritone/utils/command/defaults/ExploreCommand.java +++ b/src/main/java/baritone/utils/command/defaults/ExploreCommand.java @@ -30,7 +30,7 @@ import static java.util.Arrays.asList; public class ExploreCommand extends Command { public ExploreCommand() { - super("explore", "Explore things"); + super("explore"); } @Override @@ -58,6 +58,11 @@ public class ExploreCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Explore things"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/ExploreFilterCommand.java b/src/main/java/baritone/utils/command/defaults/ExploreFilterCommand.java index 848e913b..9f637257 100644 --- a/src/main/java/baritone/utils/command/defaults/ExploreFilterCommand.java +++ b/src/main/java/baritone/utils/command/defaults/ExploreFilterCommand.java @@ -34,7 +34,7 @@ import static java.util.Arrays.asList; public class ExploreFilterCommand extends Command { public ExploreFilterCommand() { - super("explorefilter", "Explore chunks from a json"); + super("explorefilter"); } @Override @@ -73,6 +73,11 @@ public class ExploreFilterCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Explore chunks from a json"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/FarmCommand.java b/src/main/java/baritone/utils/command/defaults/FarmCommand.java index 8c265912..4390585c 100644 --- a/src/main/java/baritone/utils/command/defaults/FarmCommand.java +++ b/src/main/java/baritone/utils/command/defaults/FarmCommand.java @@ -28,7 +28,7 @@ import static java.util.Arrays.asList; public class FarmCommand extends Command { public FarmCommand() { - super("farm", "Farm nearby crops"); + super("farm"); } @Override @@ -43,6 +43,11 @@ public class FarmCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Farm nearby crops"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/FindCommand.java b/src/main/java/baritone/utils/command/defaults/FindCommand.java index 6fd620d1..4f71366a 100644 --- a/src/main/java/baritone/utils/command/defaults/FindCommand.java +++ b/src/main/java/baritone/utils/command/defaults/FindCommand.java @@ -32,7 +32,7 @@ import static java.util.Arrays.asList; public class FindCommand extends Command { public FindCommand() { - super("find", "Find positions of a certain block"); + super("find"); } @Override @@ -65,6 +65,11 @@ public class FindCommand extends Command { return args.tabCompleteDatatype(BlockById.class); } + @Override + public String getShortDesc() { + return "Find positions of a certain block"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/FollowCommand.java b/src/main/java/baritone/utils/command/defaults/FollowCommand.java index 0107ee3b..7588edd2 100644 --- a/src/main/java/baritone/utils/command/defaults/FollowCommand.java +++ b/src/main/java/baritone/utils/command/defaults/FollowCommand.java @@ -44,7 +44,7 @@ import static java.util.Objects.nonNull; public class FollowCommand extends Command { public FollowCommand() { - super("follow", "Follow entity things"); + super("follow"); } @Override @@ -131,6 +131,11 @@ public class FollowCommand extends Command { } } + @Override + public String getShortDesc() { + return "Follow entity things"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/ForceCancelCommand.java b/src/main/java/baritone/utils/command/defaults/ForceCancelCommand.java index 685db0c3..5bd7d58a 100644 --- a/src/main/java/baritone/utils/command/defaults/ForceCancelCommand.java +++ b/src/main/java/baritone/utils/command/defaults/ForceCancelCommand.java @@ -29,7 +29,7 @@ import static java.util.Arrays.asList; public class ForceCancelCommand extends Command { public ForceCancelCommand() { - super("forcecancel", "Force cancel"); + super("forcecancel"); } @Override @@ -46,6 +46,11 @@ public class ForceCancelCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Force cancel"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/GcCommand.java b/src/main/java/baritone/utils/command/defaults/GcCommand.java index 17e241cf..7e838c6f 100644 --- a/src/main/java/baritone/utils/command/defaults/GcCommand.java +++ b/src/main/java/baritone/utils/command/defaults/GcCommand.java @@ -28,7 +28,7 @@ import static java.util.Arrays.asList; public class GcCommand extends Command { public GcCommand() { - super("gc", "Call System.gc()"); + super("gc"); } @Override @@ -45,6 +45,11 @@ public class GcCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Call System.gc()"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/GoalCommand.java b/src/main/java/baritone/utils/command/defaults/GoalCommand.java index 883aed7e..55f09928 100644 --- a/src/main/java/baritone/utils/command/defaults/GoalCommand.java +++ b/src/main/java/baritone/utils/command/defaults/GoalCommand.java @@ -36,7 +36,7 @@ import static java.util.Objects.nonNull; public class GoalCommand extends Command { public GoalCommand() { - super("goal", "Set or clear the goal"); + super("goal"); } @Override @@ -86,6 +86,11 @@ public class GoalCommand extends Command { return helper.filterPrefix(args.getString()).stream(); } + @Override + public String getShortDesc() { + return "Set or clear the goal"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/HelpCommand.java b/src/main/java/baritone/utils/command/defaults/HelpCommand.java index 16bb128a..ccd7d640 100644 --- a/src/main/java/baritone/utils/command/defaults/HelpCommand.java +++ b/src/main/java/baritone/utils/command/defaults/HelpCommand.java @@ -24,12 +24,12 @@ 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.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.ArrayList; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -41,7 +41,7 @@ import static java.util.Objects.isNull; public class HelpCommand extends Command { public HelpCommand() { - super(asList("help", "?"), "View all commands or help on specific ones"); + super(asList("help", "?")); } @Override @@ -53,40 +53,35 @@ public class HelpCommand extends Command { args, new Paginator<>( CommandManager.REGISTRY.descendingStream() .filter(command -> !command.hiddenFromHelp()) - .collect(Collectors.toCollection(ArrayList::new)) + .collect(Collectors.toList()) ), () -> 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); + ITextComponent shortDescComponent = new TextComponentString(" - " + command.getShortDesc()); + shortDescComponent.getStyle().setColor(TextFormatting.DARK_GRAY); - appendSibling(new TextComponentString(names + "\n") {{ - getStyle().setColor(TextFormatting.WHITE); - }}); + ITextComponent namesComponent = new TextComponentString(names); + namesComponent.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)) - )); + ITextComponent hoverComponent = new TextComponentString(""); + hoverComponent.getStyle().setColor(TextFormatting.GRAY); + hoverComponent.appendSibling(namesComponent); + hoverComponent.appendText("\n" + command.getShortDesc()); + hoverComponent.appendText("\n\nClick to view full help"); + String clickCommand = FORCE_COMMAND_PREFIX + String.format("%s %s", label, command.names.get(0)); - appendSibling(new TextComponentString(" - " + command.shortDesc) {{ - getStyle().setColor(TextFormatting.DARK_GRAY); - }}); - }}; + ITextComponent component = new TextComponentString(name); + component.getStyle().setColor(TextFormatting.GRAY); + component.appendSibling(shortDescComponent); + component.getStyle() + .setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverComponent)) + .setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, clickCommand)); + return component; }, - FORCE_COMMAND_PREFIX + "help" + FORCE_COMMAND_PREFIX + label ); } else { String commandName = args.getString().toLowerCase(); @@ -96,16 +91,18 @@ public class HelpCommand extends Command { throw new CommandNotFoundException(commandName); } - logDirect(String.format("%s - %s", String.join(" / ", command.names), command.shortDesc)); + logDirect(String.format("%s - %s", String.join(" / ", command.names), command.getShortDesc())); 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" - )); - }}); + + ITextComponent returnComponent = new TextComponentString("Click to return to the help menu"); + returnComponent.getStyle().setClickEvent(new ClickEvent( + ClickEvent.Action.RUN_COMMAND, + FORCE_COMMAND_PREFIX + label + )); + + logDirect(returnComponent); } } @@ -118,6 +115,11 @@ public class HelpCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "View all commands or help on specific ones"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/InvertCommand.java b/src/main/java/baritone/utils/command/defaults/InvertCommand.java index a29f2c9b..1a46bdc7 100644 --- a/src/main/java/baritone/utils/command/defaults/InvertCommand.java +++ b/src/main/java/baritone/utils/command/defaults/InvertCommand.java @@ -33,7 +33,7 @@ import static java.util.Objects.isNull; public class InvertCommand extends Command { public InvertCommand() { - super("invert", "Run away from the current goal"); + super("invert"); } @Override @@ -62,6 +62,11 @@ public class InvertCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Run away from the current goal"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/MineCommand.java b/src/main/java/baritone/utils/command/defaults/MineCommand.java index ebfb7fe1..0f155e74 100644 --- a/src/main/java/baritone/utils/command/defaults/MineCommand.java +++ b/src/main/java/baritone/utils/command/defaults/MineCommand.java @@ -23,6 +23,7 @@ import baritone.api.utils.command.Command; import baritone.api.utils.command.datatypes.BlockById; import baritone.api.utils.command.datatypes.ForBlockOptionalMeta; import baritone.api.utils.command.helpers.arguments.ArgConsumer; +import baritone.cache.WorldScanner; import java.util.ArrayList; import java.util.List; @@ -32,7 +33,7 @@ import static java.util.Arrays.asList; public class MineCommand extends Command { public MineCommand() { - super("mine", "Mine some blocks"); + super("mine"); } @Override @@ -45,6 +46,7 @@ public class MineCommand extends Command { boms.add(args.getDatatypeFor(ForBlockOptionalMeta.class)); } + WorldScanner.INSTANCE.repack(ctx); baritone.getMineProcess().mine(quantity, boms.toArray(new BlockOptionalMeta[0])); logDirect(String.format("Mining %s", boms.toString())); } @@ -54,13 +56,24 @@ public class MineCommand extends Command { return args.tabCompleteDatatype(BlockById.class); } + @Override + public String getShortDesc() { + return "Mine some blocks"; + } + @Override public List getLongDesc() { return asList( + "The mine command allows you to tell Baritone to search for and mine individual blocks.", "", + "The specified blocks can be ores (which are commonly cached), or any other block.", + "", + "Also see the legitMine settings (see #set l legitMine).", "", "Usage:", - "> " + "> mine diamond_ore - Mines all diamonds it can find.", + "> mine redstone_ore lit_redstone_ore - Mines redstone ore.", + "> mine log:0 - Mines only oak logs." ); } } diff --git a/src/main/java/baritone/utils/command/defaults/PathCommand.java b/src/main/java/baritone/utils/command/defaults/PathCommand.java index d65819fa..b2c7e69f 100644 --- a/src/main/java/baritone/utils/command/defaults/PathCommand.java +++ b/src/main/java/baritone/utils/command/defaults/PathCommand.java @@ -26,6 +26,7 @@ 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 baritone.cache.WorldScanner; import java.util.List; import java.util.stream.Stream; @@ -35,7 +36,7 @@ import static java.util.Objects.isNull; public class PathCommand extends Command { public PathCommand() { - super("path", "Start heading towards a goal"); + super(asList("path", "goto")); } @Override @@ -51,6 +52,7 @@ public class PathCommand extends Command { } args.requireMax(0); + WorldScanner.INSTANCE.repack(ctx); customGoalProcess.setGoalAndPath(goal); logDirect("Now pathing"); } @@ -77,6 +79,11 @@ public class PathCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Start heading towards a goal"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/PauseResumeCommands.java b/src/main/java/baritone/utils/command/defaults/PauseResumeCommands.java index 2b3919e4..b8b3f91f 100644 --- a/src/main/java/baritone/utils/command/defaults/PauseResumeCommands.java +++ b/src/main/java/baritone/utils/command/defaults/PauseResumeCommands.java @@ -79,7 +79,7 @@ public class PauseResumeCommands { } ); - pauseCommand = new Command("pause", "Pauses Baritone until you use resume") { + pauseCommand = new Command("pause") { @Override protected void executed(String label, ArgConsumer args, Settings settings) { args.requireMax(0); @@ -97,6 +97,11 @@ public class PauseResumeCommands { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Pauses Baritone until you use resume"; + } + @Override public List getLongDesc() { return asList( @@ -110,7 +115,7 @@ public class PauseResumeCommands { } }; - resumeCommand = new Command("resume", "Resumes Baritone after a pause") { + resumeCommand = new Command("resume") { @Override protected void executed(String label, ArgConsumer args, Settings settings) { args.requireMax(0); @@ -128,6 +133,11 @@ public class PauseResumeCommands { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Resumes Baritone after a pause"; + } + @Override public List getLongDesc() { return asList( @@ -139,7 +149,7 @@ public class PauseResumeCommands { } }; - pausedCommand = new Command("paused", "Tells you if Baritone is paused") { + pausedCommand = new Command("paused") { @Override protected void executed(String label, ArgConsumer args, Settings settings) { args.requireMax(0); @@ -152,6 +162,11 @@ public class PauseResumeCommands { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Tells you if Baritone is paused"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/ProcCommand.java b/src/main/java/baritone/utils/command/defaults/ProcCommand.java index 469089f6..a0ada87f 100644 --- a/src/main/java/baritone/utils/command/defaults/ProcCommand.java +++ b/src/main/java/baritone/utils/command/defaults/ProcCommand.java @@ -33,7 +33,7 @@ import static java.util.Objects.isNull; public class ProcCommand extends Command { public ProcCommand() { - super("proc", "View process state information"); + super("proc"); } @Override @@ -69,6 +69,11 @@ public class ProcCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "View process state information"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/ReloadAllCommand.java b/src/main/java/baritone/utils/command/defaults/ReloadAllCommand.java index 73a0245d..a7904bda 100644 --- a/src/main/java/baritone/utils/command/defaults/ReloadAllCommand.java +++ b/src/main/java/baritone/utils/command/defaults/ReloadAllCommand.java @@ -28,7 +28,7 @@ import static java.util.Arrays.asList; public class ReloadAllCommand extends Command { public ReloadAllCommand() { - super("reloadall", "Reloads Baritone's cache for this world"); + super("reloadall"); } @Override @@ -43,6 +43,11 @@ public class ReloadAllCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Reloads Baritone's cache for this world"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/RenderCommand.java b/src/main/java/baritone/utils/command/defaults/RenderCommand.java index 3fa07ca3..90a260a5 100644 --- a/src/main/java/baritone/utils/command/defaults/RenderCommand.java +++ b/src/main/java/baritone/utils/command/defaults/RenderCommand.java @@ -29,7 +29,7 @@ import static java.util.Arrays.asList; public class RenderCommand extends Command { public RenderCommand() { - super("render", "Fix glitched chunks"); + super("render"); } @Override @@ -55,6 +55,11 @@ public class RenderCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Fix glitched chunks"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/RepackCommand.java b/src/main/java/baritone/utils/command/defaults/RepackCommand.java index 0cf2ae78..357197ee 100644 --- a/src/main/java/baritone/utils/command/defaults/RepackCommand.java +++ b/src/main/java/baritone/utils/command/defaults/RepackCommand.java @@ -18,47 +18,24 @@ package baritone.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 baritone.cache.WorldScanner; 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"); + super(asList("repack", "rescan")); } @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)); + logDirect(String.format("Queued %d chunks for repacking", WorldScanner.INSTANCE.repack(ctx))); } @Override @@ -66,6 +43,11 @@ public class RepackCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Re-cache chunks"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/SaveAllCommand.java b/src/main/java/baritone/utils/command/defaults/SaveAllCommand.java index a34a6a58..953e7527 100644 --- a/src/main/java/baritone/utils/command/defaults/SaveAllCommand.java +++ b/src/main/java/baritone/utils/command/defaults/SaveAllCommand.java @@ -28,7 +28,7 @@ import static java.util.Arrays.asList; public class SaveAllCommand extends Command { public SaveAllCommand() { - super("saveall", "Saves Baritone's cache for this world"); + super("saveall"); } @Override @@ -43,6 +43,11 @@ public class SaveAllCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Saves Baritone's cache for this world"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/SchematicaCommand.java b/src/main/java/baritone/utils/command/defaults/SchematicaCommand.java index edef29a7..be455bc2 100644 --- a/src/main/java/baritone/utils/command/defaults/SchematicaCommand.java +++ b/src/main/java/baritone/utils/command/defaults/SchematicaCommand.java @@ -28,7 +28,7 @@ import static java.util.Arrays.asList; public class SchematicaCommand extends Command { public SchematicaCommand() { - super("schematica", "Opens a Schematica schematic?"); + super("schematica"); } @Override @@ -42,10 +42,15 @@ public class SchematicaCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Builds the loaded schematic"; + } + @Override public List getLongDesc() { return asList( - "I'm not actually sure what this does.", + "Builds the schematica currently open in Schematica.", "", "Usage:", "> schematica" diff --git a/src/main/java/baritone/utils/command/defaults/SelCommand.java b/src/main/java/baritone/utils/command/defaults/SelCommand.java index c6529d3d..f04e0970 100644 --- a/src/main/java/baritone/utils/command/defaults/SelCommand.java +++ b/src/main/java/baritone/utils/command/defaults/SelCommand.java @@ -20,7 +20,7 @@ package baritone.utils.command.defaults; import baritone.api.Settings; import baritone.api.event.events.RenderEvent; import baritone.api.schematic.CompositeSchematic; -import baritone.api.schematic.FillBomSchematic; +import baritone.api.schematic.FillSchematic; import baritone.api.schematic.ReplaceSchematic; import baritone.api.schematic.ShellSchematic; import baritone.api.schematic.WallsSchematic; @@ -29,7 +29,6 @@ import baritone.api.selection.ISelectionManager; import baritone.api.utils.BetterBlockPos; import baritone.api.utils.BlockOptionalMeta; import baritone.api.utils.BlockOptionalMetaLookup; -import baritone.api.utils.IRenderer; import baritone.api.utils.ISchematic; import baritone.api.utils.command.Command; import baritone.api.utils.command.datatypes.ForBlockOptionalMeta; @@ -39,6 +38,7 @@ import baritone.api.utils.command.exception.CommandInvalidStateException; import baritone.api.utils.command.exception.CommandInvalidTypeException; import baritone.api.utils.command.helpers.arguments.ArgConsumer; import baritone.api.utils.command.helpers.tabcomplete.TabCompleteHelper; +import baritone.utils.IRenderer; import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.AxisAlignedBB; @@ -59,7 +59,7 @@ public class SelCommand extends Command { private BetterBlockPos pos1 = null; public SelCommand() { - super(asList("sel", "selection", "s"), "WorldEdit-like commands"); + super(asList("sel", "selection", "s")); } @Override @@ -118,10 +118,13 @@ public class SelCommand extends Command { List replacesList = new ArrayList<>(); - while (args.has()) { + replacesList.add(type); + + while (args.has(2)) { replacesList.add(args.getDatatypeFor(ForBlockOptionalMeta.class)); } + type = args.getDatatypeFor(ForBlockOptionalMeta.class); replaces = new BlockOptionalMetaLookup(replacesList.toArray(new BlockOptionalMeta[0])); } else { args.requireMax(0); @@ -149,7 +152,7 @@ public class SelCommand extends Command { Vec3i size = selection.size(); BetterBlockPos min = selection.min(); - ISchematic schematic = new FillBomSchematic(baritone, size.getX(), size.getY(), size.getZ(), type); + ISchematic schematic = new FillSchematic(baritone, size.getX(), size.getY(), size.getZ(), type); if (action == Action.WALLS) { schematic = new WallsSchematic(baritone, schematic); @@ -242,6 +245,11 @@ public class SelCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "WorldEdit-like commands"; + } + @Override public List getLongDesc() { return asList( @@ -263,7 +271,7 @@ public class SelCommand extends Command { "> sel walls/w [block] - Fill in the walls of the selection with a specified block.", "> sel shell/shl [block] - The same as walls, but fills in a ceiling and floor too.", "> sel cleararea/ca - Basically 'set air'.", - "> sel replace/r - Replaces, with 'place', all blocks listed after it.", + "> sel replace/r - Replaces blocks with another block.", "", "> sel expand - Expand the targets.", "> sel contract - Contract the targets.", diff --git a/src/main/java/baritone/utils/command/defaults/SetCommand.java b/src/main/java/baritone/utils/command/defaults/SetCommand.java index 3bf6267e..4588c450 100644 --- a/src/main/java/baritone/utils/command/defaults/SetCommand.java +++ b/src/main/java/baritone/utils/command/defaults/SetCommand.java @@ -24,18 +24,17 @@ 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.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.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; @@ -46,7 +45,7 @@ import static java.util.stream.Stream.of; public class SetCommand extends Command { public SetCommand() { - super(asList("set", "setting", "settings"), "View or change settings"); + super(asList("set", "setting", "settings")); } @Override @@ -71,7 +70,7 @@ public class SetCommand extends Command { .filter(s -> !s.getName().equals("logger")) .filter(s -> s.getName().toLowerCase(Locale.US).contains(search.toLowerCase(Locale.US))) .sorted((s1, s2) -> String.CASE_INSENSITIVE_ORDER.compare(s1.getName(), s2.getName())) - .collect(Collectors.toCollection(ArrayList::new)); + .collect(Collectors.toList()); Paginator.paginate( args, @@ -81,31 +80,29 @@ public class SetCommand extends Command { ? String.format("All %ssettings containing the string '%s':", viewModified ? "modified " : "", 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))); + setting -> { + ITextComponent typeComponent = new TextComponentString(String.format( + " (%s)", + settingTypeToString(setting) + )); + typeComponent.getStyle().setColor(TextFormatting.DARK_GRAY); - 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()) - )); + ITextComponent hoverComponent = new TextComponentString(""); + hoverComponent.getStyle().setColor(TextFormatting.GRAY); + hoverComponent.appendText(setting.getName()); + hoverComponent.appendText(String.format("\nType: %s", settingTypeToString(setting))); + hoverComponent.appendText(String.format("\n\nValue:\n%s", settingValueToString(setting))); + String commandSuggestion = settings.prefix.value + String.format("set %s ", setting.getName()); - appendSibling(new TextComponentString(String.format(" (%s)", settingTypeToString(setting))) {{ - getStyle().setColor(TextFormatting.DARK_GRAY); - }}); - }}, + ITextComponent component = new TextComponentString(setting.getName()); + component.getStyle().setColor(TextFormatting.GRAY); + component.appendSibling(typeComponent); + component.getStyle() + .setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverComponent)) + .setClickEvent(new ClickEvent(ClickEvent.Action.SUGGEST_COMMAND, commandSuggestion)); + + return component; + }, FORCE_COMMAND_PREFIX + "set " + arg + " " + search ); @@ -187,18 +184,19 @@ public class SetCommand extends Command { )); } - 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) - )); - }}); + ITextComponent oldValueComponent = new TextComponentString(String.format("Old value: %s", oldValue)); + oldValueComponent.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) + )); + + logDirect(oldValueComponent); if ((setting.getName().equals("chatControl") && !(Boolean) setting.value && !settings.chatControlAnyway.value) || setting.getName().equals("chatControlAnyway") && !(Boolean) setting.value && !settings.chatControl.value) { @@ -260,6 +258,11 @@ public class SetCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "View or change settings"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/ThisWayCommand.java b/src/main/java/baritone/utils/command/defaults/ThisWayCommand.java index d16dbd94..2f83cb0c 100644 --- a/src/main/java/baritone/utils/command/defaults/ThisWayCommand.java +++ b/src/main/java/baritone/utils/command/defaults/ThisWayCommand.java @@ -29,7 +29,7 @@ import static java.util.Arrays.asList; public class ThisWayCommand extends Command { public ThisWayCommand() { - super(asList("thisway", "forward"), "Travel in your current direction"); + super(asList("thisway", "forward")); } @Override @@ -51,6 +51,11 @@ public class ThisWayCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Travel in your current direction"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/TunnelCommand.java b/src/main/java/baritone/utils/command/defaults/TunnelCommand.java index 00d9e67c..8d59fba6 100644 --- a/src/main/java/baritone/utils/command/defaults/TunnelCommand.java +++ b/src/main/java/baritone/utils/command/defaults/TunnelCommand.java @@ -30,7 +30,7 @@ import static java.util.Arrays.asList; public class TunnelCommand extends Command { public TunnelCommand() { - super("tunnel", "Set a goal to tunnel in your current direction"); + super("tunnel"); } @Override @@ -51,6 +51,11 @@ public class TunnelCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Set a goal to tunnel in your current direction"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/VersionCommand.java b/src/main/java/baritone/utils/command/defaults/VersionCommand.java index 6cd06f9c..71b30c19 100644 --- a/src/main/java/baritone/utils/command/defaults/VersionCommand.java +++ b/src/main/java/baritone/utils/command/defaults/VersionCommand.java @@ -30,7 +30,7 @@ import static java.util.Objects.isNull; public class VersionCommand extends Command { public VersionCommand() { - super("version", "View the Baritone version"); + super("version"); } @Override @@ -51,6 +51,11 @@ public class VersionCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "View the Baritone version"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/command/defaults/WaypointsCommand.java b/src/main/java/baritone/utils/command/defaults/WaypointsCommand.java index 894b23a0..7069e02f 100644 --- a/src/main/java/baritone/utils/command/defaults/WaypointsCommand.java +++ b/src/main/java/baritone/utils/command/defaults/WaypointsCommand.java @@ -50,7 +50,7 @@ import static java.util.Arrays.asList; public class WaypointsCommand extends Command { public WaypointsCommand() { - super(asList("waypoints", "waypoint", "wp"), "Manage waypoints"); + super(asList("waypoints", "waypoint", "wp")); } @Override @@ -87,7 +87,7 @@ public class WaypointsCommand extends Command { FORCE_COMMAND_PREFIX, label, _action.names[0], - waypoint.getTag().names[0], + waypoint.getTag().getName(), waypoint.getCreationTimestamp() )) ); @@ -99,7 +99,7 @@ public class WaypointsCommand extends Command { toComponent.apply(waypoint, action == Action.LIST ? Action.INFO : action); if (action == Action.LIST) { - IWaypoint.Tag tag = args.has() ? ForWaypoints.getTagByName(args.peekString()) : null; + IWaypoint.Tag tag = args.has() ? IWaypoint.Tag.getByName(args.peekString()) : null; if (tag != null) { args.get(); @@ -125,7 +125,7 @@ public class WaypointsCommand extends Command { FORCE_COMMAND_PREFIX, label, action.names[0], - tag != null ? " " + tag.names[0] : "" + tag != null ? " " + tag.getName() : "" ) ); } else { @@ -137,7 +137,7 @@ public class WaypointsCommand extends Command { ); } } else if (action == Action.SAVE) { - IWaypoint.Tag tag = ForWaypoints.getTagByName(args.getString()); + IWaypoint.Tag tag = IWaypoint.Tag.getByName(args.getString()); if (tag == null) { throw new CommandInvalidStateException(String.format("'%s' is not a tag ", args.consumedString())); @@ -159,7 +159,7 @@ public class WaypointsCommand extends Command { logDirect(component); } else if (action == Action.CLEAR) { args.requireMax(1); - IWaypoint.Tag tag = ForWaypoints.getTagByName(args.getString()); + IWaypoint.Tag tag = IWaypoint.Tag.getByName(args.getString()); IWaypoint[] waypoints = ForWaypoints.getWaypointsByTag(tag); for (IWaypoint waypoint : waypoints) { @@ -221,7 +221,7 @@ public class WaypointsCommand extends Command { "%s%s delete %s @ %d", FORCE_COMMAND_PREFIX, label, - waypoint.getTag().names[0], + waypoint.getTag().getName(), waypoint.getCreationTimestamp() ) )); @@ -232,7 +232,7 @@ public class WaypointsCommand extends Command { "%s%s goal %s @ %d", FORCE_COMMAND_PREFIX, label, - waypoint.getTag().names[0], + waypoint.getTag().getName(), waypoint.getCreationTimestamp() ) )); @@ -275,7 +275,7 @@ public class WaypointsCommand extends Command { if (args.hasExactlyOne()) { if (action == Action.LIST || action == Action.SAVE || action == Action.CLEAR) { return new TabCompleteHelper() - .append(ForWaypoints.getTagNames()) + .append(IWaypoint.Tag.getAllNames()) .sortAlphabetically() .filterPrefix(args.getString()) .stream(); @@ -293,6 +293,11 @@ public class WaypointsCommand extends Command { return Stream.empty(); } + @Override + public String getShortDesc() { + return "Manage waypoints"; + } + @Override public List getLongDesc() { return asList( diff --git a/src/main/java/baritone/utils/schematic/FillSchematic.java b/src/main/java/baritone/utils/schematic/FillSchematic.java index 6bac6ce6..86fc7bae 100644 --- a/src/main/java/baritone/utils/schematic/FillSchematic.java +++ b/src/main/java/baritone/utils/schematic/FillSchematic.java @@ -19,7 +19,8 @@ package baritone.utils.schematic; import baritone.api.utils.ISchematic; import net.minecraft.block.state.IBlockState; -import net.minecraft.init.Blocks; + +import java.util.List; public class FillSchematic implements ISchematic { private final int widthX; @@ -35,7 +36,7 @@ public class FillSchematic implements ISchematic { } @Override - public IBlockState desiredState(int x, int y, int z, IBlockState current) { + public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { return state; } diff --git a/src/main/java/baritone/utils/schematic/Schematic.java b/src/main/java/baritone/utils/schematic/Schematic.java index 3efb2404..93e78120 100644 --- a/src/main/java/baritone/utils/schematic/Schematic.java +++ b/src/main/java/baritone/utils/schematic/Schematic.java @@ -22,6 +22,8 @@ import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.nbt.NBTTagCompound; +import java.util.List; + public class Schematic implements ISchematic { public final int widthX; public final int heightY; @@ -68,7 +70,7 @@ public class Schematic implements ISchematic { } @Override - public IBlockState desiredState(int x, int y, int z, IBlockState current) { + public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { return states[x][z][y]; } diff --git a/src/main/java/baritone/utils/schematic/schematica/SchematicAdapter.java b/src/main/java/baritone/utils/schematic/schematica/SchematicAdapter.java index 3ba9c314..548e3e37 100644 --- a/src/main/java/baritone/utils/schematic/schematica/SchematicAdapter.java +++ b/src/main/java/baritone/utils/schematic/schematica/SchematicAdapter.java @@ -23,6 +23,8 @@ import com.github.lunatrius.schematica.client.world.SchematicWorld; import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; +import java.util.List; + public final class SchematicAdapter implements ISchematic { private final SchematicWorld schematic; @@ -31,7 +33,7 @@ public final class SchematicAdapter implements ISchematic { } @Override - public IBlockState desiredState(int x, int y, int z, IBlockState current) { + public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) { return schematic.getSchematic().getBlockState(new BlockPos(x, y, z)); }