From 1bfe13f6057c4bab02735d77f56f2ec67f192d87 Mon Sep 17 00:00:00 2001 From: Dominika Date: Mon, 4 Jan 2021 23:28:17 -0500 Subject: [PATCH] [feature] Baritone AutoComplete Signed-off-by: Dominika --- .../java/me/zeroeightsix/kami/command/Args.kt | 68 +++++++- .../kami/command/ClientCommand.kt | 17 ++ .../kami/command/commands/BaritoneCommand.kt | 151 +++++++++++++++++- .../kami/util/text/MessageSendHelper.kt | 2 +- 4 files changed, 233 insertions(+), 5 deletions(-) diff --git a/src/main/java/me/zeroeightsix/kami/command/Args.kt b/src/main/java/me/zeroeightsix/kami/command/Args.kt index 5c2eaf568..e665a95ed 100644 --- a/src/main/java/me/zeroeightsix/kami/command/Args.kt +++ b/src/main/java/me/zeroeightsix/kami/command/Args.kt @@ -1,9 +1,15 @@ package me.zeroeightsix.kami.command +import baritone.cache.CachedChunk +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import me.zeroeightsix.kami.manager.managers.UUIDManager import me.zeroeightsix.kami.module.Module import me.zeroeightsix.kami.module.ModuleManager +import me.zeroeightsix.kami.util.TickTimer +import me.zeroeightsix.kami.util.TimeUnit import me.zeroeightsix.kami.util.Wrapper +import me.zeroeightsix.kami.util.threads.defaultScope import net.minecraft.block.Block import net.minecraft.item.Item import net.minecraft.util.math.BlockPos @@ -12,6 +18,7 @@ import org.kamiblue.command.AbstractArg import org.kamiblue.command.AutoComplete import org.kamiblue.command.DynamicPrefixMatch import org.kamiblue.command.StaticPrefixMatch +import java.io.File import java.util.* import kotlin.streams.toList @@ -62,16 +69,73 @@ class BlockArg( } private companion object { - val allBlockNames = ArrayList().run { + val allBlockNames = ArrayList().apply { Block.REGISTRY.keys.forEach { add(it.toString()) add(it.path) } - sorted() + sort() } } } +class BaritoneBlockArg( + override val name: String +) : AbstractArg(), AutoComplete by StaticPrefixMatch(baritoneBlockNames) { + + override suspend fun convertToType(string: String?): Block? { + if (string == null) return null + return Block.getBlockFromName(string) + } + + private companion object { + val baritoneBlockNames = ArrayList().apply { + CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.forEach { block -> + block.registryName?.let { + add(it.toString()) + add(it.path) + } + } + sort() + } + } +} + +class SchematicArg( + override val name: String +) : AbstractArg(), AutoComplete by DynamicPrefixMatch(::schematicFiles) { + + override suspend fun convertToType(string: String?): File? { + if (string == null) return null + + val nameWithoutExt = string.removeSuffix(".schematic") + val file = File("schematics").listFiles()?.filter { + it.exists() && it.isFile && it.name.equals("$nameWithoutExt.schematic", true) + } // this stupid find and search is required because ext4 is case sensitive (Linux) + + return file?.firstOrNull() + } + + private companion object { + val timer = TickTimer(TimeUnit.SECONDS) + val schematicFolder = File("schematics") + var cachedFiles = emptyList() + + val schematicFiles: Collection + get() { + if (timer.tick(2L) && schematicFolder.isDirectory) { + defaultScope.launch(Dispatchers.IO) { + schematicFolder.listFiles()?.map { it.name }?.let { + cachedFiles = it + } + } + } + + return cachedFiles + } + } +} + class ItemArg( override val name: String ) : AbstractArg(), AutoComplete by StaticPrefixMatch(allItemNames) { diff --git a/src/main/java/me/zeroeightsix/kami/command/ClientCommand.kt b/src/main/java/me/zeroeightsix/kami/command/ClientCommand.kt index 580f9e286..afeef112c 100644 --- a/src/main/java/me/zeroeightsix/kami/command/ClientCommand.kt +++ b/src/main/java/me/zeroeightsix/kami/command/ClientCommand.kt @@ -16,6 +16,7 @@ import org.kamiblue.command.AbstractArg import org.kamiblue.command.CommandBuilder import org.kamiblue.command.utils.BuilderBlock import org.kamiblue.command.utils.ExecuteBlock +import java.io.File abstract class ClientCommand( name: String, @@ -65,6 +66,22 @@ abstract class ClientCommand( arg(BlockPosArg(name), block) } + @CommandBuilder + protected fun AbstractArg<*>.baritoneBlock( + name: String, + block: BuilderBlock + ) { + arg(BaritoneBlockArg(name), block) + } + + @CommandBuilder + protected fun AbstractArg<*>.schematic( + name: String, + file: BuilderBlock + ) { + arg(SchematicArg(name), file) + } + @CommandBuilder protected fun AbstractArg<*>.executeAsync( description: String = "No description", diff --git a/src/main/java/me/zeroeightsix/kami/command/commands/BaritoneCommand.kt b/src/main/java/me/zeroeightsix/kami/command/commands/BaritoneCommand.kt index b2a794ffb..e583ed2e5 100644 --- a/src/main/java/me/zeroeightsix/kami/command/commands/BaritoneCommand.kt +++ b/src/main/java/me/zeroeightsix/kami/command/commands/BaritoneCommand.kt @@ -1,20 +1,167 @@ package me.zeroeightsix.kami.command.commands +import me.zeroeightsix.kami.KamiMod import me.zeroeightsix.kami.command.ClientCommand import me.zeroeightsix.kami.command.CommandManager import me.zeroeightsix.kami.util.text.MessageSendHelper +// TODO: Add the follow argument when Baritone 1.2.15 is released. +// Currently follow is broken on Forge 1.12.2 in 1.2.14, it is fixed in master branch. object BaritoneCommand : ClientCommand( name = "baritone", alias = arrayOf("b") ) { init { + literal("thisway") { + int("blocks") { blocksArg -> + executeSafe("Walk in the current direction for X blocks.") { + exec("thisway", blocksArg.value.toString()) + exec("path") + } + } + } + + literal("goal") { + literal("clear") { + executeSafe("Clear the current goal.") { + exec("goal", "clear") + } + } + + int("x/y") { xArg -> + executeSafe("Set goal to a Y level.") { + exec("goal", xArg.value.toString()) + } + + int("y/z") { yArg -> + executeSafe("Set goal to X Z.") { + exec("goal", xArg.value.toString(), yArg.value.toString()) + } + + int("z") { zArg -> + executeSafe("Set goal to X Y Z.") { + exec("goal", xArg.value.toString(), yArg.value.toString(), zArg.value.toString()) + } + } + } + } + } + + literal("path") { + executeSafe("Start pathing towards your set goal.") { + exec("path") + } + } + + literal("stop", "cancel") { + executeSafe("Stop the current Baritone process.") { + exec("stop") + } + } + + literal("mine") { + block("block") { blockArg -> + executeSafe("Mine a block.") { + exec("mine", blockArg.value.registryName!!.path) + } + } + + greedy("blocks") { blocksArg -> // TODO: When array arguments are added switch this over + executeSafe("Mine any amount of blocks.") { + exec("mine", blocksArg.value) + } + } + } + + literal("goto") { + blockPos("coordinates") { coordinatesArg -> + executeSafe("Go to a set of coordinates.") { + val coord = coordinatesArg.value + exec("goto", coord.x.toString(), coord.y.toString(), coord.z.toString()) + } + } + + baritoneBlock("cached block") { blockArg -> + executeSafe("Go to a Baritone cached block.") { + exec("goto", blockArg.value.registryName!!.path) + } + } + + greedy("x y z") { coordinatesArg -> + executeSafe("Go to a set of coords. Y and Z optional.") { + exec("goto", coordinatesArg.value) + } + } + } + + literal("click") { + executeSafe("Open the click and drag menu.") { + exec("click") + } + } + + literal("build") { + schematic("schematic") { schematicArg -> + executeSafe("Build something from inside the schematics folder.") { + exec("build", schematicArg.value.name) + } + } + } + + literal("schematica") { + executeSafe("Build the currently opened schematic in Schematica.") { + exec("schematica") + } + + greedy("args") { greedyArg -> + executeSafe("Build the currently opened schematic in Schematica.") { + exec("schematica", greedyArg.value) + } + } + } + + literal("farm") { + executeSafe("Automatically farm any found crops.") { + exec("farm") + } + } + + literal("explore") { + executeSafe("Explore away from you.") { + exec("explore") + } + + int("x") { xArg -> + int("z") { zArg -> + executeSafe("Explore away from X Z.") { + exec("explore", xArg.value.toString(), zArg.value.toString()) + } + } + } + } + + literal("invert") { + executeSafe("Go in the opposite direction of your goal.") { + exec("invert") + } + } + + literal("version") { + executeSafe { + exec("version") + MessageSendHelper.sendBaritoneMessage("Running on KAMI Blue ${KamiMod.VERSION}") + } + } + greedy("arguments") { args -> executeSafe { - val newArgs = CommandManager.tryParseArgument(args.value) ?: return@executeSafe - MessageSendHelper.sendBaritoneCommand(*newArgs) + exec(args.value) } } } + private fun exec(vararg args: String) { + val safeArgs = CommandManager.tryParseArgument(args.joinToString(" ")) ?: return + MessageSendHelper.sendBaritoneCommand(*safeArgs) + } } \ No newline at end of file diff --git a/src/main/java/me/zeroeightsix/kami/util/text/MessageSendHelper.kt b/src/main/java/me/zeroeightsix/kami/util/text/MessageSendHelper.kt index 99cc6099d..5496bcead 100644 --- a/src/main/java/me/zeroeightsix/kami/util/text/MessageSendHelper.kt +++ b/src/main/java/me/zeroeightsix/kami/util/text/MessageSendHelper.kt @@ -44,7 +44,7 @@ object MessageSendHelper { val prevValue = chatControl?.value chatControl?.value = true - val event = ChatEvent(args.joinToString(separator = " ")) + val event = ChatEvent(args.joinToString(" ")) BaritoneUtils.primary?.gameEventHandler?.onSendChatMessage(event) if (!event.isCancelled && args[0] != "damn") { // don't remove the 'damn', it's critical code that will break everything if you remove it sendBaritoneMessage("Invalid Command! Please view possible commands at https://github.com/cabaletta/baritone/blob/master/USAGE.md")