[feature] Baritone AutoComplete

Signed-off-by: Dominika <sokolov.dominika@gmail.com>
This commit is contained in:
Dominika 2021-01-04 23:28:17 -05:00 committed by liv
parent c1dbe4b84f
commit 1bfe13f605
4 changed files with 233 additions and 5 deletions

View File

@ -1,9 +1,15 @@
package me.zeroeightsix.kami.command 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.manager.managers.UUIDManager
import me.zeroeightsix.kami.module.Module import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.module.ModuleManager 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.Wrapper
import me.zeroeightsix.kami.util.threads.defaultScope
import net.minecraft.block.Block import net.minecraft.block.Block
import net.minecraft.item.Item import net.minecraft.item.Item
import net.minecraft.util.math.BlockPos import net.minecraft.util.math.BlockPos
@ -12,6 +18,7 @@ import org.kamiblue.command.AbstractArg
import org.kamiblue.command.AutoComplete import org.kamiblue.command.AutoComplete
import org.kamiblue.command.DynamicPrefixMatch import org.kamiblue.command.DynamicPrefixMatch
import org.kamiblue.command.StaticPrefixMatch import org.kamiblue.command.StaticPrefixMatch
import java.io.File
import java.util.* import java.util.*
import kotlin.streams.toList import kotlin.streams.toList
@ -62,12 +69,69 @@ class BlockArg(
} }
private companion object { private companion object {
val allBlockNames = ArrayList<String>().run { val allBlockNames = ArrayList<String>().apply {
Block.REGISTRY.keys.forEach { Block.REGISTRY.keys.forEach {
add(it.toString()) add(it.toString())
add(it.path) add(it.path)
} }
sorted() sort()
}
}
}
class BaritoneBlockArg(
override val name: String
) : AbstractArg<Block>(), 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<String>().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<File>(), 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<String>()
val schematicFiles: Collection<String>
get() {
if (timer.tick(2L) && schematicFolder.isDirectory) {
defaultScope.launch(Dispatchers.IO) {
schematicFolder.listFiles()?.map { it.name }?.let {
cachedFiles = it
}
}
}
return cachedFiles
} }
} }
} }

View File

@ -16,6 +16,7 @@ import org.kamiblue.command.AbstractArg
import org.kamiblue.command.CommandBuilder import org.kamiblue.command.CommandBuilder
import org.kamiblue.command.utils.BuilderBlock import org.kamiblue.command.utils.BuilderBlock
import org.kamiblue.command.utils.ExecuteBlock import org.kamiblue.command.utils.ExecuteBlock
import java.io.File
abstract class ClientCommand( abstract class ClientCommand(
name: String, name: String,
@ -65,6 +66,22 @@ abstract class ClientCommand(
arg(BlockPosArg(name), block) arg(BlockPosArg(name), block)
} }
@CommandBuilder
protected fun AbstractArg<*>.baritoneBlock(
name: String,
block: BuilderBlock<Block>
) {
arg(BaritoneBlockArg(name), block)
}
@CommandBuilder
protected fun AbstractArg<*>.schematic(
name: String,
file: BuilderBlock<File>
) {
arg(SchematicArg(name), file)
}
@CommandBuilder @CommandBuilder
protected fun AbstractArg<*>.executeAsync( protected fun AbstractArg<*>.executeAsync(
description: String = "No description", description: String = "No description",

View File

@ -1,20 +1,167 @@
package me.zeroeightsix.kami.command.commands package me.zeroeightsix.kami.command.commands
import me.zeroeightsix.kami.KamiMod
import me.zeroeightsix.kami.command.ClientCommand import me.zeroeightsix.kami.command.ClientCommand
import me.zeroeightsix.kami.command.CommandManager import me.zeroeightsix.kami.command.CommandManager
import me.zeroeightsix.kami.util.text.MessageSendHelper 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( object BaritoneCommand : ClientCommand(
name = "baritone", name = "baritone",
alias = arrayOf("b") alias = arrayOf("b")
) { ) {
init { init {
greedy("arguments") { args -> literal("thisway") {
executeSafe { int("blocks") { blocksArg ->
val newArgs = CommandManager.tryParseArgument(args.value) ?: return@executeSafe executeSafe("Walk in the current direction for X blocks.") {
MessageSendHelper.sendBaritoneCommand(*newArgs) 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 {
exec(args.value)
}
}
}
private fun exec(vararg args: String) {
val safeArgs = CommandManager.tryParseArgument(args.joinToString(" ")) ?: return
MessageSendHelper.sendBaritoneCommand(*safeArgs)
}
} }

View File

@ -44,7 +44,7 @@ object MessageSendHelper {
val prevValue = chatControl?.value val prevValue = chatControl?.value
chatControl?.value = true chatControl?.value = true
val event = ChatEvent(args.joinToString(separator = " ")) val event = ChatEvent(args.joinToString(" "))
BaritoneUtils.primary?.gameEventHandler?.onSendChatMessage(event) 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 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") sendBaritoneMessage("Invalid Command! Please view possible commands at https://github.com/cabaletta/baritone/blob/master/USAGE.md")