diff options
| author | Lorenz <lo.scherf@gmail.com> | 2022-08-17 03:05:34 +0200 |
|---|---|---|
| committer | Lorenz <lo.scherf@gmail.com> | 2022-08-17 03:05:34 +0200 |
| commit | efbf06263d6fbf5de5a815fe5583ddd02710470f (patch) | |
| tree | cb56d5969f8bebf586298475a61c521229663fda /src/main/java/at/hannibal2/skyhanni/data | |
| parent | 9b8ff26e84dda348685fe1306abed7457b63f7e3 (diff) | |
| download | SkyHanni-efbf06263d6fbf5de5a815fe5583ddd02710470f.tar.gz SkyHanni-efbf06263d6fbf5de5a815fe5583ddd02710470f.tar.bz2 SkyHanni-efbf06263d6fbf5de5a815fe5583ddd02710470f.zip | |
moving packets around
Diffstat (limited to 'src/main/java/at/hannibal2/skyhanni/data')
6 files changed, 565 insertions, 0 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/data/ApiData.kt b/src/main/java/at/hannibal2/skyhanni/data/ApiData.kt new file mode 100644 index 000000000..9e47d5d0f --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/ApiData.kt @@ -0,0 +1,90 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.ProfileApiDataLoadedEvent +import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.utils.APIUtil +import at.hannibal2.skyhanni.utils.LorenzUtils +import net.minecraft.client.Minecraft +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class ApiData { + + private var currentProfileName = "" + + @SubscribeEvent + fun onStatusBar(event: LorenzChatEvent) { + val message = event.message + if (message.startsWith("§aYour new API key is §r§b")) { + SkyHanniMod.feature.hidden.apiKey = message.substring(26) + LorenzUtils.chat("§b[SkyHanni] A new API Key has been detected and installed") + + if (currentProfileName != "") { + updateApiData() + } + } + } + + @SubscribeEvent + fun onStatusBar(event: ProfileJoinEvent) { + currentProfileName = event.name + updateApiData() + } + + private fun updateApiData() { + val uuid = Minecraft.getMinecraft().thePlayer.uniqueID.toString().replace("-", "") + + val apiKey = SkyHanniMod.feature.hidden.apiKey + + if (apiKey.isEmpty()) { + LorenzUtils.error("SkyHanni has no API Key set. Type /api new to reload.") + return + } + + val url = "https://api.hypixel.net/player?key=$apiKey&uuid=$uuid" + + val jsonObject = APIUtil.getJSONResponse(url) + + if (!jsonObject["success"].asBoolean) { + val cause = jsonObject["cause"].asString + if (cause == "Invalid API key") { + LorenzUtils.error("SkyHanni got an API error: Invalid API key! Type /api new to reload.") + return + } else { + throw RuntimeException("API error for url '$url': $cause") + } + } + + val player = jsonObject["player"].asJsonObject + val stats = player["stats"].asJsonObject + val skyblock = stats["SkyBlock"].asJsonObject + val profiles = skyblock["profiles"].asJsonObject + for (entry in profiles.entrySet()) { + val asJsonObject = entry.value.asJsonObject + val name = asJsonObject["cute_name"].asString + val profileId = asJsonObject["profile_id"].asString + if (currentProfileName == name.lowercase()) { + loadProfile(uuid, profileId) + return + } + } + } + + private fun loadProfile(playerUuid: String, profileId: String) { + val apiKey = SkyHanniMod.feature.hidden.apiKey + val url = "https://api.hypixel.net/skyblock/profile?key=$apiKey&profile=$profileId" + + val jsonObject = APIUtil.getJSONResponse(url) + + val profile = jsonObject["profile"].asJsonObject + val members = profile["members"].asJsonObject + for (entry in members.entrySet()) { + if (entry.key == playerUuid) { + val profileData = entry.value.asJsonObject + ProfileApiDataLoadedEvent(profileData).postAndCatch() + + } + } + } +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt new file mode 100644 index 000000000..f9c0af979 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/HypixelData.kt @@ -0,0 +1,106 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.events.LorenzChatEvent +import at.hannibal2.skyhanni.events.PacketEvent +import at.hannibal2.skyhanni.events.ProfileJoinEvent +import at.hannibal2.skyhanni.utils.LorenzUtils.removeColor +import net.minecraft.client.Minecraft +import net.minecraft.network.play.server.S38PacketPlayerListItem +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 + +class HypixelData { + + companion object { + var hypixel = false + var skyblock = false + var dungeon = false + } + + @SubscribeEvent + fun onConnect(event: FMLNetworkEvent.ClientConnectedToServerEvent) { + hypixel = Minecraft.getMinecraft().runCatching { + !event.isLocal && (thePlayer?.clientBrand?.lowercase()?.contains("hypixel") + ?: currentServerData?.serverIP?.lowercase()?.contains("hypixel") ?: false) + }.onFailure { it.printStackTrace() }.getOrDefault(false) + } + + val areaRegex = Regex("§r§b§l(?<area>[\\w]+): §r§7(?<loc>[\\w ]+)§r") + + @SubscribeEvent + fun onTabUpdate(event: PacketEvent.ReceiveEvent) { + if (dungeon || !hypixel || event.packet !is S38PacketPlayerListItem || + (event.packet.action != S38PacketPlayerListItem.Action.UPDATE_DISPLAY_NAME && + event.packet.action != S38PacketPlayerListItem.Action.ADD_PLAYER) + ) return + event.packet.entries.forEach { playerData -> + val name = playerData?.displayName?.formattedText ?: playerData?.profile?.name ?: return@forEach + areaRegex.matchEntire(name)?.let { result -> + dungeon = skyblock && result.groups["area"]?.value == "Dungeon" + return@forEach + } + } + } + + @SubscribeEvent + fun onWorldChange(event: WorldEvent.Load) { + skyblock = false + dungeon = false + } + + @SubscribeEvent + fun onDisconnect(event: FMLNetworkEvent.ClientDisconnectionFromServerEvent) { + hypixel = false + skyblock = false + dungeon = false + } + + @SubscribeEvent + fun onStatusBar(event: LorenzChatEvent) { + if (!hypixel) return + + val message = event.message.removeColor().lowercase() + + if (message.startsWith("your profile was changed to:")) { + val stripped = message.replace("your profile was changed to:", "").replace("(co-op)", "").trim() + ProfileJoinEvent(stripped).postAndCatch() + } + if (message.startsWith("you are playing on profile:")) { + val stripped = message.replace("you are playing on profile:", "").replace("(co-op)", "").trim() + ProfileJoinEvent(stripped).postAndCatch() + + } + } + + var timerTick = 0 + + @SubscribeEvent + fun onTick(event: TickEvent.ClientTickEvent) { + if (!hypixel) return + if (event.phase != TickEvent.Phase.START) return + + timerTick++ + + if (timerTick % 5 != 0) return + + val newState = checkScoreboard() + if (newState == skyblock) return + + skyblock = newState + } + + private fun checkScoreboard(): Boolean { + val minecraft = Minecraft.getMinecraft() + val world = minecraft.theWorld ?: return false + + val sidebarObjective = world.scoreboard.getObjectiveInDisplaySlot(1) ?: return false + + val displayName = sidebarObjective.displayName + + return displayName.removeColor().contains("SKYBLOCK") + + } + +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/data/ItemRenderBackground.kt b/src/main/java/at/hannibal2/skyhanni/data/ItemRenderBackground.kt new file mode 100644 index 000000000..bff39fc8c --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/ItemRenderBackground.kt @@ -0,0 +1,47 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.events.RenderRealOverlayEvent +import at.hannibal2.skyhanni.utils.LorenzUtils +import net.minecraft.client.Minecraft +import net.minecraft.client.gui.Gui +import net.minecraft.client.renderer.GlStateManager +import net.minecraft.item.ItemStack +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent + +class ItemRenderBackground { + + companion object { + + val map = mutableMapOf<ItemStack, Int>() + val mapTime = mutableMapOf<ItemStack, Long>() + + var ItemStack.background: Int + get() { + if (System.currentTimeMillis() > mapTime.getOrDefault(this, 0) + 100) return -1 + return map.getOrDefault(this, -1) + } + set(value) { + map[this] = value + mapTime[this] = System.currentTimeMillis() + } + } + + + @SubscribeEvent + fun renderOverlayLol(event: RenderRealOverlayEvent) { + val stack = event.stack + if (LorenzUtils.inSkyblock) { + if (stack != null) { + val color = stack.background + if (color != -1) { + GlStateManager.pushMatrix() + GlStateManager.translate(0f, 0f, 110 + Minecraft.getMinecraft().renderItem.zLevel) + val x = event.x + val y = event.y + Gui.drawRect(x, y, x + 16, y + 16, color) + GlStateManager.popMatrix() + } + } + } + } +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt b/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt new file mode 100644 index 000000000..179635250 --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/ScoreboardData.kt @@ -0,0 +1,48 @@ +package at.hannibal2.skyhanni.data + +import at.hannibal2.skyhanni.utils.LorenzUtils.removeColor +import net.minecraft.client.Minecraft +import net.minecraft.scoreboard.Score +import net.minecraft.scoreboard.ScorePlayerTeam +import net.minecraftforge.fml.common.eventhandler.EventPriority +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent +import net.minecraftforge.fml.common.gameevent.TickEvent + +class ScoreboardData { + + companion object { + var sidebarLines: List<String> = emptyList() + var sidebarLinesRaw: List<String> = emptyList() + } + + @SubscribeEvent(priority = EventPriority.HIGHEST) + fun onTick(event: TickEvent.ClientTickEvent) { + if (event.phase != TickEvent.Phase.START) return + + val list = fetchScoreboardLines() + sidebarLines = list.map { cleanSB(it) }.reversed() + sidebarLinesRaw = list.reversed() + } + + private fun cleanSB(scoreboard: String): String { + return scoreboard.removeColor().toCharArray().filter { it.code in 21..126 }.joinToString(separator = "") + } + + fun fetchScoreboardLines(): List<String> { + val scoreboard = Minecraft.getMinecraft().theWorld?.scoreboard ?: return emptyList() + val objective = scoreboard.getObjectiveInDisplaySlot(1) ?: return emptyList() + var scores = scoreboard.getSortedScores(objective) + val list = scores.filter { input: Score? -> + input != null && input.playerName != null && !input.playerName + .startsWith("#") + } + scores = if (list.size > 15) { + list.drop(15) + } else { + list + } + return scores.map { + ScorePlayerTeam.formatPlayerName(scoreboard.getPlayersTeam(it.playerName), it.playerName) + } + } +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt new file mode 100644 index 000000000..8351991ab --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoManager.kt @@ -0,0 +1,172 @@ +package at.hannibal2.skyhanni.data.repo + +import at.hannibal2.skyhanni.SkyHanniMod +import at.hannibal2.skyhanni.events.RepositoryReloadEvent +import at.hannibal2.skyhanni.utils.LorenzUtils +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import com.google.gson.JsonObject +import net.minecraft.client.Minecraft +import org.apache.commons.io.FileUtils +import java.io.* +import java.net.URL +import java.nio.charset.StandardCharsets +import java.util.concurrent.CompletableFuture +import java.util.concurrent.atomic.AtomicBoolean + +class RepoManager(private val configLocation: File) { + val gson: Gson = GsonBuilder().setPrettyPrinting().create() + private var latestRepoCommit: String? = null + private val repoLocation: File = File(configLocation, "repo") + + fun loadRepoInformation() { + atomicShouldManuallyReload.set(true) + if (SkyHanniMod.feature.apiData.repoAutoUpdate) { + fetchRepository().thenRun(this::reloadRepository) + } else { + reloadRepository() + } + } + + private val atomicShouldManuallyReload = AtomicBoolean(false)//TODO FIX + + fun updateRepo() { + atomicShouldManuallyReload.set(true) + fetchRepository(true).thenRun { this.reloadRepository("Repo updated successful :)") } + } + + fun reloadLocalRepo() { + atomicShouldManuallyReload.set(true) + reloadRepository("Repo loaded from local files successful :)") + } + + private fun fetchRepository(command: Boolean = false): CompletableFuture<Boolean> { + return CompletableFuture.supplyAsync { + try { + val currentCommitJSON: JsonObject? = getJsonFromFile(File(configLocation, "currentCommit.json")) + latestRepoCommit = null + try { + InputStreamReader(URL(getCommitApiUrl()).openStream()) + .use { inReader -> + val commits: JsonObject = gson.fromJson(inReader, JsonObject::class.java) + latestRepoCommit = commits["sha"].asString + } + } catch (e: Exception) { + e.printStackTrace() + } + if (latestRepoCommit == null || latestRepoCommit!!.isEmpty()) return@supplyAsync false + if (File(configLocation, "repo").exists()) { + if (currentCommitJSON != null && currentCommitJSON["sha"].asString == latestRepoCommit) { + if (command) { + LorenzUtils.chat("§e[SkyHanni] §7The repo is already up to date!") + atomicShouldManuallyReload.set(false) + } + return@supplyAsync false + } + } + RepoUtils.recursiveDelete(repoLocation) + repoLocation.mkdirs() + val itemsZip = File(repoLocation, "sh-repo-main.zip") + try { + itemsZip.createNewFile() + } catch (e: IOException) { + return@supplyAsync false + } + val url = URL(getDownloadUrl(latestRepoCommit)) + val urlConnection = url.openConnection() + urlConnection.connectTimeout = 15000 + urlConnection.readTimeout = 30000 + try { + urlConnection.getInputStream().use { `is` -> + FileUtils.copyInputStreamToFile( + `is`, + itemsZip + ) + } + } catch (e: IOException) { + e.printStackTrace() + System.err.println("Failed to download SkyHanni Repo! Please report this issue to the mod creator") + if (command) { + LorenzUtils.error("An error occurred while trying to reload the repo! See logs for more info.") + } + return@supplyAsync false + } + RepoUtils.unzipIgnoreFirstFolder( + itemsZip.absolutePath, + repoLocation.absolutePath + ) + if (currentCommitJSON == null || currentCommitJSON["sha"].asString != latestRepoCommit) { + val newCurrentCommitJSON = JsonObject() + newCurrentCommitJSON.addProperty("sha", latestRepoCommit) + try { + writeJson(newCurrentCommitJSON, File(configLocation, "currentCommit.json")) + } catch (ignored: IOException) { + } + } + } catch (e: Exception) { + e.printStackTrace() + } + true + } + } + + private fun reloadRepository(answerMessage: String = ""): CompletableFuture<Void?> { + val comp = CompletableFuture<Void?>() + if (!atomicShouldManuallyReload.get()) return comp + Minecraft.getMinecraft().addScheduledTask { + try { + RepositoryReloadEvent(repoLocation, gson).postAndCatch() + comp.complete(null) + if (answerMessage.isNotEmpty()) { + LorenzUtils.chat("§e[SkyHanni] §a$answerMessage") + } + } catch (e: java.lang.Exception) { + comp.completeExceptionally(e) + LorenzUtils.error("An error occurred while trying to reload the repo! See logs for more info.") + } + } + return comp + } + + /** + * Parses a file in to a JsonObject. + */ + private fun getJsonFromFile(file: File?): JsonObject? { + try { + BufferedReader( + InputStreamReader( + FileInputStream(file), + StandardCharsets.UTF_8 + ) + ).use { reader -> + return gson.fromJson(reader, JsonObject::class.java) + } + } catch (e: java.lang.Exception) { + return null + } + } + + private fun getCommitApiUrl(): String { + val repoUser = "hannibal00212" + val repoName = "SkyHanni-REPO" + val repoBranch = "main" + return String.format("https://api.github.com/repos/%s/%s/commits/%s", repoUser, repoName, repoBranch) + } + + private fun getDownloadUrl(commitId: String?): String { + val repoUser = "hannibal00212" + val repoName = "SkyHanni-REPO" + return String.format("https://github.com/%s/%s/archive/%s.zip", repoUser, repoName, commitId) + } + + @Throws(IOException::class) + fun writeJson(json: JsonObject?, file: File) { + file.createNewFile() + BufferedWriter( + OutputStreamWriter( + FileOutputStream(file), + StandardCharsets.UTF_8 + ) + ).use { writer -> writer.write(gson.toJson(json)) } + } +}
\ No newline at end of file diff --git a/src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt new file mode 100644 index 000000000..969b526cc --- /dev/null +++ b/src/main/java/at/hannibal2/skyhanni/data/repo/RepoUtils.kt @@ -0,0 +1,102 @@ +package at.hannibal2.skyhanni.data.repo + +import com.google.gson.Gson +import com.google.gson.JsonObject +import java.io.* +import java.nio.charset.StandardCharsets +import java.nio.file.Files +import java.util.zip.ZipInputStream + +object RepoUtils { + + fun recursiveDelete(file: File) { + if (file.isDirectory && !Files.isSymbolicLink(file.toPath())) { + for (child in file.listFiles()) { + recursiveDelete(child) + } + } + file.delete() + } + + /** + * Modified from https://www.journaldev.com/960/java-unzip-file-example + */ + fun unzipIgnoreFirstFolder(zipFilePath: String, destDir: String) { + val dir = File(destDir) + // create output directory if it doesn't exist + if (!dir.exists()) dir.mkdirs() + val fis: FileInputStream + //buffer for read and write data to file + val buffer = ByteArray(1024) + try { + fis = FileInputStream(zipFilePath) + val zis = ZipInputStream(fis) + var ze = zis.nextEntry + while (ze != null) { + if (!ze.isDirectory) { + var fileName = ze.name + fileName = fileName.substring(fileName.split("/").toTypedArray()[0].length + 1) + val newFile = File(destDir + File.separator + fileName) + //create directories for sub directories in zip + File(newFile.parent).mkdirs() + if (!isInTree(dir, newFile)) { + throw RuntimeException( + "SkyHanni detected an invalid zip file. This is a potential security risk, please report this on the SkyHanni discord." + ) + } + val fos = FileOutputStream(newFile) + var len: Int + while (zis.read(buffer).also { len = it } > 0) { + fos.write(buffer, 0, len) + } + fos.close() + } + //close this ZipEntry + zis.closeEntry() + ze = zis.nextEntry + } + //close last ZipEntry + zis.closeEntry() + zis.close() + fis.close() + } catch (e: IOException) { + e.printStackTrace() + } + } + + @Throws(IOException::class) + private fun isInTree(rootDirectory: File, file: File): Boolean { + var rootDirectory = rootDirectory + var file: File? = file + file = file!!.canonicalFile + rootDirectory = rootDirectory.canonicalFile + while (file != null) { + if (file == rootDirectory) return true + file = file.parentFile + } + return false + } + + fun getConstant(repoLocation: File, constant: String, gson: Gson): JsonObject? { + return getConstant(repoLocation, constant, gson, JsonObject::class.java) + } + + private fun <T> getConstant(repo: File, constant: String, gson: Gson, clazz: Class<T>?): T? { + if (repo.exists()) { + val jsonFile = File(repo, "constants/$constant.json") + try { + BufferedReader( + InputStreamReader( + FileInputStream(jsonFile), + StandardCharsets.UTF_8 + ) + ).use { reader -> + return gson.fromJson(reader, clazz) + } + } catch (e: Exception) { + return null + } + } + return null + } +}
\ No newline at end of file |
