diff options
Diffstat (limited to 'src/main/kotlin/com/ambientaddons/utils')
4 files changed, 230 insertions, 0 deletions
diff --git a/src/main/kotlin/com/ambientaddons/utils/DungeonFloor.kt b/src/main/kotlin/com/ambientaddons/utils/DungeonFloor.kt new file mode 100644 index 0000000..a64fed0 --- /dev/null +++ b/src/main/kotlin/com/ambientaddons/utils/DungeonFloor.kt @@ -0,0 +1,32 @@ +package com.ambientaddons.utils + +data class DungeonFloor( + val mode: Mode, + val floor: Int +) { + override fun toString(): String { + return when { + floor == 0 -> "E" + mode == Mode.Normal -> "F$floor" + else -> "M$floor" + } + } + + companion object { + fun String.toDungeonFloor(): DungeonFloor? { + if (this.isEmpty()) return null + if (this == "E") return DungeonFloor(Mode.Normal, 0) + val floorInt = this.last().digitToIntOrNull() ?: return null + if (floorInt !in 1..7) return null + return when (this.first()) { + 'F' -> DungeonFloor(Mode.Normal, floorInt) + 'M' -> DungeonFloor(Mode.Master, floorInt) + else -> null + } + } + } +} + +enum class Mode { Normal, Master } + + diff --git a/src/main/kotlin/com/ambientaddons/utils/Extensions.kt b/src/main/kotlin/com/ambientaddons/utils/Extensions.kt new file mode 100644 index 0000000..3da5767 --- /dev/null +++ b/src/main/kotlin/com/ambientaddons/utils/Extensions.kt @@ -0,0 +1,73 @@ +package com.ambientaddons.utils + +import com.ambientaddons.utils.Extensions.enchants +import com.ambientaddons.utils.Extensions.extraAttributes +import com.ambientaddons.utils.Extensions.skyblockID +import net.minecraft.client.gui.GuiScreen +import net.minecraft.client.gui.inventory.GuiChest +import net.minecraft.inventory.ContainerChest +import net.minecraft.inventory.IInventory +import net.minecraft.item.Item +import net.minecraft.item.ItemStack +import net.minecraft.nbt.NBTTagCompound +import net.minecraft.util.StringUtils + +object Extensions { + fun String.substringBetween(start: String, end: String): String { + return this + .substringAfter("(", "") + .substringBefore(")", "") + } + + fun String.stripControlCodes(): String { + return StringUtils.stripControlCodes(this) + } + + fun String.cleanSB(): String { + return StringUtils.stripControlCodes(this) + ?.toCharArray() + ?.filter { it.code in 21..126 } + ?.joinToString("") + ?: "" + } + + fun String.withModPrefix(): String { + return "§9§lAmbient §7» §r${this}" + } + + val GuiScreen.chest: ContainerChest? + get() = (this as? GuiChest)?.inventorySlots as? ContainerChest + + val IInventory.items: List<ItemStack?> + get() = (0 until this.sizeInventory).map { this.getStackInSlot(it) } + + + private val ItemStack.extraAttributes: NBTTagCompound? + get() { + if (!this.hasTagCompound()) return null + return this.getSubCompound("ExtraAttributes", false) ?: return null + } + + val ItemStack.skyblockID: String? + get() = this.extraAttributes?.let { + if (!it.hasKey("id", 8)) return null + return it.getString("id") + } + + val ItemStack.enchants: Map<String, Int>? + get() = this.extraAttributes?.let { extraAttributes -> + if (!extraAttributes.hasKey("enchantments", 10)) return null + val enchantments = extraAttributes.getCompoundTag("enchantments") + enchantments.keySet.associateWith { enchantments.getInteger(it) } + } + + val ItemStack.lore: List<String>? + get() { + if (!this.hasTagCompound()) return null + val displayTag = this.getSubCompound("display", false) ?: return null + if (!displayTag.hasKey("Lore", 9)) return null + val loreList = displayTag.getTagList("Lore", 8) + return (0 until loreList.tagCount()).map { loreList.getStringTagAt(it) } + } + +} diff --git a/src/main/kotlin/com/ambientaddons/utils/LocationUtils.kt b/src/main/kotlin/com/ambientaddons/utils/LocationUtils.kt new file mode 100644 index 0000000..d185a08 --- /dev/null +++ b/src/main/kotlin/com/ambientaddons/utils/LocationUtils.kt @@ -0,0 +1,87 @@ +package com.ambientaddons.utils + +import AmbientAddons.Companion.mc +import com.ambientaddons.utils.DungeonFloor.Companion.toDungeonFloor +import com.ambientaddons.utils.Extensions.cleanSB +import com.ambientaddons.utils.Extensions.stripControlCodes +import com.ambientaddons.utils.Extensions.substringBetween +import com.ambientaddons.utils.TabListUtils.fetchTabEntries +import net.minecraft.scoreboard.Score +import net.minecraft.scoreboard.ScorePlayerTeam +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.network.FMLNetworkEvent + +object LocationUtils { + private var areaRegex = Regex("^(?:Area|Dungeon): ([\\w ].+)\$") + private var onHypixel = false + var inSkyblock = false + var location: String? = null + var dungeonFloor: DungeonFloor? = null + var ticks = 0 + + @SubscribeEvent + fun onWorldUnload(event: WorldEvent.Unload) { + inSkyblock = false + dungeonFloor = null + location = null + } + + @SubscribeEvent + fun onConnect(event: FMLNetworkEvent.ClientConnectedToServerEvent) { + onHypixel = mc.runCatching { + !event.isLocal && ((thePlayer?.clientBrand?.lowercase()?.contains("hypixel") + ?: currentServerData?.serverIP?.lowercase()?.contains("hypixel")) == true) + }.getOrDefault(false) + } + + @SubscribeEvent + fun onDisconnect(event: FMLNetworkEvent.ClientDisconnectionFromServerEvent) { + onHypixel = false + } + + // from Skytils, under AGPL 3.0 + fun fetchScoreboardLines(): List<String> { + val scoreboard = mc.theWorld?.scoreboard ?: return emptyList() + val objective = scoreboard.getObjectiveInDisplaySlot(1) ?: return emptyList() + val scores = scoreboard.getSortedScores(objective).filter { input: Score? -> + input != null && input.playerName != null && !input.playerName + .startsWith("#") + }.take(15) + return scores.map { + ScorePlayerTeam.formatPlayerName(scoreboard.getPlayersTeam(it.playerName), it.playerName).cleanSB() + }.asReversed() + } + + // modified from Harry282/Skyblock-Client, under AGPL 3.0 + @SubscribeEvent + fun onTick(event: TickEvent.ClientTickEvent) { + if (!onHypixel || event.phase != TickEvent.Phase.START) return + if (ticks % 10 == 0) { + val title = mc.theWorld?.scoreboard?.getObjectiveInDisplaySlot(1)?.displayName?.cleanSB() + if (!inSkyblock) { + inSkyblock = title?.contains("SKYBLOCK") == true + } + if (inSkyblock) { + if (location == null) { + val tab = fetchTabEntries() + location = tab.firstNotNullOfOrNull { areaRegex.find(it.text.stripControlCodes()) }?.let { + it.groupValues.getOrNull(1) + } + } + if (location == "Catacombs" && dungeonFloor == null) { + val dungeonLine = fetchScoreboardLines().find { + it.run { contains("The Catacombs (") && !contains("Queue") } + } + dungeonFloor = dungeonLine?.substringBetween("(", ")")?.toDungeonFloor() + } + } + } + ticks++ + } + + override fun toString(): String = + "onHypixel: $onHypixel, inSkyblock: $inSkyblock, location: $location, floor: $dungeonFloor" + +}
\ No newline at end of file diff --git a/src/main/kotlin/com/ambientaddons/utils/TabListUtils.kt b/src/main/kotlin/com/ambientaddons/utils/TabListUtils.kt new file mode 100644 index 0000000..6fd7fef --- /dev/null +++ b/src/main/kotlin/com/ambientaddons/utils/TabListUtils.kt @@ -0,0 +1,38 @@ +package com.ambientaddons.utils + +import AmbientAddons.Companion.mc +import com.google.common.collect.ComparisonChain +import com.google.common.collect.Ordering +import net.minecraft.client.network.NetworkPlayerInfo +import net.minecraft.world.WorldSettings + +// From SkytilsMod/Skytils, under AGPL 3.0 +val NetworkPlayerInfo.text: String + get() = mc.ingameGUI.tabList.getPlayerName(this) + +object TabListUtils { + private val playerInfoOrdering = object : Ordering<NetworkPlayerInfo>() { + override fun compare(p_compare_1_: NetworkPlayerInfo?, p_compare_2_: NetworkPlayerInfo?): Int { + val scorePlayerTeam = p_compare_1_?.playerTeam + val scorePlayerTeam1 = p_compare_2_?.playerTeam + if (p_compare_1_ != null) { + if (p_compare_2_ != null) { + return ComparisonChain.start().compareTrueFirst( + p_compare_1_.gameType != WorldSettings.GameType.SPECTATOR, + p_compare_2_.gameType != WorldSettings.GameType.SPECTATOR + ).compare( + if (scorePlayerTeam != null) scorePlayerTeam.registeredName else "", + if (scorePlayerTeam1 != null) scorePlayerTeam1.registeredName else "" + ).compare(p_compare_1_.gameProfile.name, p_compare_2_.gameProfile.name).result() + } + return 0 + } + return -1 + } + } + + fun fetchTabEntries(): List<NetworkPlayerInfo> = + if (mc.thePlayer == null) emptyList() else playerInfoOrdering.sortedCopy( + mc.thePlayer.sendQueue.playerInfoMap + ) +}
\ No newline at end of file |