package moe.nea.firmament.commands import com.mojang.brigadier.CommandDispatcher import com.mojang.brigadier.arguments.StringArgumentType.string import io.ktor.client.statement.bodyAsText import net.fabricmc.fabric.api.client.command.v2.FabricClientCommandSource import net.minecraft.nbt.NbtOps import net.minecraft.text.Text import net.minecraft.text.TextCodecs import moe.nea.firmament.apis.UrsaManager import moe.nea.firmament.events.CommandEvent import moe.nea.firmament.events.FirmamentEventBus import moe.nea.firmament.features.debug.DebugLogger import moe.nea.firmament.features.debug.PowerUserTools import moe.nea.firmament.features.inventory.buttons.InventoryButtons import moe.nea.firmament.features.inventory.storageoverlay.StorageOverlayScreen import moe.nea.firmament.features.inventory.storageoverlay.StorageOverviewScreen import moe.nea.firmament.gui.config.AllConfigsGui import moe.nea.firmament.gui.config.BooleanHandler import moe.nea.firmament.gui.config.ManagedConfig import moe.nea.firmament.gui.config.ManagedOption import moe.nea.firmament.init.MixinPlugin import moe.nea.firmament.repo.HypixelStaticData import moe.nea.firmament.repo.RepoManager import moe.nea.firmament.util.FirmFormatters import moe.nea.firmament.util.MC import moe.nea.firmament.util.SBData import moe.nea.firmament.util.ScreenUtil import moe.nea.firmament.util.SkyblockId import moe.nea.firmament.util.accessors.messages import moe.nea.firmament.util.collections.InstanceList import moe.nea.firmament.util.collections.WeakCache import moe.nea.firmament.util.mc.SNbtFormatter import moe.nea.firmament.util.unformattedString fun firmamentCommand() = literal("firmament") { thenLiteral("config") { thenExecute { AllConfigsGui.showAllGuis() } thenLiteral("toggle") { thenArgument("config", string()) { config -> suggestsList { ManagedConfig.allManagedConfigs.getAll().asSequence().map { it.name }.asIterable() } thenArgument("property", string()) { property -> suggestsList { (ManagedConfig.allManagedConfigs.getAll().find { it.name == this[config] } ?: return@suggestsList listOf()) .allOptions.entries.asSequence().filter { it.value.handler is BooleanHandler } .map { it.key } .asIterable() } thenExecute { val config = this[config] val property = this[property] val configObj = ManagedConfig.allManagedConfigs.getAll().find { it.name == config } if (configObj == null) { source.sendFeedback( Text.stringifiedTranslatable( "firmament.command.toggle.no-config-found", config ) ) return@thenExecute } val propertyObj = configObj.allOptions[property] if (propertyObj == null) { source.sendFeedback( Text.stringifiedTranslatable("firmament.command.toggle.no-property-found", property) ) return@thenExecute } if (propertyObj.handler !is BooleanHandler) { source.sendFeedback( Text.stringifiedTranslatable("firmament.command.toggle.not-a-toggle", property) ) return@thenExecute } propertyObj as ManagedOption propertyObj.value = !propertyObj.value configObj.save() source.sendFeedback( Text.stringifiedTranslatable( "firmament.command.toggle.toggled", configObj.labelText, propertyObj.labelText, Text.translatable("firmament.toggle.${propertyObj.value}") ) ) } } } } } thenLiteral("buttons") { thenExecute { InventoryButtons.openEditor() } } thenLiteral("sendcoords") { thenExecute { val p = MC.player ?: return@thenExecute MC.sendServerChat("x: ${p.blockX}, y: ${p.blockY}, z: ${p.blockZ}") } thenArgument("rest", RestArgumentType) { rest -> thenExecute { val p = MC.player ?: return@thenExecute MC.sendServerChat("x: ${p.blockX}, y: ${p.blockY}, z: ${p.blockZ} ${this[rest]}") } } } thenLiteral("storageoverview") { thenExecute { ScreenUtil.setScreenLater(StorageOverviewScreen()) MC.player?.networkHandler?.sendChatCommand("storage") } } thenLiteral("storage") { thenExecute { ScreenUtil.setScreenLater(StorageOverlayScreen()) MC.player?.networkHandler?.sendChatCommand("storage") } } thenLiteral("repo") { thenLiteral("reload") { thenLiteral("fetch") { thenExecute { source.sendFeedback(Text.translatable("firmament.repo.reload.network")) // TODO better reporting RepoManager.launchAsyncUpdate() } } thenExecute { source.sendFeedback(Text.translatable("firmament.repo.reload.disk")) RepoManager.reload() } } } thenLiteral("price") { thenArgument("item", string()) { item -> suggestsList { RepoManager.neuRepo.items.items.keys } thenExecute { val itemName = SkyblockId(get(item)) source.sendFeedback(Text.stringifiedTranslatable("firmament.price", itemName.neuItem)) val bazaarData = HypixelStaticData.bazaarData[itemName] if (bazaarData != null) { source.sendFeedback(Text.translatable("firmament.price.bazaar")) source.sendFeedback( Text.stringifiedTranslatable("firmament.price.bazaar.productid", bazaarData.productId.bazaarId) ) source.sendFeedback( Text.stringifiedTranslatable( "firmament.price.bazaar.buy.price", FirmFormatters.formatCommas(bazaarData.quickStatus.buyPrice, 1) ) ) source.sendFeedback( Text.stringifiedTranslatable( "firmament.price.bazaar.buy.order", bazaarData.quickStatus.buyOrders ) ) source.sendFeedback( Text.stringifiedTranslatable( "firmament.price.bazaar.sell.price", FirmFormatters.formatCommas(bazaarData.quickStatus.sellPrice, 1) ) ) source.sendFeedback( Text.stringifiedTranslatable( "firmament.price.bazaar.sell.order", bazaarData.quickStatus.sellOrders ) ) } val lowestBin = HypixelStaticData.lowestBin[itemName] if (lowestBin != null) { source.sendFeedback( Text.stringifiedTranslatable( "firmament.price.lowestbin", FirmFormatters.formatCommas(lowestBin, 1) ) ) } } } } thenLiteral("dev") { thenLiteral("simulate") { thenArgument("message", RestArgumentType) { message -> thenExecute { MC.instance.messageHandler.onGameMessage(Text.literal(get(message)), false) } } } thenLiteral("debuglog") { thenLiteral("toggle") { thenArgument("tag", string()) { tag -> suggestsList { DebugLogger.allInstances.getAll().map { it.tag } + DebugLogger.EnabledLogs.data } thenExecute { val tagText = this[tag] val enabled = DebugLogger.EnabledLogs.data if (tagText in enabled) { enabled.remove(tagText) source.sendFeedback(Text.literal("Disabled $tagText debug logging")) } else { enabled.add(tagText) source.sendFeedback(Text.literal("Enabled $tagText debug logging")) } } } } } thenLiteral("dumpchat") { thenExecute { MC.inGameHud.chatHud.messages.forEach { val nbt = TextCodecs.CODEC.encodeStart(NbtOps.INSTANCE, it.content).orThrow println(nbt) } } thenArgument("search", string()) { search -> thenExecute { MC.inGameHud.chatHud.messages .filter { this[search] in it.content.unformattedString } .forEach { val nbt = TextCodecs.CODEC.encodeStart(NbtOps.INSTANCE, it.content).orThrow println(SNbtFormatter.prettify(nbt)) } } } } thenLiteral("sbdata") { thenExecute { source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.profile", SBData.profileId)) val locrawInfo = SBData.locraw if (locrawInfo == null) { source.sendFeedback(Text.translatable("firmament.sbinfo.nolocraw")) } else { source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.server", locrawInfo.server)) source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.gametype", locrawInfo.gametype)) source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.mode", locrawInfo.mode)) source.sendFeedback(Text.stringifiedTranslatable("firmament.sbinfo.map", locrawInfo.map)) } } } thenLiteral("copyEntities") { thenExecute { val player = MC.player ?: return@thenExecute player.world.getOtherEntities(player, player.boundingBox.expand(12.0)) .forEach(PowerUserTools::showEntity) } } thenLiteral("callUrsa") { thenArgument("path", string()) { path -> thenExecute { source.sendFeedback(Text.translatable("firmament.ursa.debugrequest.start")) val text = UrsaManager.request(this[path].split("/")).bodyAsText() source.sendFeedback(Text.stringifiedTranslatable("firmament.ursa.debugrequest.result", text)) } } } thenLiteral("events") { thenExecute { source.sendFeedback(Text.translatable("firmament.event.start")) FirmamentEventBus.allEventBuses.forEach { eventBus -> source.sendFeedback(Text.translatable( "firmament.event.bustype", eventBus.eventType.typeName.removePrefix("moe.nea.firmament"))) eventBus.handlers.forEach { handler -> source.sendFeedback(Text.translatable( "firmament.event.handler", handler.label)) } } } } thenLiteral("caches") { thenExecute { source.sendFeedback(Text.literal("Caches:")) WeakCache.allInstances.getAll().forEach { source.sendFeedback(Text.literal(" - ${it.name}: ${it.size}")) } source.sendFeedback(Text.translatable("Instance lists:")) InstanceList.allInstances.getAll().forEach { source.sendFeedback(Text.literal(" - ${it.name}: ${it.size}")) } } } thenLiteral("mixins") { thenExecute { source.sendFeedback(Text.translatable("firmament.mixins.start")) MixinPlugin.appliedMixins .map { it.removePrefix(MixinPlugin.mixinPackage) } .forEach { source.sendFeedback(Text.literal(" - ").withColor(0xD020F0) .append(Text.literal(it).withColor(0xF6BA20))) } } } } CommandEvent.SubCommand.publish(CommandEvent.SubCommand(this@literal)) } fun registerFirmamentCommand(dispatcher: CommandDispatcher) { val firmament = dispatcher.register(firmamentCommand()) dispatcher.register(literal("firm") { redirect(firmament) }) }