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

Commit 78a5e14

Browse files
committed
feat: introduce support for creating OfflineCloudPlayer if not exists via packet handling and CloudPlayerManager modifications
1 parent 7acc5ff commit 78a5e14

File tree

13 files changed

+95
-25
lines changed

13 files changed

+95
-25
lines changed

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

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ interface CloudPlayerManager {
2828

2929
fun getPlayer(name: String): CloudPlayer?
3030

31-
fun getOfflinePlayer(uuid: UUID): OfflineCloudPlayer
31+
fun getOfflinePlayer(uuid: UUID, createIfNotExists: Boolean = true): OfflineCloudPlayer
3232

3333
fun getOnlinePlayers(): UserList
3434

@@ -59,19 +59,19 @@ fun Audience?.toCloudPlayer(): CloudPlayer? {
5959
* or `null` if the [Audience] is not a player or cannot be resolved.
6060
*/
6161
@JvmName("toOfflineCloudPlayerNullable")
62-
fun Audience?.toOfflineCloudPlayer(): OfflineCloudPlayer? = this?.toOfflineCloudPlayer()
62+
fun Audience?.toOfflineCloudPlayer(createIfNotExists: Boolean = true): OfflineCloudPlayer? = this?.toOfflineCloudPlayer(createIfNotExists)
6363

64-
fun Audience.toOfflineCloudPlayer(): OfflineCloudPlayer? {
64+
fun Audience.toOfflineCloudPlayer(createIfNotExists: Boolean = true): OfflineCloudPlayer? {
6565
return this.pointers().get(Identity.UUID).getOrNull()
66-
?.let { CloudPlayerManager.getOfflinePlayer(it) }
66+
?.let { CloudPlayerManager.getOfflinePlayer(it, createIfNotExists) }
6767
}
6868

69-
fun UUID.toOfflineCloudPlayer(): OfflineCloudPlayer =
70-
CloudPlayerManager.getOfflinePlayer(this)
69+
fun UUID.toOfflineCloudPlayer(createIfNotExists: Boolean = true): OfflineCloudPlayer =
70+
CloudPlayerManager.getOfflinePlayer(this, createIfNotExists)
7171

7272
@JvmName("toOfflineCloudPlayerNullable")
73-
fun UUID?.toOfflineCloudPlayer(): OfflineCloudPlayer? =
74-
this?.let { CloudPlayerManager.getOfflinePlayer(it) }
73+
fun UUID?.toOfflineCloudPlayer(createIfNotExists: Boolean = true): OfflineCloudPlayer? =
74+
this?.let { CloudPlayerManager.getOfflinePlayer(it, createIfNotExists) }
7575

7676
fun UUID.toCloudPlayer(): CloudPlayer? =
7777
CloudPlayerManager.getPlayer(this)

surf-cloud-core/surf-cloud-core-client/src/main/kotlin/dev/slne/surf/cloud/core/client/player/ClientCloudPlayerImpl.kt

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,11 @@ import kotlin.time.Duration
4949
import kotlin.time.Duration.Companion.days
5050
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.ServerboundRequestPlayerDataResponse.NameHistory as NameHistoryResponse
5151

52-
abstract class ClientCloudPlayerImpl<PlatformPlayer : Audience>(uuid: UUID, name: String) :
53-
CommonCloudPlayerImpl(uuid, name) {
52+
abstract class ClientCloudPlayerImpl<PlatformPlayer : Audience>(
53+
uuid: UUID,
54+
name: String,
55+
private val createIfNotExists: Boolean
56+
) : CommonCloudPlayerImpl(uuid, name) {
5457
@Volatile
5558
var proxyServerUid: Long? = null
5659

@@ -60,7 +63,6 @@ abstract class ClientCloudPlayerImpl<PlatformPlayer : Audience>(uuid: UUID, name
6063
var afk: Boolean by AtomicBoolean()
6164

6265
override val connectedToProxy get() = proxyServerUid != null
63-
6466
override val connectedToServer get() = serverUid != null
6567

6668
/**
@@ -71,6 +73,12 @@ abstract class ClientCloudPlayerImpl<PlatformPlayer : Audience>(uuid: UUID, name
7173

7274
protected abstract val platformClass: Class<PlatformPlayer>
7375

76+
init {
77+
if (createIfNotExists && player == null) {
78+
ServerboundCreateOfflineCloudPlayerIfNotExistsPacket(uuid).fireAndForget()
79+
}
80+
}
81+
7482
override suspend fun latestIpAddress(): Inet4Address {
7583
return request<IpAddress>(DataRequestType.LATEST_IP_ADDRESS).ip
7684
?: error("Failed to get IP address")
@@ -129,7 +137,7 @@ abstract class ClientCloudPlayerImpl<PlatformPlayer : Audience>(uuid: UUID, name
129137
ServerboundPlayerPersistentDataContainerUpdatePacket(
130138
uuid,
131139
response.verificationId,
132-
container.toTagCompound()
140+
container.toTagCompound()
133141
).fireAndForget()
134142

135143
return result

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/coroutines/scopes.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ object NameHistoryScope : BaseScope(
118118
)
119119

120120
object PlayerDatabaseScope : BaseScope(
121-
dispatcher = newSingleThreadContext("player-database-thread"),
121+
dispatcher = Dispatchers.IO,
122122
name = "player-database"
123123
)
124124

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/netty/network/ConnectionImpl.kt

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,10 @@ class ConnectionImpl(
275275
}
276276

277277
is ServerPreRunningPacketListener -> when (msg) {
278-
is ServerboundProceedToSynchronizingAcknowledgedPacket -> listener.handleReadyToRun(msg)
278+
is ServerboundProceedToSynchronizingAcknowledgedPacket -> listener.handleReadyToRun(
279+
msg
280+
)
281+
279282
is ServerboundPreRunningAcknowledgedPacket -> listener.handlePreRunningAcknowledged(
280283
msg
281284
)
@@ -287,9 +290,15 @@ class ConnectionImpl(
287290

288291
is ServerSynchronizingPacketListener -> when (msg) {
289292
is FinishSynchronizingPacket -> listener.handleFinishSynchronizing(msg)
290-
is ServerboundSynchronizeFinishAcknowledgedPacket -> listener.handleSynchronizeFinishAcknowledged(msg)
293+
is ServerboundSynchronizeFinishAcknowledgedPacket -> listener.handleSynchronizeFinishAcknowledged(
294+
msg
295+
)
296+
291297
is SyncValueChangePacket -> listener.handleSyncValueChange(msg)
292298
is SyncSetDeltaPacket -> listener.handleSyncSetDelta(msg)
299+
is ServerboundCreateOfflineCloudPlayerIfNotExistsPacket -> listener.handleCreateOfflineCloudPlayerIfNotExists(
300+
msg
301+
)
293302

294303
else -> listener.handlePacket(msg)
295304
}
@@ -409,8 +418,12 @@ class ConnectionImpl(
409418
is RequestPlayerPermissionPacket -> listener.handleRequestPlayerPermission(
410419
msg
411420
)
421+
412422
is SyncValueChangePacket -> listener.handleSyncValueChange(msg)
413423
is SyncSetDeltaPacket -> listener.handleSyncSetDelta(msg)
424+
is ServerboundCreateOfflineCloudPlayerIfNotExistsPacket -> listener.handleCreateOfflineCloudPlayerIfNotExists(
425+
msg
426+
)
414427

415428
else -> listener.handlePacket(msg) // handle other packets
416429
}
@@ -450,19 +463,26 @@ class ConnectionImpl(
450463
msg
451464
)
452465

453-
is ClientboundProceedToSynchronizingPacket -> listener.handleProceedToSynchronizing(msg)
466+
is ClientboundProceedToSynchronizingPacket -> listener.handleProceedToSynchronizing(
467+
msg
468+
)
454469

455470
else -> error("Unexpected packet $msg")
456471
}
457472

458473
is ClientSynchronizingPacketListener -> when (msg) {
459-
is ClientboundSynchronizeFinishPacket -> listener.handleSynchronizeFinish(msg)
474+
is ClientboundSynchronizeFinishPacket -> listener.handleSynchronizeFinish(
475+
msg
476+
)
477+
460478
is SyncValueChangePacket -> listener.handleSyncValueChange(msg)
461479
is ClientboundBatchSyncValuePacket -> listener.handleBatchSyncValue(msg)
462480
is ClientboundBatchSyncSetPacket -> listener.handleBatchSyncSet(msg)
463481
is ClientboundBatchUpdateServer -> listener.handleBatchUpdateServer(msg)
464482
is SyncSetDeltaPacket -> listener.handleSyncSetDelta(msg)
465-
is ClientboundSetVelocitySecretPacket -> listener.handleSetVelocitySecret(msg)
483+
is ClientboundSetVelocitySecretPacket -> listener.handleSetVelocitySecret(
484+
msg
485+
)
466486

467487
else -> listener.handlePacket(msg)
468488
}
@@ -565,9 +585,12 @@ class ConnectionImpl(
565585
is RequestPlayerPermissionPacket -> listener.handleRequestPlayerPermission(
566586
msg
567587
)
588+
568589
is SyncValueChangePacket -> listener.handleSyncValueChange(msg)
569590
is SyncSetDeltaPacket -> listener.handleSyncSetDelta(msg)
570-
is ClientboundSetVelocitySecretPacket -> listener.handleSetVelocitySecret(msg)
591+
is ClientboundSetVelocitySecretPacket -> listener.handleSetVelocitySecret(
592+
msg
593+
)
571594

572595
else -> listener.handlePacket(msg)
573596
}

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/netty/network/protocol/running/RunningProtocols.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ object RunningProtocols {
138138
.addPacket(ServerboundQueuePlayerToGroupPacket::class.createCodec())
139139
.addPacket(SyncValueChangePacket.STREAM_CODEC)
140140
.addPacket(SyncSetDeltaPacket.STREAM_CODEC)
141+
.addPacket(ServerboundCreateOfflineCloudPlayerIfNotExistsPacket::class.createCodec())
141142
}
142143

143144
val SERVERBOUND by lazy { SERVERBOUND_TEMPLATE.freeze().bind(::SurfByteBuf) }

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/netty/network/protocol/running/RunningServerPacketListener.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,5 +108,7 @@ interface RunningServerPacketListener : ServerCommonPacketListener, TickablePack
108108

109109
fun handleSyncSetDelta(packet: SyncSetDeltaPacket)
110110

111+
fun handleCreateOfflineCloudPlayerIfNotExists(packet: ServerboundCreateOfflineCloudPlayerIfNotExistsPacket)
112+
111113
fun handlePacket(packet: NettyPacket)
112114
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package dev.slne.surf.cloud.core.common.netty.network.protocol.running
2+
3+
import dev.slne.surf.cloud.api.common.meta.SurfNettyPacket
4+
import dev.slne.surf.cloud.api.common.netty.network.protocol.PacketFlow
5+
import dev.slne.surf.cloud.api.common.netty.packet.NettyPacket
6+
import kotlinx.serialization.Contextual
7+
import kotlinx.serialization.Serializable
8+
import java.util.*
9+
10+
@SurfNettyPacket("cloud:clientbound:create_offline_cloud_player_if_not_exists", PacketFlow.SERVERBOUND)
11+
@Serializable
12+
class ServerboundCreateOfflineCloudPlayerIfNotExistsPacket(val uuid: @Contextual UUID): NettyPacket()

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/netty/network/protocol/synchronizing/ServerSynchronizingPacketListener.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package dev.slne.surf.cloud.core.common.netty.network.protocol.synchronizing
33
import dev.slne.surf.cloud.api.common.netty.network.ConnectionProtocol
44
import dev.slne.surf.cloud.api.common.netty.packet.NettyPacket
55
import dev.slne.surf.cloud.core.common.netty.network.protocol.common.ServerCommonPacketListener
6+
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.ServerboundCreateOfflineCloudPlayerIfNotExistsPacket
67
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.SyncSetDeltaPacket
78
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.SyncValueChangePacket
89

@@ -17,5 +18,7 @@ interface ServerSynchronizingPacketListener : ServerCommonPacketListener {
1718

1819
fun handleSyncSetDelta(packet: SyncSetDeltaPacket)
1920

21+
fun handleCreateOfflineCloudPlayerIfNotExists(packet: ServerboundCreateOfflineCloudPlayerIfNotExistsPacket)
22+
2023
fun handlePacket(packet: NettyPacket)
2124
}

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/netty/network/protocol/synchronizing/SynchronizingProtocols.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import dev.slne.surf.cloud.api.common.netty.protocol.buffer.SurfByteBuf
66
import dev.slne.surf.cloud.core.common.netty.network.protocol.ProtocolInfoBuilder
77
import dev.slne.surf.cloud.core.common.netty.network.protocol.common.*
88
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.ClientboundBatchUpdateServer
9+
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.ServerboundCreateOfflineCloudPlayerIfNotExistsPacket
910
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.SyncSetDeltaPacket
1011
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.SyncValueChangePacket
1112

@@ -41,6 +42,7 @@ object SynchronizingProtocols {
4142
.addPacket(SyncValueChangePacket.STREAM_CODEC)
4243
.addPacket(SyncSetDeltaPacket.STREAM_CODEC)
4344
.addPacket(FinishSynchronizingPacket.STREAM_CODEC)
45+
.addPacket(ServerboundCreateOfflineCloudPlayerIfNotExistsPacket::class.createCodec())
4446
}
4547

4648
val SERVERBOUND by lazy { SERVERBOUND_TEMPLATE.bind(::SurfByteBuf) }

surf-cloud-standalone/src/main/kotlin/dev/slne/surf/cloud/standalone/netty/server/network/ServerRunningPacketListenerImpl.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,6 +519,10 @@ class ServerRunningPacketListenerImpl(
519519
}
520520
}
521521

522+
override fun handleCreateOfflineCloudPlayerIfNotExists(packet: ServerboundCreateOfflineCloudPlayerIfNotExistsPacket) {
523+
CloudPlayerManager.getOfflinePlayer(packet.uuid, true)
524+
}
525+
522526
override fun handlePacket(packet: NettyPacket) {
523527
val listeners = NettyListenerRegistry.getListeners(packet.javaClass) ?: return
524528
if (listeners.isEmpty()) return

0 commit comments

Comments
 (0)