Skip to content

Commit

Permalink
🚀 start of the thingy
Browse files Browse the repository at this point in the history
  • Loading branch information
asoji committed Oct 11, 2024
1 parent fe7ae58 commit d49f2e8
Show file tree
Hide file tree
Showing 15 changed files with 239 additions and 100 deletions.
14 changes: 13 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
plugins {
kotlin("jvm") version "2.0.20"
kotlin("jvm") version "2.0.21"
`maven-publish`
java

alias(libs.plugins.grgit)
alias(libs.plugins.fabric.loom)
alias(libs.plugins.ktor)
alias(libs.plugins.kotlinx.serialization)
}

val archivesBaseName = "${project.property("archives_base_name").toString()}+mc${libs.versions.minecraft.get()}"
version = getModVersion()
group = project.property("maven_group")!!

repositories {
mavenCentral()
maven("https://api.modrinth.com/maven")
maven("https://maven.terraformersmc.com/")
maven("https://maven.parchmentmc.org")
Expand Down Expand Up @@ -40,6 +43,8 @@ dependencies {
modLocalRuntime(libs.bundles.dev.mods)

include(modImplementation("gay.asoji:fmw:1.0.0+build.8")!!) // just to avoid the basic long metadata calls

implementation(libs.bundles.ktor)
}

// Write the version to the fabric.mod.json
Expand Down Expand Up @@ -105,6 +110,13 @@ publishing {
// }
}

application {
mainClass.set("one.devos.nautical.exposeplayers.ExposePlayersKt")

val isDevelopment: Boolean = project.ext.has("development")
applicationDefaultJvmArgs = listOf("-Dio.ktor.development=$isDevelopment")
}

fun getModVersion(): String {
val modVersion = project.property("mod_version")
val buildId = System.getenv("GITHUB_RUN_NUMBER")
Expand Down
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ org.gradle.parallel=true
# Mod Properties
mod_version=0.1.0
maven_group=one.devos.nautical
archives_base_name=template
archives_base_name=exposeplayers

# Dependencies are handled in ./gradle/libs.versions.toml
19 changes: 16 additions & 3 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,36 @@ fabric_language_kotlin = "1.12.2+kotlin.2.0.20"
sodium_version = "mc1.21-0.6.0-beta.2-fabric"
mod_menu_version = "11.0.2"
joml_version = "1.10.5"
ktor = "3.0.0"


[libraries]
minecraft = { module = "com.mojang:minecraft", version.ref = "minecraft" }
#quilt_mappings = { module = "org.quiltmc:quilt-mappings", version.ref = "quilt_mappings" }
fabric_loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_loader" }
fabric-loader = { module = "net.fabricmc:fabric-loader", version.ref = "fabric_loader" }
fabric-api = { module = "net.fabricmc.fabric-api:fabric-api", version.ref = "fabric_api" }
fabric_language_kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric_language_kotlin" }
fabric-language-kotlin = { module = "net.fabricmc:fabric-language-kotlin", version.ref = "fabric_language_kotlin" }
sodium = { module = "maven.modrinth:sodium", version.ref = "sodium_version" }
joml = { module = "org.joml:joml", version.ref = "joml_version" }
mod_menu = { module = "com.terraformersmc:modmenu", version.ref = "mod_menu_version" }
ktor-server-content-negotiation-jvm = { module = "io.ktor:ktor-server-content-negotiation-jvm", version.ref = "ktor" }
ktor-server-core-jvm = { module = "io.ktor:ktor-server-core-jvm", version.ref = "ktor" }
ktor-serialization-kotlinx-json-jvm = { module = "io.ktor:ktor-serialization-kotlinx-json-jvm", version.ref = "ktor" }
ktor-server-netty-jvm = { module = "io.ktor:ktor-server-netty-jvm", version.ref = "ktor" }

# If you have multiple similar dependencies, you can declare a dependency bundle and reference it on the build script with "libs.bundles.example".
[bundles]
dev_mods = [ "joml", "sodium" ]
dependencies = [ "mod_menu" ]
ktor = [
"ktor-server-content-negotiation-jvm",
"ktor-server-core-jvm",
"ktor-serialization-kotlinx-json-jvm",
"ktor-server-netty-jvm"
]

[plugins]
grgit = { id = "org.ajoberstar.grgit", version = "5.2.2"}
fabric_loom = { id = "fabric-loom", version = "1.7-SNAPSHOT" }

ktor = { id = "io.ktor.plugin", version = "3.0.0" }
kotlinx-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version = "2.0.21" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package one.devos.nautical.exposeplayers.mixin;

import net.minecraft.server.players.PlayerList;
import net.minecraft.stats.ServerStatsCounter;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;

import java.util.Map;
import java.util.UUID;

@Mixin(PlayerList.class)
public interface PlayerListMixin {

@Accessor("stats")
default Map<UUID, ServerStatsCounter> getStats() {
throw new UnsupportedOperationException();
}

}
22 changes: 0 additions & 22 deletions src/main/java/one/devos/nautical/template/mixin/ExampleMixin.java

This file was deleted.

36 changes: 36 additions & 0 deletions src/main/kotlin/one/devos/nautical/exposeplayers/ExposePlayers.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package one.devos.nautical.exposeplayers

import gay.asoji.fmw.FMW
import io.ktor.server.engine.*
import io.ktor.server.netty.*
import net.fabricmc.api.ModInitializer
import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents
import one.devos.nautical.exposeplayers.plugins.configureRouting
import one.devos.nautical.exposeplayers.plugins.configureSerialization
import org.slf4j.Logger
import org.slf4j.LoggerFactory

object ExposePlayers : ModInitializer {
val MOD_ID: String = "exposeplayers"
val LOGGER: Logger = LoggerFactory.getLogger(MOD_ID)
val MOD_NAME: String = FMW.getName(MOD_ID)

private var server: EmbeddedServer<NettyApplicationEngine, NettyApplicationEngine.Configuration>? = null

override fun onInitialize() {
LOGGER.info("[${MOD_NAME}] Starting up ExposePlayers")

ServerLifecycleEvents.SERVER_STARTED.register { server ->
this.server?.stop()
this.server = embeddedServer(Netty, port = 64589, host = "0.0.0.0", module = {
configureRouting(server)
configureSerialization()
}).start(wait = false)
}

ServerLifecycleEvents.SERVER_STOPPED.register { server ->
this.server?.stop()
this.server = null
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package one.devos.nautical.exposeplayers.plugins

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import kotlinx.serialization.Contextual
import kotlinx.serialization.Serializable
import net.minecraft.core.registries.BuiltInRegistries
import net.minecraft.server.MinecraftServer
import net.minecraft.stats.Stats
import one.devos.nautical.exposeplayers.utils.UUIDSerializer
import one.devos.nautical.exposeplayers.utils.getPlayerStatsByUuid
import java.util.UUID

fun Application.configureRouting(server: MinecraftServer) {
routing {
get {
call.respondText("Hello world!")
}

get("/players") {
call.respond(PlayersEndpointResponse(
server.playerCount,
server.playerList.players.map { player ->
PlayerInfo(player.uuid, player.name.string)
}
))
}

get("/players/stats/{player_name}") {
val playerName = call.parameters["player_name"]
if (playerName == null) {
call.respond(HttpStatusCode.BadRequest)
return@get
}

val playerUuid = server.profileCache?.get(playerName)?.get()?.id
if (playerUuid == null) {
call.respond(HttpStatusCode.BadRequest)
return@get
}

val statsCounter = server.playerList.getPlayerStatsByUuid(playerUuid, playerName)
// call.respond(BuiltInRegistries.STAT_TYPE.map { statisticType -> {
// statisticType.flatMap
// })


}
}
}

@Serializable
private data class PlayerInfo(
@Serializable(with = UUIDSerializer::class) val uuid: UUID,
val name: String
)

@Serializable
private data class PlayersEndpointResponse(
val count: Int,
val players: List<@Contextual PlayerInfo>
)

@Serializable
private data class PlayerStatistic(
val displayName: String,
val value: Any
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package one.devos.nautical.exposeplayers.plugins

import io.ktor.serialization.kotlinx.json.*
import io.ktor.server.application.*
import io.ktor.server.plugins.contentnegotiation.*
import io.ktor.server.routing.*
import io.ktor.util.reflect.*

fun Application.configureSerialization() {
install(ContentNegotiation) {
json()
}

// routing {
// get("/json/kotlinx-serialization") {
// call.respond(
// mapOf("hello" to "world")
// )
// }
// }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package one.devos.nautical.exposeplayers.utils

import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import java.util.UUID

object UUIDSerializer : KSerializer<UUID> {

override val descriptor = PrimitiveSerialDescriptor("UUID", PrimitiveKind.STRING)

override fun deserialize(decoder: Decoder): UUID {
return UUID.fromString(decoder.decodeString())
}

override fun serialize(encoder: Encoder, value: UUID) {
encoder.encodeString(value.toString())
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package one.devos.nautical.exposeplayers.utils

import net.minecraft.FileUtil
import net.minecraft.server.players.PlayerList
import net.minecraft.stats.ServerStatsCounter
import net.minecraft.world.level.storage.LevelResource
import one.devos.nautical.exposeplayers.mixin.PlayerListMixin
import java.io.File
import java.util.UUID

val PlayerList.stats: MutableMap<UUID, ServerStatsCounter>
get() = (this as PlayerListMixin).stats

fun PlayerList.getPlayerStatsByUuid(uuid: UUID, name: String): ServerStatsCounter {
var statsCounter = stats[uuid]
if (statsCounter == null) {
val directory = this.server.getWorldPath(LevelResource.PLAYER_STATS_DIR).toFile()
val uuidFile = File(directory, "$uuid.json")
if (!uuidFile.exists()) {
val playerNameFile = File(directory, "$name.json")
val path = playerNameFile.toPath()
if (FileUtil.isPathNormalized(path) && FileUtil.isPathPortable(path) && path.startsWith(directory.path) && playerNameFile.isFile) {
playerNameFile.renameTo(uuidFile);
}
}

statsCounter = ServerStatsCounter(this.server, uuidFile)
stats[uuid] = statsCounter
}

return statsCounter!!
}
39 changes: 0 additions & 39 deletions src/main/kotlin/one/devos/nautical/template/TemplateMod.kt

This file was deleted.

This file was deleted.

Loading

1 comment on commit d49f2e8

@asoji
Copy link
Member Author

@asoji asoji commented on d49f2e8 Oct 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

my computer was dying so hard while pushing this help @BluSpring @Deftu

Please sign in to comment.