Skip to content
This repository was archived by the owner on Dec 10, 2025. It is now read-only.

Commit 88f7163

Browse files
committed
refactor: Migrate CloudPlayer persistence & update player data protocols
This commit overhauls the player persistence and network data handling layers by: • Removing legacy JPA-based implementations: - Deleted JPA entities, repositories, and services (e.g. CloudPlayerEntity, CloudPlayerNameHistoryEntity, CloudPlayerRepository, CloudPlayerService in the JPA flavor) along with outdated test files. • Introducing an Exposed DAO persistence layer: - Added new Exposed-based CloudPlayerEntity and CloudPlayerNameHistoryEntity classes and their corresponding tables. - Created new CloudPlayerTables (and migration script V1__Add_cloud_player_tables.sql) to support the updated data schema. - Implemented a new CloudPlayerService using Exposed DAO and adjusted DAO service methods for player lookup, creation, and updates. • Updating player management and data retrieval: - Modified StandaloneCloudPlayerImpl to store player name and IP address; its methods now delegate to the new Exposed service. - Enhanced OfflineCloudPlayerImpl to request updated player metadata (latest IP, last server, display name, name history, etc.) using newly defined netty request/response packets. - Added new serverbound data packets (ServerboundRequestPlayerDataPacket/DataRequestType and ServerboundRequestPlayerDataResponse) for handling various player data queries. • Refining Netty protocol and network configuration: - Updated netty listener pipelines to use a configurable logging level (based on cloud configuration). - Adjusted packet registration and handling to integrate the new request/response flows. • Build and configuration improvements: - Upgraded the Exposed dependency to version 0.60.0. - Added necessary dependencies (Flyway, MySQL Connector, Spring Instrument) and updated Gradle build files. - Introduced additional Spring configuration classes (AdditionalStandaloneConfiguration, PluginDatabaseConfig) to streamline the standalone module setup. This migration from JPA to an Exposed-based persistence model simplifies database interactions and unifies player data retrieval through standardized netty protocols. It also improves clarity and consistency in the overall player management codebase.
1 parent 055792e commit 88f7163

File tree

71 files changed

+2009
-544
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+2009
-544
lines changed

.idea/dataSources.xml

Lines changed: 0 additions & 30 deletions
This file was deleted.

