/*
* Skytils - Hypixel Skyblock Quality of Life Mod
* Copyright (C) 2021 Skytils
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see .
*/
package skytils.skytilsmod.utils
import com.google.gson.Gson
import com.google.gson.JsonObject
import net.minecraft.client.gui.inventory.GuiChest
import net.minecraft.inventory.ContainerChest
import net.minecraft.network.play.client.C01PacketChatMessage
import net.minecraft.scoreboard.Score
import net.minecraft.scoreboard.ScorePlayerTeam
import net.minecraftforge.client.event.ClientChatReceivedEvent
import net.minecraftforge.client.event.GuiOpenEvent
import net.minecraftforge.event.world.WorldEvent
import net.minecraftforge.fml.common.eventhandler.EventPriority
import net.minecraftforge.fml.common.eventhandler.SubscribeEvent
import net.minecraftforge.fml.common.gameevent.TickEvent
import net.minecraftforge.fml.common.gameevent.TickEvent.ClientTickEvent
import skytils.skytilsmod.Skytils
import skytils.skytilsmod.Skytils.Companion.mc
import skytils.skytilsmod.events.impl.PacketEvent
import skytils.skytilsmod.events.impl.SendChatMessageEvent
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.*
/**
* Adapted from NotEnoughUpdates under Creative Commons Attribution-NonCommercial 3.0
* https://github.com/Moulberry/NotEnoughUpdates/blob/master/LICENSE
*
* @author Moulberry
*/
object SBInfo {
private val timePattern = ".+(am|pm)".toRegex()
private val JSON_BRACKET_PATTERN = "\\{.+}".toRegex()
var location = ""
var date = ""
var time = ""
var objective: String? = ""
var mode: String? = ""
var currentTimeDate: Date? = null
@JvmField
var lastOpenContainerName: String? = null
private var lastManualLocRaw: Long = -1
private var lastLocRaw: Long = -1
private var joinedWorld: Long = -1
private var locraw: JsonObject? = null
@SubscribeEvent
fun onGuiOpen(event: GuiOpenEvent) {
if (!Utils.inSkyblock) return
if (event.gui is GuiChest) {
val chest = event.gui as GuiChest
val container = chest.inventorySlots as ContainerChest
val containerName = container.lowerChestInventory.displayName.unformattedText
lastOpenContainerName = containerName
}
}
@SubscribeEvent
fun onWorldChange(event: WorldEvent.Load) {
lastLocRaw = -1
locraw = null
mode = null
joinedWorld = System.currentTimeMillis()
lastOpenContainerName = null
}
@SubscribeEvent
fun onSendChatMessage(event: SendChatMessageEvent) {
val msg = event.message
if (msg.trim().startsWith("/locraw")) {
lastManualLocRaw = System.currentTimeMillis()
}
}
@SubscribeEvent(priority = EventPriority.LOW, receiveCanceled = true)
fun onChatMessage(event: ClientChatReceivedEvent) {
if (event.message.unformattedText.contains("{") && event.message.unformattedText.contains("}")) {
val pattern = JSON_BRACKET_PATTERN.find(event.message.unformattedText) ?: return
try {
val obj = Gson().fromJson(pattern.groupValues[0], JsonObject::class.java)
if (obj.has("server")) {
if (System.currentTimeMillis() - lastManualLocRaw > 5000) event.isCanceled = true
if (obj.has("gametype") && obj.has("mode") && obj.has("map")) {
locraw = obj
mode = locraw!!["mode"].asString
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
@SubscribeEvent
fun onPacket(event: PacketEvent.SendEvent) {
if (Utils.isOnHypixel && event.packet is C01PacketChatMessage) {
if (event.packet.message.startsWith("/locraw")) {
lastLocRaw = System.currentTimeMillis()
}
}
}
@SubscribeEvent
fun onTick(event: ClientTickEvent) {
if (event.phase != TickEvent.Phase.START || mc.thePlayer == null || mc.theWorld == null || !Utils.inSkyblock) return
val currentTime = System.currentTimeMillis()
if (locraw == null && currentTime - joinedWorld > 1300 && currentTime - lastLocRaw > 15000) {
lastLocRaw = System.currentTimeMillis()
Skytils.sendMessageQueue.add("/locraw")
}
try {
val scoreboard = mc.thePlayer.worldScoreboard
val sidebarObjective = scoreboard.getObjectiveInDisplaySlot(1) //§707/14/20
val scores: List = ArrayList(scoreboard.getSortedScores(sidebarObjective))
val lines: MutableList = ArrayList()
for (i in scores.indices.reversed()) {
val score = scores[i]
val scorePlayerTeamOne = scoreboard.getPlayersTeam(score.playerName)
var line = ScorePlayerTeam.formatPlayerName(scorePlayerTeamOne, score.playerName)
line = line.stripControlCodes()
lines.add(line)
}
if (lines.size >= 5) {
date = lines[2].stripControlCodes().trim()
//§74:40am
val matcher = timePattern.find(lines[3])
if (matcher != null) {
time = matcher.groupValues[0].stripControlCodes().trim()
try {
val timeSpace = time.replace("am", " am").replace("pm", " pm")
val parseFormat = SimpleDateFormat("hh:mm a")
currentTimeDate = parseFormat.parse(timeSpace)
} catch (e: ParseException) {
}
}
for (loc in lines) {
if (loc.contains('⏣')) {
location = loc.stripControlCodes().replace("[^A-Za-z0-9() -]".toRegex(), "").trim()
break
}
}
}
objective = null
var objTextLast = false
for (line in lines) {
if (objTextLast) {
objective = line
}
objTextLast = line == "Objective"
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
enum class SkyblockIsland(val formattedName: String, val mode: String) {
PrivateIsland("Private Island", "dynamic"),
SpiderDen("Spider's Den", "combat_1"),
BlazingFortress("Blazing Fortress", "combat_2"),
TheEnd("The End", "combat_3"),
GoldMine("Gold Mine", "mining_1"),
DeepCaverns("Deep Caverns", "mining_2"),
DwarvenMines("Dwarven Mines", "mining_3"),
CrystalHollows("Crystal Hollows", "crystal_hollows"),
FarmingIsland("The Farming Islands", "farming_1"),
ThePark("The Park", "foraging_1"),
Dungeon("Dungeon", "dungeon"),
DungeonHub("Dungeon Hub", "dungeon_hub"),
Hub("Hub", "hub"),
DarkAuction("Dark Auction", "dark_auction"),
JerryWorkshop("Jerry's Workshop", "winter")
}