diff options
Diffstat (limited to 'src/main/kotlin/com')
7 files changed, 217 insertions, 10 deletions
diff --git a/src/main/kotlin/com/ambientaddons/AmbientAddons.kt b/src/main/kotlin/com/ambientaddons/AmbientAddons.kt index 7b481ce..9f63b13 100644 --- a/src/main/kotlin/com/ambientaddons/AmbientAddons.kt +++ b/src/main/kotlin/com/ambientaddons/AmbientAddons.kt @@ -1,7 +1,9 @@ import com.ambientaddons.commands.AmbientCommand +import com.ambientaddons.commands.PingCommand import com.ambientaddons.config.Config import com.ambientaddons.config.PersistentData import com.ambientaddons.features.display.CatOverlay +import com.ambientaddons.features.display.PingOverlay import com.ambientaddons.features.display.WitherShieldOverlay import com.ambientaddons.features.dungeon.* import com.ambientaddons.features.dungeon.terminals.MelodyHelper @@ -47,7 +49,10 @@ class AmbientAddons { @Mod.EventHandler fun onInit(event: FMLInitializationEvent) { - ClientCommandHandler.instance.registerCommand(AmbientCommand()) + listOf( + AmbientCommand(), + PingCommand() + ).forEach(ClientCommandHandler.instance::registerCommand) listOf( this, SBLocation, @@ -66,11 +71,13 @@ class AmbientAddons { DungeonHighlights, Trapper, CrimsonFishing, - CatOverlay + CatOverlay, + PingOverlay ).forEach(MinecraftForge.EVENT_BUS::register) keyBinds.values.forEach(ClientRegistry::registerKeyBinding) guiElements = listOf( - CatOverlay.element + CatOverlay.element, + PingOverlay.element ) } diff --git a/src/main/kotlin/com/ambientaddons/commands/PingCommand.kt b/src/main/kotlin/com/ambientaddons/commands/PingCommand.kt new file mode 100644 index 0000000..a3d68cb --- /dev/null +++ b/src/main/kotlin/com/ambientaddons/commands/PingCommand.kt @@ -0,0 +1,23 @@ +package com.ambientaddons.commands + +import com.ambientaddons.config.Config +import com.ambientaddons.features.display.PingOverlay +import com.ambientaddons.utils.Extensions.withModPrefix +import com.ambientaddons.utils.SBLocation +import gg.essential.universal.UChat +import net.minecraft.command.CommandBase +import net.minecraft.command.ICommandSender + +class PingCommand : CommandBase() { + override fun getCommandName() = "ping" + + override fun getCommandAliases() = listOf("amping") + + override fun getCommandUsage(sender: ICommandSender?) = "/$commandName" + + override fun getRequiredPermissionLevel() = 0 + + override fun processCommand(sender: ICommandSender?, args: Array<String>) { + PingOverlay.sendPing(true) + } +}
\ No newline at end of file diff --git a/src/main/kotlin/com/ambientaddons/config/Config.kt b/src/main/kotlin/com/ambientaddons/config/Config.kt index 4e4c39f..db2c327 100644 --- a/src/main/kotlin/com/ambientaddons/config/Config.kt +++ b/src/main/kotlin/com/ambientaddons/config/Config.kt @@ -37,6 +37,9 @@ object Config : Vigilant( var cat = true var witherShieldDisplay = 0 + var shouldPing = 0 + var pingDisplay = 0 + var terminatorCps = 0 var cancelInteractions = false var closeSecretChests = false @@ -191,6 +194,21 @@ object Config : Vigilant( description = "Displays remaining wither shield duration", options = listOf("Off", "Default", "Shadow", "Outline") ) + subcategory("Ping and TPS") { + selector( + ::shouldPing, + name = "Enable ping", + description = "Enables ping in command and display. This requires sending packets to the server.", + options = listOf("Off", "In Skyblock", "On Hypixel", "Always") + ) + selector( + ::pingDisplay, + name = "Ping and TPS display", + description = "Displays current ping and TPS. Ping requires ", + options = listOf("Off", "Default", "Shadow", "Outline") + ) + } + } category("Dungeon") { diff --git a/src/main/kotlin/com/ambientaddons/features/display/PingOverlay.kt b/src/main/kotlin/com/ambientaddons/features/display/PingOverlay.kt new file mode 100644 index 0000000..d8689be --- /dev/null +++ b/src/main/kotlin/com/ambientaddons/features/display/PingOverlay.kt @@ -0,0 +1,155 @@ +package com.ambientaddons.features.display + +import AmbientAddons.Companion.config +import AmbientAddons.Companion.mc +import com.ambientaddons.events.ReceivePacketEvent +import com.ambientaddons.gui.GuiElement +import com.ambientaddons.utils.Alignment +import com.ambientaddons.utils.Extensions.renderWidth +import com.ambientaddons.utils.Extensions.withModPrefix +import com.ambientaddons.utils.SBLocation +import com.ambientaddons.utils.dungeon.TextStyle +import com.ambientaddons.utils.render.OverlayUtils +import gg.essential.universal.UChat +import net.minecraft.client.renderer.GlStateManager +import net.minecraft.network.play.client.C16PacketClientStatus +import net.minecraft.network.play.server.S01PacketJoinGame +import net.minecraft.network.play.server.S03PacketTimeUpdate +import net.minecraft.network.play.server.S37PacketStatistics +import net.minecraftforge.client.event.RenderGameOverlayEvent +import net.minecraftforge.event.world.WorldEvent +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent +import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent +import kotlin.math.max + +// Modified from SkytilsMod/Skytils, under AGPL 3.0 +object PingOverlay { + val element = GuiElement("ping", 55, 20) + private val alpha = 1 / 3.0 + private var averageTps: Double? = null + private var tpsCount = 0 + private var lastTpsSample: Long? = null + + private var averagePing: Double? = null + private var pingCount = 0 + private var pingStartTime: Long? = null + + private var ticks = 0 + private var isPinging = false + private var chatNextPing = false + + @SubscribeEvent + fun onPacketReceived(event: ReceivePacketEvent) { + if (event.packet is S03PacketTimeUpdate) { + val currentTime = System.currentTimeMillis() + lastTpsSample?.let { lastTime -> + val time = currentTime - lastTime + val instantTps = (20000.0 / time).coerceIn(0.0, 20.0) + tpsCount++ + averageTps = instantTps * alpha + (averageTps ?: instantTps) * (1 - alpha) + } + lastTpsSample = currentTime + } else if (config.shouldPing != 0 && event.packet is S37PacketStatistics) { + isPinging = false + pingStartTime?.let { startTime -> + val instantPing = (System.nanoTime() - startTime) / 1e6 + pingCount++ + averagePing = instantPing * alpha + (averagePing ?: instantPing) * (1 - alpha) + } + if (chatNextPing) { + printPing() + chatNextPing = false + } + } else if (event.packet is S01PacketJoinGame) reset() + } + + @SubscribeEvent + fun onWorldLoad(event: WorldEvent.Load) { + reset() + } + + private fun reset() { + isPinging = false + tpsCount = 0 + averageTps = null + pingCount = 0 + averagePing = null + } + + private fun printPing() { + val pingValue = averagePing?.let { "${colorizePing(it) }%.1f".format(it) } ?: "§e?" + val tpsValue = averageTps?.let { "${colorizeTps(it) }%.1f".format(it) } ?: "§e?" + if (shouldPing()) { + UChat.chat("$pingValue §7ms ($tpsValue §7tps)".withModPrefix()) + } else { + UChat.chat("$tpsValue §7tps".withModPrefix()) + } + } + + fun sendPing(isFromCommand: Boolean) { + if (isFromCommand) chatNextPing = true + if (!isPinging) { + isPinging = true + mc.thePlayer.sendQueue.networkManager.sendPacket(C16PacketClientStatus(C16PacketClientStatus.EnumState.REQUEST_STATS), + { + pingStartTime = System.nanoTime() + } + ) + } else if (isFromCommand && !shouldPing()) { + UChat.chat("§cAlready pinging!".withModPrefix()) + } + } + + @SubscribeEvent + fun onTick(event: ClientTickEvent) { + if (!shouldPing() || event.phase != TickEvent.Phase.START) return + if (ticks % 40 == 0) { + sendPing(false) + } + ticks++ + } + + private fun colorizeTps(tps: Double) = when { + (tps > 19) -> "§a" + (tps > 18) -> "§2" + (tps > 17) -> "§e" + (tps > 15) -> "§6" + else -> "§c" + } + + private fun colorizePing(ping: Double) = when { + (ping < 50) -> "§a" + (ping < 100) -> "§2" + (ping < 150) -> "§e" + (ping < 250) -> "§6" + else -> "§c" + } + + private fun shouldPing(): Boolean = + mc.theWorld != null && (config.shouldPing == 3 || (config.shouldPing == 2 && SBLocation.onHypixel) || (config.shouldPing == 1 && SBLocation.inSkyblock)) + + @SubscribeEvent + fun onRenderOverlay(event: RenderGameOverlayEvent) { + if (config.pingDisplay == 0 || event.type != RenderGameOverlayEvent.ElementType.TEXT) return + val textStyle = TextStyle.fromInt(config.pingDisplay - 1) ?: return + GlStateManager.pushMatrix() + GlStateManager.translate(element.position.x, element.position.y, 500.0) + GlStateManager.scale(element.position.scale, element.position.scale, 1.0) + val tpsValue = averageTps?.let { "${colorizeTps(it) }%.1f".format(it) } ?: "§e?" + if (shouldPing()) { + val pingValue = averagePing?.let { "${colorizePing(it)}%.1f".format(it) } ?: "§e?" + val valueWidth = max(pingValue.renderWidth(), tpsValue.renderWidth()) + OverlayUtils.drawString(0, 0, "§bPing:", textStyle, Alignment.Left) + OverlayUtils.drawString(0, 10, "§bTPS:", textStyle, Alignment.Left) + OverlayUtils.drawString(30 + valueWidth, 0, pingValue, textStyle, Alignment.Right) + OverlayUtils.drawString(30 + valueWidth, 10, tpsValue, textStyle, Alignment.Right) + } else { + OverlayUtils.drawString(0, 0, "§bTPS:", textStyle, Alignment.Left) + OverlayUtils.drawString(30 + tpsValue.renderWidth(), 0, tpsValue, textStyle, Alignment.Right) + } + GlStateManager.popMatrix() + } + + +} diff --git a/src/main/kotlin/com/ambientaddons/gui/GuiElement.kt b/src/main/kotlin/com/ambientaddons/gui/GuiElement.kt index c398464..7cb65e3 100644 --- a/src/main/kotlin/com/ambientaddons/gui/GuiElement.kt +++ b/src/main/kotlin/com/ambientaddons/gui/GuiElement.kt @@ -1,5 +1,6 @@ package com.ambientaddons.gui +import AmbientAddons.Companion.guiElements import AmbientAddons.Companion.persistentData import com.ambientaddons.utils.render.OverlayUtils import gg.essential.universal.UResolution @@ -33,8 +34,9 @@ class GuiElement(val name: String, private val width: Int, private val height: I val renderWidth = width * position.scale val renderHeight = height * position.scale GlStateManager.translate(position.x - padding * renderWidth, position.y - padding * renderWidth, 400.0) - val color = if (isInsideElement(mouseX, mouseY)) Color(255, 255, 255, 128) else Color(128, 128, 128, 128) - OverlayUtils.renderRect(0.0, 0.0, renderWidth * (1 + padding * 2), renderHeight * (1 + padding * 2), color) + val color = if (guiElements.find { it.isInsideElement(mouseX, mouseY) } == this) + Color(255, 255, 255, 128) else Color(128, 128, 128, 128) + OverlayUtils.renderRect(0.0, 0.0, renderWidth * (1 + padding * 2), renderHeight * (1 + padding * 2), color) GlStateManager.popMatrix() } diff --git a/src/main/kotlin/com/ambientaddons/gui/MoveGui.kt b/src/main/kotlin/com/ambientaddons/gui/MoveGui.kt index 33c96e7..61bb41b 100644 --- a/src/main/kotlin/com/ambientaddons/gui/MoveGui.kt +++ b/src/main/kotlin/com/ambientaddons/gui/MoveGui.kt @@ -11,6 +11,7 @@ import net.minecraft.client.renderer.GlStateManager import org.lwjgl.input.Mouse import org.lwjgl.opengl.Display import java.awt.Color +import kotlin.math.sign class MoveGui : GuiScreen() { private var currentElement: GuiElement? = null @@ -53,12 +54,12 @@ class MoveGui : GuiScreen() { override fun handleMouseInput() { super.handleMouseInput() val (mouseX, mouseY) = getMouseCoordinates() + val dScroll = (Mouse.getEventDWheel().sign * 0.1).takeIf { it != 0.0 } ?: return currentElement = guiElements.find { it.isInsideElement(mouseX, mouseY) }?.apply { clickOffsetX = mouseX - position.x clickOffsetY = mouseY - position.y - val scrollAmount = Mouse.getEventDWheel() val oldScale = position.scale - val newScale = (position.scale + scrollAmount / 7200.0).coerceAtLeast(0.1) + val newScale = (position.scale + dScroll).coerceAtLeast(0.1) position.x = mouseX + (newScale / oldScale) * (position.x - mouseX) position.y = mouseY + (newScale / oldScale) * (position.y - mouseY) position.scale = newScale diff --git a/src/main/kotlin/com/ambientaddons/utils/Extensions.kt b/src/main/kotlin/com/ambientaddons/utils/Extensions.kt index 3da5767..ef4bcf1 100644 --- a/src/main/kotlin/com/ambientaddons/utils/Extensions.kt +++ b/src/main/kotlin/com/ambientaddons/utils/Extensions.kt @@ -1,5 +1,6 @@ package com.ambientaddons.utils +import AmbientAddons.Companion.mc import com.ambientaddons.utils.Extensions.enchants import com.ambientaddons.utils.Extensions.extraAttributes import com.ambientaddons.utils.Extensions.skyblockID @@ -31,9 +32,9 @@ object Extensions { ?: "" } - fun String.withModPrefix(): String { - return "§9§lAmbient §7» §r${this}" - } + fun String.withModPrefix(): String = "§9§lAmbient §7» §r${this}" + + fun String.renderWidth(): Int = mc.fontRendererObj.getStringWidth(this) val GuiScreen.chest: ContainerChest? get() = (this as? GuiChest)?.inventorySlots as? ContainerChest |