build.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@ buildscript {
1313

1414
plugins {
1515
id("org.jetbrains.kotlinx.binary-compatibility-validator") version "0.17.0"
16+
id("io.freefair.aspectj.post-compile-weaving") version "8.13.1"
1617
java
1718
}
1819

1920
allprojects {
2021
apply(plugin = "java")
22+
apply(plugin = "io.freefair.aspectj.post-compile-weaving")
2123
group = "dev.slne.surf.cloud"
2224
version = findProperty("version") as String
2325

gradle/libs.versions.toml

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ netty = "4.1.117.Final"
55
nbt = "6.1"
66
datafixerupper = "8.0.16"
77
byte-buddy = "1.15.10"
8-
exposed = "0.59.0"
8+
exposed = "0.60.0"
99
maven-impl = "4.0.0-rc-2"
1010
maven-resolver = "2.0.5"
1111
jline = "3.26.3"
@@ -53,6 +53,7 @@ aspectjrt = { module = "org.aspectj:aspectjrt" }
5353
zstd-jni = { module = "com.github.luben:zstd-jni", version.ref = "zstd-jni" }
5454
luckperms-api = { module = "net.luckperms:api", version.ref = "luckperms-api" }
5555
mariadb-java-client = { module = "org.mariadb.jdbc:mariadb-java-client" }
56+
mysql-connector-j = { module = "com.mysql:mysql-connector-j" }
5657
spring-boot-starter-data-jpa = { module = "org.springframework.boot:spring-boot-starter-data-jpa" }
5758
reactive-streams = { module = "org.reactivestreams:reactive-streams", version.ref = "reactive-streams" }
5859
hibernate-jcache = { module = "org.hibernate.orm:hibernate-jcache" }
@@ -61,6 +62,9 @@ ktor-server-status-pages = { module = "io.ktor:ktor-server-status-pages" }
6162
spring-boot-starter-log4j2 = { module = "org.springframework.boot:spring-boot-starter-log4j2" }
6263
spring-aop = { module = "org.springframework:spring-aop" }
6364
spring-aspects = { module = "org.springframework:spring-aspects" }
65+
flyway-core = { module = "org.flywaydb:flyway-core" }
66+
flyway-mysql = { module = "org.flywaydb:flyway-mysql" }
67+
spring-instrument = { module = "org.springframework:spring-instrument" }
6468

6569

6670
[plugins]
@@ -73,4 +77,5 @@ jackson-api-common = ["jackson-core", "jackson-databind", "jackson-module-kotlin
7377
exposed-api-server = ["exposed-spring-boot-starter", "exposed-java-time"]
7478
maven-libraries = ["maven-impl", "maven-resolver"]
7579
console-api = ["jline", "brigadier", "terminalconsoleappender"]
76-
ktor-api-server = ["ktor-server-core-jvm", "ktor-server-netty", "ktor-server-core", "ktor-server-html-builder", "kotlin-css", "ktor-server-websockets", "ktor-serialization-kotlinx-json"]
80+
ktor-api-server = ["ktor-server-core-jvm", "ktor-server-netty", "ktor-server-core", "ktor-server-html-builder", "kotlin-css", "ktor-server-websockets", "ktor-serialization-kotlinx-json"]
81+
flyway = ["flyway-core", "flyway-mysql"]

surf-cloud-api/surf-cloud-api-common/build.gradle.kts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import org.gradle.internal.impldep.org.bouncycastle.asn1.x500.style.RFC4519Style.l
2-
31
plugins {
42
id("dev.slne.surf.surfapi.gradle.core")
53
}
Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
11
package dev.slne.surf.cloud.api.common
22

3+
import org.springframework.boot.autoconfigure.AutoConfigurationPackage
34
import org.springframework.boot.autoconfigure.SpringBootApplication
4-
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass
5-
import org.springframework.boot.autoconfigure.data.redis.RedisRepositoriesAutoConfiguration
65
import org.springframework.boot.autoconfigure.domain.EntityScan
7-
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
86
import org.springframework.cache.annotation.EnableCaching
97
import org.springframework.context.annotation.AdviceMode
8+
import org.springframework.context.annotation.Bean
9+
import org.springframework.context.annotation.Configuration
1010
import org.springframework.context.annotation.EnableAspectJAutoProxy
11+
import org.springframework.context.annotation.EnableLoadTimeWeaving
1112
import org.springframework.context.annotation.Import
13+
import org.springframework.context.annotation.Primary
1214
import org.springframework.context.annotation.Profile
13-
import org.springframework.data.jpa.repository.config.EnableJpaAuditing
15+
import org.springframework.jdbc.datasource.DataSourceTransactionManager
1416
import org.springframework.scheduling.annotation.EnableAsync
1517
import org.springframework.scheduling.annotation.EnableScheduling
18+
import org.springframework.transaction.PlatformTransactionManager
1619
import org.springframework.transaction.annotation.EnableTransactionManagement
20+
import org.springframework.transaction.aspectj.AnnotationTransactionAspect
21+
import javax.sql.DataSource
22+
1723

1824
/**
1925
* Annotation for defining Surf Cloud applications with specific configurations.
@@ -23,20 +29,11 @@ import org.springframework.transaction.annotation.EnableTransactionManagement
2329
*/
2430
@Target(AnnotationTarget.CLASS)
2531
@Retention(AnnotationRetention.RUNTIME)
26-
@SpringBootApplication(
27-
exclude = [DataSourceAutoConfiguration::class, RedisRepositoriesAutoConfiguration::class]
28-
)
32+
@SpringBootApplication
2933
@EnableScheduling
30-
@EnableAsync(mode = AdviceMode.ASPECTJ)
31-
@EnableTransactionManagement(mode = AdviceMode.ASPECTJ)
34+
@EnableAsync
3235
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
3336
@EntityScan
34-
//@EnableRedisRepositories
35-
@EnableCaching(mode = AdviceMode.ASPECTJ)
36-
@Import(JpaAuditingConfiguration::class)
37+
@EnableCaching
38+
@AutoConfigurationPackage
3739
annotation class SurfCloudApplication
38-
39-
@EnableJpaAuditing
40-
@ConditionalOnClass(name = ["org.springframework.beans.factory.aspectj.AnnotationBeanConfigurerAspect"])
41-
@Profile("server")
42-
class JpaAuditingConfiguration

surf-cloud-api/surf-cloud-api-common/src/main/kotlin/dev/slne/surf/cloud/api/common/config/properties/CloudProperties.kt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package dev.slne.surf.cloud.api.common.config.properties
22

3-
43
/**
54
* Contains predefined cloud properties for Surf Cloud applications.
65
*/
@@ -9,7 +8,7 @@ object CloudProperties {
98
/**
109
* Default value indicating that the server category is not set.
1110
*/
12-
private const val SERVER_CATEGORY_NOT_SET = "NOT_SET"
11+
const val SERVER_CATEGORY_NOT_SET = "NOT_SET"
1312

1413
/**
1514
* System property for the server category. Defaults to [SERVER_CATEGORY_NOT_SET].

surf-cloud-api/surf-cloud-api-common/src/main/kotlin/dev/slne/surf/cloud/api/common/meta/SurfNettyPacketHandler.kt

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
package dev.slne.surf.cloud.api.common.meta
22

3+
import org.springframework.aot.hint.annotation.Reflective
4+
import org.springframework.core.annotation.AliasFor
5+
import kotlin.reflect.KClass
6+
37
/**
48
* Annotation for marking methods in a component as packet handlers.
59
*/
@@ -11,4 +15,10 @@ package dev.slne.surf.cloud.api.common.meta
1115
@Retention(
1216
AnnotationRetention.RUNTIME
1317
)
14-
annotation class SurfNettyPacketHandler
18+
@Reflective
19+
annotation class SurfNettyPacketHandler(
20+
@get:AliasFor("classes") val value: Array<KClass<*>> = [],
21+
@get:AliasFor("values") val classes: Array<KClass<*>> = [],
22+
val condition: String = "",
23+
val id: String = ""
24+
)

surf-cloud-api/surf-cloud-api-common/src/main/kotlin/dev/slne/surf/cloud/api/common/netty/protocol/buffer/SurfByteBuf.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import dev.slne.surf.cloud.api.common.netty.protocol.buffer.types.VarLong
1717
import dev.slne.surf.cloud.api.common.util.codec.ExtraCodecs
1818
import dev.slne.surf.cloud.api.common.util.createUnresolvedInetSocketAddress
1919
import dev.slne.surf.cloud.api.common.util.fromJson
20+
import dev.slne.surf.surfapi.core.api.util.getCallerClass
2021
import io.netty.buffer.ByteBuf
2122
import io.netty.handler.codec.DecoderException
2223
import io.netty.handler.codec.EncoderException
@@ -631,12 +632,12 @@ open class SurfByteBuf(source: ByteBuf) : WrappedByteBuf(source) {
631632
fun <B : ByteBuf> readCompoundTag(buf: B) = ExtraCodecs.COMPOUND_TAG_CODEC.decode(buf)
632633

633634
fun <B: ByteBuf> writeZonedDateTime(buf: B, time: ZonedDateTime) {
634-
writeVarLong(buf, time.toInstant().toEpochMilli())
635+
buf.writeLong(time.toInstant().toEpochMilli())
635636
writeUtf(buf, time.zone.id)
636637
}
637638

638639
fun <B: ByteBuf> readZonedDateTime(buf: B): ZonedDateTime {
639-
val epoch = readVarLong(buf)
640+
val epoch = buf.readLong()
640641
val zone = readUtf(buf)
641642
return ZonedDateTime.ofInstant(Instant.ofEpochMilli(epoch), ZoneId.of(zone))
642643
}
@@ -655,9 +656,9 @@ open class SurfByteBuf(source: ByteBuf) : WrappedByteBuf(source) {
655656
writeUtf(buf, singleton::class.qualifiedName!!)
656657
}
657658

658-
fun <B : ByteBuf> readSingleton(buf: B): Any {
659+
fun <B : ByteBuf> readSingleton(buf: B, classLoader: ClassLoader): Any {
659660
val className = readUtf(buf)
660-
return Class.forName(className).kotlin.objectInstance
661+
return Class.forName(className, true, classLoader).kotlin.objectInstance
661662
?: throw DecoderException("Failed to read singleton: $className")
662663
}
663664
}
@@ -834,7 +835,7 @@ open class SurfByteBuf(source: ByteBuf) : WrappedByteBuf(source) {
834835
fun writeInet4Address(address: Inet4Address) = writeInet4Address(this, address)
835836
fun readInet4Address() = readInet4Address(this)
836837
fun writeSingleton(singleton: Any) = writeSingleton(this, singleton)
837-
fun readSingleton() = readSingleton(this)
838+
fun readSingleton(classLoader: ClassLoader) = readSingleton(this, classLoader)
838839
// @formatter:on
839840
// endregion
840841

@@ -1064,7 +1065,7 @@ fun <B : ByteBuf> B.writeZonedDateTime(time: ZonedDateTime) = SurfByteBuf.writeZ
10641065
fun <B : ByteBuf> B.readInet4Address() = SurfByteBuf.readInet4Address(this)
10651066
fun <B : ByteBuf> B.writeInet4Address(address: Inet4Address) = SurfByteBuf.writeInet4Address(this, address)
10661067

1067-
fun <B : ByteBuf> B.readSingleton() = SurfByteBuf.readSingleton(this)
1068+
fun <B : ByteBuf> B.readSingleton(classLoader: ClassLoader) = SurfByteBuf.readSingleton(this, classLoader)
10681069
fun <B : ByteBuf> B.writeSingleton(singleton: Any) = SurfByteBuf.writeSingleton(this, singleton)
10691070

10701071
fun ByteBuf.wrap() = SurfByteBuf(this)

surf-cloud-api/surf-cloud-api-common/src/main/kotlin/dev/slne/surf/cloud/api/common/player/CloudPlayer.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import dev.slne.surf.cloud.api.common.player.teleport.TeleportLocation
77
import dev.slne.surf.cloud.api.common.server.CloudServer
88
import net.kyori.adventure.audience.Audience
99
import net.kyori.adventure.text.Component
10-
import java.net.InetAddress
10+
import java.net.Inet4Address
1111
import java.util.*
1212

1313
/**
@@ -18,7 +18,7 @@ import java.util.*
1818
* it enables sending messages or components to the player.
1919
*/
2020
interface CloudPlayer : Audience, OfflineCloudPlayer { // TODO: conversation but done correctly?
21-
override suspend fun latestIpAddress(): InetAddress
21+
override suspend fun latestIpAddress(): Inet4Address
2222
override suspend fun lastServerRaw(): String
2323

2424
/**
@@ -142,6 +142,7 @@ interface CloudPlayer : Audience, OfflineCloudPlayer { // TODO: conversation but
142142
) = teleport(TeleportLocation(world, x, y, z, yaw, pitch), teleportCause, *flags)
143143

144144
override suspend fun displayName(): Component
145+
override suspend fun name(): String
145146
}
146147

147148
/**

surf-cloud-api/surf-cloud-api-common/src/main/kotlin/dev/slne/surf/cloud/api/common/player/CloudPlayerManager.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
package dev.slne.surf.cloud.api.common.player
22

3+
import dev.slne.surf.cloud.api.common.server.UserList
34
import dev.slne.surf.cloud.api.common.util.annotation.InternalApi
45
import dev.slne.surf.surfapi.core.api.util.requiredService
6+
import it.unimi.dsi.fastutil.objects.ObjectSet
57
import net.kyori.adventure.audience.Audience
68
import net.kyori.adventure.identity.Identity
79
import org.jetbrains.annotations.ApiStatus
@@ -27,6 +29,8 @@ interface CloudPlayerManager {
2729

2830
fun getOfflinePlayer(uuid: UUID): OfflineCloudPlayer
2931

32+
fun getOnlinePlayers(): UserList
33+
3034
companion object : CloudPlayerManager by INSTANCE {
3135
@InternalApi
3236
val instance = INSTANCE

0 commit comments

Comments
 (0)