Add tab completion to /warp
This commit is contained in:
@@ -15,7 +15,7 @@ modmenu = "8.0.0"
|
|||||||
ktor = "2.3.0"
|
ktor = "2.3.0"
|
||||||
dbus_java = "4.2.1"
|
dbus_java = "4.2.1"
|
||||||
architectury = "10.0.7"
|
architectury = "10.0.7"
|
||||||
neurepoparser = "1.3.1"
|
neurepoparser = "1.4.0"
|
||||||
qolify = "1.3.0-1.20.2"
|
qolify = "1.3.0-1.20.2"
|
||||||
citresewn = "1.1.3+1.20"
|
citresewn = "1.1.3+1.20"
|
||||||
hotswap_agent = "1.4.2-SNAPSHOT"
|
hotswap_agent = "1.4.2-SNAPSHOT"
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
package moe.nea.firmament.mixins;
|
package moe.nea.firmament.mixins;
|
||||||
|
|
||||||
|
import com.llamalad7.mixinextras.injector.ModifyExpressionValue;
|
||||||
|
import com.mojang.brigadier.CommandDispatcher;
|
||||||
|
import moe.nea.firmament.events.MaskCommands;
|
||||||
import moe.nea.firmament.events.ParticleSpawnEvent;
|
import moe.nea.firmament.events.ParticleSpawnEvent;
|
||||||
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
import net.minecraft.client.network.ClientPlayNetworkHandler;
|
||||||
import net.minecraft.network.packet.s2c.play.ParticleS2CPacket;
|
import net.minecraft.network.packet.s2c.play.ParticleS2CPacket;
|
||||||
@@ -16,7 +19,15 @@ import org.spongepowered.asm.mixin.injection.Inject;
|
|||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
|
||||||
@Mixin(ClientPlayNetworkHandler.class)
|
@Mixin(ClientPlayNetworkHandler.class)
|
||||||
public class MixinClientPacketHandler {
|
public abstract class MixinClientPacketHandler {
|
||||||
|
|
||||||
|
|
||||||
|
@ModifyExpressionValue(method = "onCommandTree", at = @At(value = "NEW", target = "(Lcom/mojang/brigadier/tree/RootCommandNode;)Lcom/mojang/brigadier/CommandDispatcher;"))
|
||||||
|
public CommandDispatcher onOnCommandTree(CommandDispatcher dispatcher) {
|
||||||
|
MaskCommands.Companion.publish(new MaskCommands(dispatcher));
|
||||||
|
return dispatcher;
|
||||||
|
}
|
||||||
|
|
||||||
@Inject(method = "onParticle", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkThreadUtils;forceMainThread(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;Lnet/minecraft/util/thread/ThreadExecutor;)V", shift = At.Shift.AFTER), cancellable = true)
|
@Inject(method = "onParticle", at = @At(value = "INVOKE", target = "Lnet/minecraft/network/NetworkThreadUtils;forceMainThread(Lnet/minecraft/network/packet/Packet;Lnet/minecraft/network/listener/PacketListener;Lnet/minecraft/util/thread/ThreadExecutor;)V", shift = At.Shift.AFTER), cancellable = true)
|
||||||
public void onParticleSpawn(ParticleS2CPacket packet, CallbackInfo ci) {
|
public void onParticleSpawn(ParticleS2CPacket packet, CallbackInfo ci) {
|
||||||
var event = new ParticleSpawnEvent(
|
var event = new ParticleSpawnEvent(
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ import moe.nea.firmament.events.registration.registerFirmamentChatEvents
|
|||||||
import moe.nea.firmament.features.FeatureManager
|
import moe.nea.firmament.features.FeatureManager
|
||||||
import moe.nea.firmament.repo.HypixelStaticData
|
import moe.nea.firmament.repo.HypixelStaticData
|
||||||
import moe.nea.firmament.repo.RepoManager
|
import moe.nea.firmament.repo.RepoManager
|
||||||
|
import moe.nea.firmament.util.MC
|
||||||
import moe.nea.firmament.util.SBData
|
import moe.nea.firmament.util.SBData
|
||||||
import moe.nea.firmament.util.data.IDataHolder
|
import moe.nea.firmament.util.data.IDataHolder
|
||||||
|
|
||||||
@@ -107,7 +108,7 @@ object Firmament {
|
|||||||
ctx: CommandRegistryAccess
|
ctx: CommandRegistryAccess
|
||||||
) {
|
) {
|
||||||
registerFirmamentCommand(dispatcher)
|
registerFirmamentCommand(dispatcher)
|
||||||
CommandEvent.publish(CommandEvent(dispatcher, ctx))
|
CommandEvent.publish(CommandEvent(dispatcher, ctx, MC.networkHandler?.commandDispatcher))
|
||||||
}
|
}
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
|
|||||||
@@ -16,9 +16,15 @@ import moe.nea.firmament.commands.literal
|
|||||||
data class CommandEvent(
|
data class CommandEvent(
|
||||||
val dispatcher: CommandDispatcher<DefaultSource>,
|
val dispatcher: CommandDispatcher<DefaultSource>,
|
||||||
val ctx: CommandRegistryAccess,
|
val ctx: CommandRegistryAccess,
|
||||||
|
val serverCommands: CommandDispatcher<*>?,
|
||||||
) : FirmamentEvent() {
|
) : FirmamentEvent() {
|
||||||
companion object : FirmamentEventBus<CommandEvent>()
|
companion object : FirmamentEventBus<CommandEvent>()
|
||||||
|
|
||||||
|
fun deleteCommand(name: String) {
|
||||||
|
dispatcher.root.children.removeIf { it.name.equals(name, ignoreCase = false) }
|
||||||
|
serverCommands?.root?.children?.removeIf { it.name.equals(name, ignoreCase = false) }
|
||||||
|
}
|
||||||
|
|
||||||
fun register(
|
fun register(
|
||||||
name: String,
|
name: String,
|
||||||
block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit
|
block: CaseInsensitiveLiteralCommandNode.Builder<DefaultSource>.() -> Unit
|
||||||
|
|||||||
17
src/main/kotlin/moe/nea/firmament/events/MaskCommands.kt
Normal file
17
src/main/kotlin/moe/nea/firmament/events/MaskCommands.kt
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.events
|
||||||
|
|
||||||
|
import com.mojang.brigadier.CommandDispatcher
|
||||||
|
|
||||||
|
data class MaskCommands(val dispatcher: CommandDispatcher<*>) : FirmamentEvent() {
|
||||||
|
companion object : FirmamentEventBus<MaskCommands>()
|
||||||
|
|
||||||
|
fun mask(name: String) {
|
||||||
|
dispatcher.root.children.removeIf { it.name.equals(name, ignoreCase = true) }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ package moe.nea.firmament.features
|
|||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
import kotlinx.serialization.serializer
|
import kotlinx.serialization.serializer
|
||||||
import moe.nea.firmament.Firmament
|
import moe.nea.firmament.Firmament
|
||||||
|
import moe.nea.firmament.features.chat.AutoCompletions
|
||||||
import moe.nea.firmament.features.chat.ChatLinks
|
import moe.nea.firmament.features.chat.ChatLinks
|
||||||
import moe.nea.firmament.features.chat.QuickCommands
|
import moe.nea.firmament.features.chat.QuickCommands
|
||||||
import moe.nea.firmament.features.debug.DebugView
|
import moe.nea.firmament.features.debug.DebugView
|
||||||
@@ -48,6 +49,7 @@ object FeatureManager : DataHolder<FeatureManager.Config>(serializer(), "feature
|
|||||||
if (hasAutoloaded) return
|
if (hasAutoloaded) return
|
||||||
loadFeature(MinorTrolling)
|
loadFeature(MinorTrolling)
|
||||||
loadFeature(FairySouls)
|
loadFeature(FairySouls)
|
||||||
|
loadFeature(AutoCompletions)
|
||||||
// TODO: loadFeature(FishingWarning)
|
// TODO: loadFeature(FishingWarning)
|
||||||
loadFeature(SlotLocking)
|
loadFeature(SlotLocking)
|
||||||
loadFeature(StorageOverlay)
|
loadFeature(StorageOverlay)
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Linnea Gräf <nea@nea.moe>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*/
|
||||||
|
|
||||||
|
package moe.nea.firmament.features.chat
|
||||||
|
|
||||||
|
import com.mojang.brigadier.arguments.StringArgumentType.string
|
||||||
|
import moe.nea.firmament.commands.get
|
||||||
|
import moe.nea.firmament.commands.suggestsList
|
||||||
|
import moe.nea.firmament.commands.thenArgument
|
||||||
|
import moe.nea.firmament.commands.thenExecute
|
||||||
|
import moe.nea.firmament.events.CommandEvent
|
||||||
|
import moe.nea.firmament.events.MaskCommands
|
||||||
|
import moe.nea.firmament.features.FirmamentFeature
|
||||||
|
import moe.nea.firmament.gui.config.ManagedConfig
|
||||||
|
import moe.nea.firmament.repo.RepoManager
|
||||||
|
import moe.nea.firmament.util.MC
|
||||||
|
|
||||||
|
object AutoCompletions : FirmamentFeature {
|
||||||
|
|
||||||
|
object TConfig : ManagedConfig(identifier) {
|
||||||
|
val provideWarpTabCompletion by toggle("warp-complete") { true }
|
||||||
|
val replaceWarpIsByWarpIsland by toggle("warp-is") { true }
|
||||||
|
}
|
||||||
|
|
||||||
|
override val config: ManagedConfig?
|
||||||
|
get() = TConfig
|
||||||
|
override val identifier: String
|
||||||
|
get() = "auto-completions"
|
||||||
|
|
||||||
|
override fun onLoad() {
|
||||||
|
MaskCommands.subscribe {
|
||||||
|
if (TConfig.provideWarpTabCompletion) {
|
||||||
|
it.mask("warp")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CommandEvent.subscribe {
|
||||||
|
if (TConfig.provideWarpTabCompletion) {
|
||||||
|
it.deleteCommand("warp")
|
||||||
|
it.register("warp") {
|
||||||
|
thenArgument("to", string()) { toArg ->
|
||||||
|
suggestsList {
|
||||||
|
RepoManager.neuRepo.constants?.islands?.warps?.flatMap { listOf(it.warp) + it.aliases } ?: listOf()
|
||||||
|
}
|
||||||
|
thenExecute {
|
||||||
|
val warpName = get(toArg)
|
||||||
|
if (warpName == "is" && TConfig.replaceWarpIsByWarpIsland) {
|
||||||
|
MC.sendServerCommand("warp island")
|
||||||
|
} else {
|
||||||
|
MC.sendServerCommand("warp ${warpName}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,17 +31,17 @@ object RepoDownloadManager {
|
|||||||
val repoMetadataLocation = Firmament.DATA_DIR.resolve("loaded-repo-sha.txt")
|
val repoMetadataLocation = Firmament.DATA_DIR.resolve("loaded-repo-sha.txt")
|
||||||
|
|
||||||
private fun loadSavedVersionHash(): String? =
|
private fun loadSavedVersionHash(): String? =
|
||||||
if (repoSavedLocation.exists()) {
|
if (repoSavedLocation.exists()) {
|
||||||
if (repoMetadataLocation.exists()) {
|
if (repoMetadataLocation.exists()) {
|
||||||
try {
|
try {
|
||||||
repoMetadataLocation.readText().trim()
|
repoMetadataLocation.readText().trim()
|
||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
null
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
} else null
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
} else null
|
||||||
|
|
||||||
private fun saveVersionHash(versionHash: String) {
|
private fun saveVersionHash(versionHash: String) {
|
||||||
latestSavedVersionHash = versionHash
|
latestSavedVersionHash = versionHash
|
||||||
@@ -56,7 +56,7 @@ object RepoDownloadManager {
|
|||||||
|
|
||||||
private suspend fun requestLatestGithubSha(): String? {
|
private suspend fun requestLatestGithubSha(): String? {
|
||||||
val response =
|
val response =
|
||||||
Firmament.httpClient.get("https://api.github.com/repos/${RepoManager.Config.username}/${RepoManager.Config.reponame}/commits/${RepoManager.Config.branch}")
|
Firmament.httpClient.get("https://api.github.com/repos/${RepoManager.Config.username}/${RepoManager.Config.reponame}/commits/${RepoManager.Config.branch}")
|
||||||
if (response.status.value != 200) {
|
if (response.status.value != 200) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,8 @@ object RepoDownloadManager {
|
|||||||
}
|
}
|
||||||
val currentSha = loadSavedVersionHash()
|
val currentSha = loadSavedVersionHash()
|
||||||
if (latestSha != currentSha || force) {
|
if (latestSha != currentSha || force) {
|
||||||
val requestUrl = "https://github.com/${RepoManager.Config.username}/${RepoManager.Config.reponame}/archive/$latestSha.zip"
|
val requestUrl =
|
||||||
|
"https://github.com/${RepoManager.Config.username}/${RepoManager.Config.reponame}/archive/$latestSha.zip"
|
||||||
logger.info("Planning to upgrade repository from $currentSha to $latestSha from $requestUrl")
|
logger.info("Planning to upgrade repository from $currentSha to $latestSha from $requestUrl")
|
||||||
val zipFile = downloadGithubArchive(requestUrl)
|
val zipFile = downloadGithubArchive(requestUrl)
|
||||||
logger.info("Download repository zip file to $zipFile. Deleting old repository")
|
logger.info("Download repository zip file to $zipFile. Deleting old repository")
|
||||||
@@ -106,17 +107,15 @@ object RepoDownloadManager {
|
|||||||
val entry = cis.nextEntry ?: break
|
val entry = cis.nextEntry ?: break
|
||||||
if (entry.isDirectory) continue
|
if (entry.isDirectory) continue
|
||||||
val extractedLocation =
|
val extractedLocation =
|
||||||
repoSavedLocation.resolve(
|
repoSavedLocation.resolve(
|
||||||
entry.name.substringAfter('/', missingDelimiterValue = "")
|
entry.name.substringAfter('/', missingDelimiterValue = "")
|
||||||
)
|
)
|
||||||
if (repoSavedLocation !in extractedLocation.iterate { it.parent }) {
|
if (repoSavedLocation !in extractedLocation.iterate { it.parent }) {
|
||||||
logger.error("Firmament detected an invalid zip file. This is a potential security risk, please report this in the Firmament discord.")
|
logger.error("Firmament detected an invalid zip file. This is a potential security risk, please report this in the Firmament discord.")
|
||||||
throw RuntimeException("Firmament detected an invalid zip file. This is a potential security risk, please report this in the Firmament discord.")
|
throw RuntimeException("Firmament detected an invalid zip file. This is a potential security risk, please report this in the Firmament discord.")
|
||||||
}
|
}
|
||||||
extractedLocation.parent.createDirectories()
|
extractedLocation.parent.createDirectories()
|
||||||
cis.use {
|
extractedLocation.outputStream().use { cis.copyTo(it) }
|
||||||
extractedLocation.outputStream().use { cis.copyTo(it) }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,8 +99,13 @@ object RepoManager {
|
|||||||
Firmament.coroutineScope.launch {
|
Firmament.coroutineScope.launch {
|
||||||
progressBar.reportProgress("Downloading", 0, null)
|
progressBar.reportProgress("Downloading", 0, null)
|
||||||
CottonHud.add(progressBar)
|
CottonHud.add(progressBar)
|
||||||
RepoDownloadManager.downloadUpdate(force)
|
try {
|
||||||
progressBar.reportProgress("Download complete", 1, 1)
|
RepoDownloadManager.downloadUpdate(force)
|
||||||
|
progressBar.reportProgress("Download complete", 1, 1)
|
||||||
|
} finally {
|
||||||
|
CottonHud.remove(progressBar)
|
||||||
|
|
||||||
|
}
|
||||||
reload()
|
reload()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,16 @@
|
|||||||
package moe.nea.firmament.util
|
package moe.nea.firmament.util
|
||||||
|
|
||||||
import io.github.moulberry.repo.data.Coordinate
|
import io.github.moulberry.repo.data.Coordinate
|
||||||
|
import java.time.Instant
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
import net.minecraft.client.MinecraftClient
|
import net.minecraft.client.MinecraftClient
|
||||||
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
import net.minecraft.client.gui.screen.ingame.HandledScreen
|
||||||
|
import net.minecraft.network.message.ArgumentSignatureDataMap
|
||||||
|
import net.minecraft.network.message.LastSeenMessagesCollector.LastSeenMessages
|
||||||
|
import net.minecraft.network.packet.c2s.play.CommandExecutionC2SPacket
|
||||||
import net.minecraft.text.Text
|
import net.minecraft.text.Text
|
||||||
import net.minecraft.util.math.BlockPos
|
import net.minecraft.util.math.BlockPos
|
||||||
import moe.nea.firmament.events.TickEvent
|
import moe.nea.firmament.events.TickEvent
|
||||||
import moe.nea.firmament.mixins.accessor.AccessorHandledScreen
|
|
||||||
|
|
||||||
object MC {
|
object MC {
|
||||||
|
|
||||||
@@ -34,10 +37,25 @@ object MC {
|
|||||||
messageQueue.add(text)
|
messageQueue.add(text)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun sendServerCommand(command: String) {
|
||||||
|
val nh = player?.networkHandler ?: return
|
||||||
|
val lastSeenMessages: LastSeenMessages = nh.lastSeenMessagesCollector.collect()
|
||||||
|
nh.sendPacket(
|
||||||
|
CommandExecutionC2SPacket(
|
||||||
|
command,
|
||||||
|
Instant.now(),
|
||||||
|
0L,
|
||||||
|
ArgumentSignatureDataMap.EMPTY,
|
||||||
|
lastSeenMessages.update()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun sendCommand(command: String) {
|
fun sendCommand(command: String) {
|
||||||
player?.networkHandler?.sendCommand(command)
|
player?.networkHandler?.sendCommand(command)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline val networkHandler get() = player?.networkHandler
|
||||||
inline val instance get() = MinecraftClient.getInstance()
|
inline val instance get() = MinecraftClient.getInstance()
|
||||||
inline val keyboard get() = MinecraftClient.getInstance().keyboard
|
inline val keyboard get() = MinecraftClient.getInstance().keyboard
|
||||||
inline val textureManager get() = MinecraftClient.getInstance().textureManager
|
inline val textureManager get() = MinecraftClient.getInstance().textureManager
|
||||||
|
|||||||
@@ -27,6 +27,9 @@
|
|||||||
"firmament.repo.reload.disk": "Reloading repository from disk. This may lag a bit.",
|
"firmament.repo.reload.disk": "Reloading repository from disk. This may lag a bit.",
|
||||||
"firmament.repo.cache": "Recaching items",
|
"firmament.repo.cache": "Recaching items",
|
||||||
"firmament.repo.brokenitem": "Failed to render item: %s",
|
"firmament.repo.brokenitem": "Failed to render item: %s",
|
||||||
|
"firmament.config.auto-completions": "Hypixel Command Improvements",
|
||||||
|
"firmament.config.auto-completions.warp-complete": "Auto Complete /warp",
|
||||||
|
"firmament.config.auto-completions.warp-is": "Redirect /warp is to /warp island",
|
||||||
"firmanent.config.edit": "Edit",
|
"firmanent.config.edit": "Edit",
|
||||||
"firmament.config.repo": "Firmament Repo Settings",
|
"firmament.config.repo": "Firmament Repo Settings",
|
||||||
"firmament.config.repo.autoUpdate": "Auto Update",
|
"firmament.config.repo.autoUpdate": "Auto Update",
|
||||||
|
|||||||
@@ -5,3 +5,4 @@ accessible class net/minecraft/client/font/TextRenderer$Drawer
|
|||||||
accessible class net/minecraft/client/render/model/ModelLoader$BakerImpl
|
accessible class net/minecraft/client/render/model/ModelLoader$BakerImpl
|
||||||
accessible method net/minecraft/client/render/model/ModelLoader$BakerImpl <init> (Lnet/minecraft/client/render/model/ModelLoader;Ljava/util/function/BiFunction;Lnet/minecraft/util/Identifier;)V
|
accessible method net/minecraft/client/render/model/ModelLoader$BakerImpl <init> (Lnet/minecraft/client/render/model/ModelLoader;Ljava/util/function/BiFunction;Lnet/minecraft/util/Identifier;)V
|
||||||
accessible field net/minecraft/client/texture/PlayerSkinProvider TEXTURES Ljava/lang/String;
|
accessible field net/minecraft/client/texture/PlayerSkinProvider TEXTURES Ljava/lang/String;
|
||||||
|
accessible field net/minecraft/client/network/ClientPlayNetworkHandler lastSeenMessagesCollector Lnet/minecraft/network/message/LastSeenMessagesCollector;
|
||||||
|
|||||||
Reference in New Issue
Block a user