Reform dependency structure.

This commit is contained in:
2023-02-07 04:52:54 -05:00
parent eb587dc299
commit d335a0b63f
36 changed files with 121 additions and 98 deletions

View File

@ -0,0 +1,3 @@
plugins {
id("gay.pizza.foundation.concrete-library")
}

View File

@ -0,0 +1,74 @@
package gay.pizza.foundation.shared
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
import net.kyori.adventure.text.serializer.legacy.LegacyComponentSerializer
import org.bukkit.advancement.Advancement
import java.lang.reflect.Field
import java.util.concurrent.ConcurrentHashMap
private fun Advancement.getInternalHandle(): Any =
javaClass.getMethod("getHandle").invoke(this)
private fun Class<*>.getDeclaredFieldAccessible(name: String): Field {
val field = getDeclaredField(name)
if (!field.trySetAccessible()) {
throw RuntimeException("Failed to set reflection permissions to accessible.")
}
return field
}
private fun Advancement.getInternalAdvancementDisplay(handle: Any = getInternalHandle()): Any? =
handle.javaClass.methods.firstOrNull {
it.returnType.simpleName == "AdvancementDisplay" &&
it.parameterCount == 0
}?.invoke(handle) ?: handle.javaClass.getDeclaredFieldAccessible("c").get(handle)
private fun Advancement.displayTitleText(): String? {
val handle = getInternalHandle()
val advancementDisplay = getInternalAdvancementDisplay(handle) ?: return null
try {
val field = advancementDisplay.javaClass.getDeclaredField("a")
field.trySetAccessible()
val message = field.get(advancementDisplay)
val title = message.javaClass.getMethod("getString").invoke(message)
return title.toString()
} catch (_: Exception) {
}
val titleComponentField = advancementDisplay.javaClass.declaredFields.firstOrNull {
it.type.simpleName == "IChatBaseComponent"
}
if (titleComponentField != null) {
titleComponentField.trySetAccessible()
val titleChatBaseComponent = titleComponentField.get(advancementDisplay)
val title = titleChatBaseComponent.javaClass.getMethod("getText").invoke(titleChatBaseComponent).toString()
if (title.isNotBlank()) {
return title
}
val chatSerializerClass = titleChatBaseComponent.javaClass.declaredClasses.firstOrNull {
it.simpleName == "ChatSerializer"
}
if (chatSerializerClass != null) {
val componentJson = chatSerializerClass
.getMethod("a", titleChatBaseComponent.javaClass)
.invoke(null, titleChatBaseComponent).toString()
val gson = GsonComponentSerializer.gson().deserialize(componentJson)
return LegacyComponentSerializer.legacySection().serialize(gson)
}
}
val rawAdvancementName = key.key
return rawAdvancementName.substring(rawAdvancementName.lastIndexOf("/") + 1)
.lowercase().split("_")
.joinToString(" ") { it.substring(0, 1).uppercase() + it.substring(1) }
}
object AdvancementTitleCache {
private val cache = ConcurrentHashMap<Advancement, String?>()
fun of(advancement: Advancement): String? =
cache.computeIfAbsent(advancement) { it.displayTitleText() }
}

View File

@ -0,0 +1,7 @@
package gay.pizza.foundation.shared
import org.bukkit.entity.Player
fun Player.chat(vararg messages: String): Unit = messages.forEach { message ->
chat(message)
}

View File

@ -0,0 +1,8 @@
package gay.pizza.foundation.shared
fun <T, R : Comparable<R>> Collection<T>.sortedBy(order: SortOrder, selector: (T) -> R?): List<T> =
if (order == SortOrder.Ascending) {
sortedBy(selector)
} else {
sortedByDescending(selector)
}

View File

@ -0,0 +1,7 @@
package gay.pizza.foundation.shared
import java.nio.file.Path
interface IFoundationCore {
val pluginDataPath: Path
}

View File

@ -0,0 +1,7 @@
package gay.pizza.foundation.shared
object Platform {
private val os: String? = System.getProperty("os.name")
fun isWindows(): Boolean = os != null && os.lowercase().startsWith("windows")
}

View File

@ -0,0 +1,3 @@
package gay.pizza.foundation.shared
annotation class PluginMainClass

View File

@ -0,0 +1,28 @@
package gay.pizza.foundation.shared
import org.bukkit.Material
import org.bukkit.OfflinePlayer
import org.bukkit.Server
import org.bukkit.Statistic
import org.bukkit.entity.EntityType
val Server.allPlayers: List<OfflinePlayer>
get() = listOf(onlinePlayers, offlinePlayers.filter { !isPlayerOnline(it) }.toList()).flatten()
fun Server.isPlayerOnline(player: OfflinePlayer) =
onlinePlayers.any { onlinePlayer -> onlinePlayer.name == player.name }
fun Server.allPlayerStatisticsOf(
statistic: Statistic,
material: Material? = null,
entityType: EntityType? = null,
order: SortOrder = SortOrder.Ascending
) = allPlayers.map { player ->
player to if (material != null) {
player.getStatistic(statistic, material)
} else if (entityType != null) {
player.getStatistic(statistic, entityType)
} else {
player.getStatistic(statistic)
}
}.sortedBy(order) { it.second }

View File

@ -0,0 +1,6 @@
package gay.pizza.foundation.shared
enum class SortOrder {
Ascending,
Descending
}

View File

@ -0,0 +1,12 @@
package gay.pizza.foundation.shared
import org.bukkit.Location
import org.bukkit.World
import org.bukkit.entity.Entity
import org.bukkit.entity.Player
import kotlin.reflect.KClass
fun <T: Entity> World.spawn(location: Location, clazz: KClass<T>): T = spawn(location, clazz.java)
fun <T: Entity> Player.spawn(clazz: KClass<T>): T = spawn(clazz.java)
fun <T: Entity> Player.spawn(clazz: Class<T>): T = world.spawn(location, clazz)

View File

@ -0,0 +1,39 @@
package gay.pizza.foundation.shared
import org.slf4j.Logger
import java.nio.file.Path
/**
* Copy the default configuration from the resource [resourceName] into the directory [targetPath].
* @param targetPath The output directory as a path, it must exist before calling this.
* @param resourceName Path to resource, it should be in the root of the `resources` directory,
* without the leading slash.
*/
inline fun <reified T> copyDefaultConfig(log: Logger, targetPath: Path, resourceName: String): Path {
if (resourceName.startsWith("/")) {
throw IllegalArgumentException("resourceName starts with slash")
}
if (!targetPath.toFile().exists()) {
throw Exception("Configuration output path does not exist!")
}
val outPath = targetPath.resolve(resourceName)
val outFile = outPath.toFile()
if (outFile.exists()) {
log.debug("Configuration file already exists.")
return outPath
}
val resourceStream = T::class.java.getResourceAsStream("/$resourceName")
?: throw Exception("Configuration resource does not exist!")
val outputStream = outFile.outputStream()
resourceStream.use {
outputStream.use {
log.info("Copied default configuration to $outPath")
resourceStream.copyTo(outputStream)
}
}
return outPath
}