Skip to content

Commit

Permalink
Adds self-host pack, Supports offline-mode head.
Browse files Browse the repository at this point in the history
  • Loading branch information
toxicity188 committed Apr 20, 2024
1 parent 3f1eb0b commit 08338a6
Show file tree
Hide file tree
Showing 20 changed files with 242 additions and 31 deletions.
3 changes: 2 additions & 1 deletion api/src/main/java/kr/toxicity/hud/api/nms/NMSVersion.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ public enum NMSVersion {
V1_19_R3(19,3, 13),
V1_20_R1(20,1, 15),
V1_20_R2(20,2, 18),
V1_20_R3(20,3, 22)
V1_20_R3(20,3, 22),
V1_20_R4(20,4, 32)
;
/**
* Main version.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ public interface HudScheduler {
* @return scheduled task.
*/
@NotNull HudTask task(@NotNull Plugin plugin, @NotNull Runnable runnable);
/**
* Executes sync task.
* @param plugin target plugin.
* @param delay delay
* @param runnable task
* @return scheduled task.
*/
@NotNull HudTask taskLater(@NotNull Plugin plugin, long delay, @NotNull Runnable runnable);
/**
* Executes async task.
* @param plugin target plugin.
Expand Down
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ allprojects {
apply(plugin = "kotlin")

group = "kr.toxicity.hud"
version = "beta-15-HOTFIX"
version = "beta-16"

repositories {
mavenCentral()
Expand Down
1 change: 1 addition & 0 deletions dist/src/main/kotlin/kr/toxicity/hud/BetterHudImpl.kt
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ class BetterHudImpl: BetterHud() {
"v1_20_R1" -> kr.toxicity.hud.nms.v1_20_R1.NMSImpl()
"v1_20_R2" -> kr.toxicity.hud.nms.v1_20_R2.NMSImpl()
"v1_20_R3" -> kr.toxicity.hud.nms.v1_20_R3.NMSImpl()
//"v1_20_R4" -> kr.toxicity.hud.nms.v1_20_R4.NMSImpl()
else -> {
warn("Unsupported bukkit version: $version")
pluginManager.disablePlugin(this)
Expand Down
9 changes: 9 additions & 0 deletions dist/src/main/kotlin/kr/toxicity/hud/manager/ConfigManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,17 @@ object ConfigManager: BetterHudManager {
private set
var buildFolderLocation = "BetterHud\\build"
private set
var enableProtection = true
private set

var mergeBossBar = true
private set
var packType = PackType.FOLDER
private set
var enableSelfHost = false
private set
var selfHostPort = 8163
private set

override fun start() {

Expand Down Expand Up @@ -66,7 +72,10 @@ object ConfigManager: BetterHudManager {
yaml.getString("build-folder-location")?.let {
buildFolderLocation = it
}
enableProtection = yaml.getBoolean("enable-protection")
mergeBossBar = yaml.getBoolean("merge-boss-bar", true)
enableSelfHost = yaml.getBoolean("enable-self-host")
selfHostPort = yaml.getInt("self-host-port", 8163)
}.onFailure { e ->
warn("Unable to load config.yml")
warn("Reason: ${e.message}")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import java.awt.image.BufferedImage
object PlayerHeadManager: BetterHudManager {

private val skinProviders = ArrayList<PlayerSkinProvider>()
private val defaultProviders = GameProfileProvider()
private val defaultProviders = GameProfileSkinProvider()
private val headMap = HashMap<String, HudHead>()

override fun start() {
if (Bukkit.getPluginManager().isPluginEnabled("SkinsRestorer")) {
skinProviders.add(SkinRestorerProvider())
skinProviders.add(SkinsRestorerSkinProvider())
}
if (!Bukkit.getServer().onlineMode) {
skinProviders.add(HttpSkinProvider())
Expand Down
9 changes: 5 additions & 4 deletions dist/src/main/kotlin/kr/toxicity/hud/manager/PlayerManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@ package kr.toxicity.hud.manager
import kr.toxicity.hud.api.event.HudPlayerJoinEvent
import kr.toxicity.hud.api.event.HudPlayerQuitEvent
import kr.toxicity.hud.api.player.HudPlayer
import kr.toxicity.hud.pack.PackUploader
import kr.toxicity.hud.resource.GlobalResource
import kr.toxicity.hud.util.PLUGIN
import kr.toxicity.hud.util.asyncTask
import kr.toxicity.hud.util.call
import kr.toxicity.hud.util.task
import kr.toxicity.hud.util.*
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import org.bukkit.event.EventHandler
Expand Down Expand Up @@ -48,6 +46,9 @@ object PlayerManager: BetterHudManager {
hudPlayer.computeIfAbsent(adaptedPlayer.uniqueId) {
val hud = DatabaseManagerImpl.currentDatabase.load(adaptedPlayer)
task {
taskLater(20) {
PackUploader.apply(player)
}
HudPlayerJoinEvent(adaptedPlayer, hud).call()
}
hud
Expand Down
4 changes: 2 additions & 2 deletions dist/src/main/kotlin/kr/toxicity/hud/manager/TextManager.kt
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ object TextManager: BetterHudManager {

private fun loadDefaultBitmap() {
defaultBitmapImageMap.clear()
PLUGIN.getResource("default.json")?.let {
PLUGIN.getResource("minecraft_default.json")?.let {
runCatching {
InputStreamReader(it).buffered().use { reader ->
JsonParser.parseReader(reader)
Expand Down Expand Up @@ -174,7 +174,7 @@ object TextManager: BetterHudManager {
}
}
}.onFailure { e ->
warn("Unable to parse default.json")
warn("Unable to parse minecraft_default.json")
warn("Reason: ${e.message}")
}
}
Expand Down
60 changes: 52 additions & 8 deletions dist/src/main/kotlin/kr/toxicity/hud/pack/PackGenerator.kt
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package kr.toxicity.hud.pack

import com.google.gson.JsonObject
import kr.toxicity.hud.manager.ConfigManager
import kr.toxicity.hud.util.*
import org.bukkit.Bukkit
import java.io.File
import java.math.BigInteger
import java.security.DigestOutputStream
import java.security.MessageDigest
import java.util.Comparator
import java.util.TreeMap
import java.util.zip.Deflater
Expand All @@ -12,6 +17,12 @@ import java.util.zip.ZipOutputStream
object PackGenerator {
private val tasks = TreeMap<String, PackFile>()

private class ZipBuilder(
val zip: ZipOutputStream
) {
var byte = 0
}

fun generate(callback: () -> Unit) {
runCatching {
val saveTask: Generator = when (ConfigManager.packType) {
Expand Down Expand Up @@ -62,32 +73,65 @@ object PackGenerator {
}
}
PackType.ZIP -> {
val zip = ZipOutputStream(File(DATA_FOLDER.parentFile, "${ConfigManager.buildFolderLocation}.zip").apply {
val protection = ConfigManager.enableProtection
val host = ConfigManager.enableSelfHost
val message = runCatching {
MessageDigest.getInstance("SHA-1")
}.getOrNull()
val file = File(DATA_FOLDER.parentFile, "${ConfigManager.buildFolderLocation}.zip")
val stream = file.apply {
if (!exists()) delete()
}.outputStream().buffered()).apply {
}.outputStream().buffered()
val zip = ZipBuilder(ZipOutputStream(message?.let {
DigestOutputStream(stream, it)
} ?: stream).apply {
setComment("BetterHud resource pack.")
setLevel(Deflater.BEST_COMPRESSION)
PLUGIN.loadAssets("pack") { s, i ->
putNextEntry(ZipEntry(s.replace('\\','/')))
write(i.readAllBytes())
closeEntry()
}
})
fun addEntry(entry: ZipEntry, byte: ByteArray) {
synchronized(zip) {
zip.byte += byte.size
zip.zip.putNextEntry(entry)
zip.zip.write(byte)
zip.zip.closeEntry()
if (protection) {
entry.crc = byte.size.toLong()
entry.size = BigInteger(byte).mod(BigInteger.valueOf(Long.MAX_VALUE)).toLong()
}
}
}
if (host) {
PLUGIN.getResource("icon.png")?.buffered()?.use {
addEntry(ZipEntry("pack.png"), it.readAllBytes())
}
addEntry(ZipEntry("pack.mcmeta"), JsonObject().apply {
add("pack", JsonObject().apply {
addProperty("pack_format", PLUGIN.nms.version.metaVersion)
addProperty("description", "BetterHud's self host pack.")
})
}.toByteArray())
}
object : Generator {
override fun close() {
synchronized(zip) {
zip.close()
zip.zip.close()
if (host && message != null) {
PackUploader.upload(message, file.inputStream().buffered().use {
it.readAllBytes()
})
} else PackUploader.stop()
}
}

override fun invoke(p1: PackFile) {
val entry = ZipEntry(p1.path)
val byte = p1.array()
synchronized(zip) {
zip.putNextEntry(entry)
zip.write(byte)
zip.closeEntry()
}
addEntry(entry, byte)
}
}
}
Expand Down
108 changes: 108 additions & 0 deletions dist/src/main/kotlin/kr/toxicity/hud/pack/PackUploader.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package kr.toxicity.hud.pack

import com.google.gson.JsonPrimitive
import com.sun.net.httpserver.HttpServer
import kr.toxicity.hud.api.nms.NMSVersion
import kr.toxicity.hud.manager.ConfigManager
import kr.toxicity.hud.util.*
import org.bukkit.Bukkit
import org.bukkit.entity.Player
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.URI
import java.net.http.HttpClient
import java.net.http.HttpRequest
import java.net.http.HttpResponse
import java.security.MessageDigest
import java.util.*


object PackUploader {

private interface PackServer {
fun stop()
fun apply(player: Player)
}
@Volatile
private var server: PackServer? = null

fun apply(player: Player): Boolean {
return server?.apply(player) != null
}
fun stop(): Boolean {
val result = server?.stop() != null
server = null
return result
}

fun upload(message: MessageDigest, byteArray: ByteArray) {
val hash = StringBuilder(40)
val useUrl = VERSION >= NMSVersion.V1_20_R3
val digest = message.digest()
for (element in digest) {
val byte = element.toInt()
hash.append(Character.forDigit((byte shr 4) and 15, 16))
.append(Character.forDigit(byte and 15, 16))
}
val string = hash.toString()
var t = 0
val uuid = UUID.nameUUIDFromBytes(ByteArray(20) {
((Character.digit(hash.codePointAt(t++), 16) shl 4) or Character.digit(hash.codePointAt(t++), 16)).toByte()
})
HttpClient.newHttpClient()
.sendAsync(HttpRequest.newBuilder()
.uri(URI.create("http://checkip.amazonaws.com/"))
.GET()
.build(), HttpResponse.BodyHandlers.ofString()).thenAccept {
val host = ConfigManager.selfHostPort
val body = it.body()
val url = "http://${body.substring(0, body.length - 1)}:$host/$string.zip"
runCatching {
server?.stop()
val http = HttpServer.create(InetSocketAddress(InetAddress.getLocalHost(), host), 0).apply {
createContext("/") { exec ->
exec.use { exchange ->
if (exchange.requestURI.path != "/$string.zip") {
exchange.responseHeaders.set("Content-Type", "application/json")
val byte = JsonPrimitive("Invalid file name.").toByteArray()
exchange.sendResponseHeaders(200, byte.size.toLong())
exchange.responseBody.write(byte)
} else {
exchange.responseHeaders.set("Content-Type", "application/zip")
exchange.sendResponseHeaders(200, byteArray.size.toLong())
exchange.responseBody.write(byteArray)
}
}
}
start()
}
server = object : PackServer {
override fun stop() {
http.stop(0)
}
override fun apply(player: Player) {
if (useUrl) {
player.setResourcePack(uuid, url, digest, null, false)
} else {
player.setResourcePack(url, digest, null, false)
}
}
}
Bukkit.getOnlinePlayers().forEach { player ->
if (useUrl) {
player.setResourcePack(uuid, url, digest, null, false)
} else {
player.setResourcePack(url, digest, null, false)
}
}
info("Resource pack server opened at $url")
}.onFailure { e ->
e.printStackTrace()
warn("Unable to open server.")
}
}.handle { _, e ->
e.printStackTrace()
warn("Unable to get host's ip.")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package kr.toxicity.hud.player
import kr.toxicity.hud.util.textures
import org.bukkit.entity.Player

class GameProfileProvider: PlayerSkinProvider {
class GameProfileSkinProvider: PlayerSkinProvider {
override fun provide(player: Player): String {
return player.textures
}
Expand Down
28 changes: 18 additions & 10 deletions dist/src/main/kotlin/kr/toxicity/hud/player/HttpSkinProvider.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,24 @@ import java.net.http.HttpResponse

class HttpSkinProvider: PlayerSkinProvider {
override fun provide(player: Player): String? {
return InputStreamReader(HttpClient.newHttpClient().send(HttpRequest.newBuilder()
.uri(URI.create("https://sessionserver.mojang.com/session/minecraft/profile/${player.uniqueId.toString().replace("_","").lowercase()}"))
.GET()
.build(), HttpResponse.BodyHandlers.ofInputStream()).body()).buffered().use {
return runCatching {
val uuid = InputStreamReader(HttpClient.newHttpClient().send(HttpRequest.newBuilder()
.uri(URI.create("https://api.mojang.com/users/profiles/minecraft/${player.name}?at=${System.currentTimeMillis() / 1000}"))
.GET()
.build(), HttpResponse.BodyHandlers.ofInputStream()).body()).buffered().use {
JsonParser.parseReader(it)
}.asJsonObject
.getAsJsonArray("properties")
.get(0)
.asJsonObject
.getAsJsonPrimitive("value")
.asString
}.asJsonObject.getAsJsonPrimitive("id").asString
InputStreamReader(HttpClient.newHttpClient().send(HttpRequest.newBuilder()
.uri(URI.create("https://sessionserver.mojang.com/session/minecraft/profile/$uuid"))
.GET()
.build(), HttpResponse.BodyHandlers.ofInputStream()).body()).buffered().use {
JsonParser.parseReader(it)
}.asJsonObject
.getAsJsonArray("properties")
.get(0)
.asJsonObject
.getAsJsonPrimitive("value")
.asString
}.getOrNull()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package kr.toxicity.hud.player
import net.skinsrestorer.api.SkinsRestorerProvider
import org.bukkit.entity.Player

class SkinRestorerProvider: PlayerSkinProvider {
class SkinsRestorerSkinProvider: PlayerSkinProvider {
override fun provide(player: Player): String? {
return SkinsRestorerProvider.get().playerStorage.getSkinOfPlayer(player.uniqueId).map {
it.value
Expand Down
Loading

0 comments on commit 08338a6

Please sign in to comment.