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

Commit dbd36fb

Browse files
committed
feat: enhance player data handling with tracking, patches, and bidirectional updates
- Removed `TrackingPlayerPersistentDataContainerImpl` from `standalone` module and consolidated logic in `core`. - Replaced `withPersistentData` with `editPdc` for non-suspending data modification and deprecated the former. - Introduced snapshots in `PersistentPlayerDataContainer` for safe concurrent edits. - Added bidirectional `UpdatePlayerPersistentDataContainerPacket` and streamlined packet handling. - Improved player data synchronization with patch-based updates and lock mechanisms.
1 parent c0a03ba commit dbd36fb

File tree

16 files changed

+222
-96
lines changed

16 files changed

+222
-96
lines changed

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

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,14 @@ interface CloudPlayer : Audience, OfflineCloudPlayer {
6161
/**
6262
* Performs modifications on the player's persistent data container.
6363
*
64-
* @param block A suspending block to modify the persistent data container.
64+
* @param block A block to modify the persistent data container.
6565
* @return The result of the block execution.
6666
*/
67-
suspend fun <R> withPersistentData(block: PersistentPlayerDataContainer.() -> R): R
67+
fun <R> editPdc(block: PersistentPlayerDataContainer.() -> R): R
68+
69+
@Deprecated("Use renamed non-suspendable method", ReplaceWith("editPdc(block)"))
70+
suspend fun <R> withPersistentData(block: PersistentPlayerDataContainer.() -> R): R =
71+
editPdc(block)
6872

6973
/**
7074
* Connects the player to a specified server.

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,4 +65,6 @@ interface PersistentPlayerDataContainer: PersistentPlayerDataContainerView {
6565
* @param buf The buffer to read from.
6666
*/
6767
fun readFromBuf(buf: SurfByteBuf)
68+
69+
override fun snapshot(): PersistentPlayerDataContainer
6870
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,4 +70,6 @@ interface PersistentPlayerDataContainerView {
7070
* @param buf The buffer to write to.
7171
*/
7272
fun writeToBuf(buf: SurfByteBuf)
73+
74+
fun snapshot(): PersistentPlayerDataContainerView
7375
}

surf-cloud-core/surf-cloud-core-client/src/main/kotlin/dev/slne/surf/cloud/core/client/netty/network/ClientRunningPacketListenerImpl.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,9 @@ class ClientRunningPacketListenerImpl(
209209
}
210210

211211
override suspend fun handleAddPlayerToServer(packet: ClientboundAddPlayerToServerPacket) {
212-
(serverManagerImpl.retrieveServerByName(packet.serverName)?.users as? UserListImpl)?.add(packet.playerUuid)
212+
(serverManagerImpl.retrieveServerByName(packet.serverName)?.users as? UserListImpl)?.add(
213+
packet.playerUuid
214+
)
213215
}
214216

215217
override suspend fun handleRemovePlayerFromServer(packet: ClientboundRemovePlayerFromServerPacket) {
@@ -371,6 +373,11 @@ class ClientRunningPacketListenerImpl(
371373
platformExtension.sendToast(packet.uuid, packet.toast)
372374
}
373375

376+
override fun handleUpdatePlayerPersistentDataContainer(packet: UpdatePlayerPersistentDataContainerPacket) {
377+
val player = commonPlayerManagerImpl.getPlayer(packet.uuid) ?: return
378+
player.applyPpdcPatch(packet.patch)
379+
}
380+
374381
override fun handlePacket(packet: NettyPacket) {
375382
val listeners = NettyListenerRegistry.getListeners(packet.javaClass) ?: return
376383
if (listeners.isEmpty()) return

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

Lines changed: 17 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,14 @@ import dev.slne.surf.cloud.core.common.netty.network.protocol.running.*
2323
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.ServerboundRequestPlayerDataPacket.DataRequestType
2424
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.ServerboundRequestPlayerDataResponse.*
2525
import dev.slne.surf.cloud.core.common.player.CommonCloudPlayerImpl
26-
import dev.slne.surf.cloud.core.common.player.ppdc.PersistentPlayerDataContainerImpl
27-
import dev.slne.surf.cloud.core.common.player.ppdc.PersistentPlayerDataContainerViewImpl
26+
import dev.slne.surf.cloud.core.common.player.ppdc.network.PdcPatch
2827
import dev.slne.surf.cloud.core.common.util.hasPermissionPlattform
2928
import dev.slne.surf.surfapi.core.api.messages.adventure.getPointer
30-
import dev.slne.surf.surfapi.core.api.nbt.FastCompoundBinaryTag
31-
import dev.slne.surf.surfapi.core.api.nbt.fast
3229
import net.kyori.adventure.audience.Audience
3330
import net.kyori.adventure.audience.MessageType
3431
import net.kyori.adventure.bossbar.BossBar
3532
import net.kyori.adventure.identity.Identity
3633
import net.kyori.adventure.inventory.Book
37-
import net.kyori.adventure.nbt.CompoundBinaryTag
3834
import net.kyori.adventure.resource.ResourcePackRequest
3935
import net.kyori.adventure.sound.Sound
4036
import net.kyori.adventure.sound.Sound.Emitter
@@ -49,6 +45,7 @@ import java.net.Inet4Address
4945
import java.time.ZonedDateTime
5046
import java.util.*
5147
import java.util.concurrent.atomic.AtomicBoolean
48+
import kotlin.concurrent.write
5249
import kotlin.time.Duration
5350
import kotlin.time.Duration.Companion.days
5451
import dev.slne.surf.cloud.core.common.netty.network.protocol.running.ServerboundRequestPlayerDataResponse.NameHistory as NameHistoryResponse
@@ -68,11 +65,6 @@ abstract class ClientCloudPlayerImpl<PlatformPlayer : Audience>(
6865
override val connectedToProxy get() = proxyServerName != null
6966
override val connectedToServer get() = serverName != null
7067

71-
var ppdcData: FastCompoundBinaryTag = CompoundBinaryTag.empty().fast()
72-
override val persistentData = object : PersistentPlayerDataContainerViewImpl() {
73-
override fun toTagCompound() = ppdcData
74-
override fun getTag(key: String) = ppdcData.get(key)
75-
}
7668

7769
/**
7870
* The audience for this player. If the player is on this server, this will point to
@@ -82,6 +74,21 @@ abstract class ClientCloudPlayerImpl<PlatformPlayer : Audience>(
8274

8375
protected abstract val platformClass: Class<PlatformPlayer>
8476

77+
fun applyPpdcPatch(patch: PdcPatch) {
78+
ppdcReentrantLock.write {
79+
ppdc.applyOps(ppdc.tag, patch)
80+
}
81+
}
82+
83+
override fun <R> editPdc(block: PersistentPlayerDataContainer.() -> R): R {
84+
val (result, patch) = editPdc0(true, block)
85+
if (!patch.empty) {
86+
UpdatePlayerPersistentDataContainerPacket(uuid, patch).fireAndForget()
87+
}
88+
89+
return result
90+
}
91+
8592
override suspend fun latestIpAddress(): Inet4Address {
8693
return request<IpAddress>(DataRequestType.LATEST_IP_ADDRESS).ip
8794
?: error("Failed to get IP address")
@@ -130,22 +137,6 @@ abstract class ClientCloudPlayerImpl<PlatformPlayer : Audience>(
130137
) == true
131138
}
132139

133-
override suspend fun <R> withPersistentData(block: PersistentPlayerDataContainer.() -> R): R {
134-
val response = ServerboundRequestPlayerPersistentDataContainer(uuid).fireAndAwaitOrThrow()
135-
136-
val nbt = response.nbt
137-
val container = PersistentPlayerDataContainerImpl(nbt.fast(synchronize = true))
138-
val result = container.block()
139-
140-
ServerboundPlayerPersistentDataContainerUpdatePacket(
141-
uuid,
142-
response.verificationId,
143-
container.toTagCompound()
144-
).fireAndForget()
145-
146-
return result
147-
}
148-
149140
override suspend fun displayName(): Component {
150141
val localName = audience?.getPointer(Identity.DISPLAY_NAME)
151142
if (localName != null) {

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,6 +449,9 @@ class ConnectionImpl(
449449
)
450450

451451
is SendToastPacket -> listener.handleSendToast(msg)
452+
is UpdatePlayerPersistentDataContainerPacket -> listener.handleUpdatePlayerPersistentDataContainer(
453+
msg
454+
)
452455

453456
else -> listener.handlePacket(msg) // handle other packets
454457
}
@@ -629,6 +632,9 @@ class ConnectionImpl(
629632
is ClientboundCacheDeltaPacket -> listener.handleCacheDelta(msg)
630633
is ClientboundCacheErrorPacket -> listener.handleCacheError(msg)
631634
is SendToastPacket -> listener.handleSendToast(msg)
635+
is UpdatePlayerPersistentDataContainerPacket -> listener.handleUpdatePlayerPersistentDataContainer(
636+
msg
637+
)
632638

633639
else -> listener.handlePacket(msg)
634640
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,5 +97,7 @@ interface RunningClientPacketListener : ClientCommonPacketListener {
9797

9898
fun handleSendToast(packet: SendToastPacket)
9999

100+
fun handleUpdatePlayerPersistentDataContainer(packet: UpdatePlayerPersistentDataContainerPacket)
101+
100102
fun handlePacket(packet: NettyPacket)
101103
}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ object RunningProtocols {
7272
.addPacket(WhitelistStatusResponsePacket::class.createCodec())
7373
.addPacket(WhitelistResponsePacket::class.createCodec())
7474
.addPacket(SendToastPacket.STREAM_CODEC)
75+
.addPacket(UpdatePlayerPersistentDataContainerPacket.STREAM_CODEC)
7576
}
7677

7778
val CLIENTBOUND by lazy { CLIENTBOUND_TEMPLATE.freeze().bind(::SurfByteBuf) }
@@ -150,6 +151,7 @@ object RunningProtocols {
150151
.addPacket(ServerboundUpdateWhitelistPacket::class.createCodec())
151152
.addPacket(ServerboundRefreshWhitelistPacket.STREAM_CODEC)
152153
.addPacket(SendToastPacket.STREAM_CODEC)
154+
.addPacket(UpdatePlayerPersistentDataContainerPacket.STREAM_CODEC)
153155
}
154156

155157
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
@@ -128,5 +128,7 @@ interface RunningServerPacketListener : ServerCommonPacketListener, TickablePack
128128

129129
fun handleSendToast(packet: SendToastPacket)
130130

131+
fun handleUpdatePlayerPersistentDataContainer(packet: UpdatePlayerPersistentDataContainerPacket)
132+
131133
fun handlePacket(packet: NettyPacket)
132134
}

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/netty/network/protocol/running/ClientboundUpdatePlayerPersistentDataContainerPacket.kt renamed to surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/netty/network/protocol/running/UpdatePlayerPersistentDataContainerPacket.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,24 @@ package dev.slne.surf.cloud.core.common.netty.network.protocol.running
22

33
import dev.slne.surf.cloud.api.common.meta.SurfNettyPacket
44
import dev.slne.surf.cloud.api.common.netty.network.codec.ByteBufCodecs
5-
import dev.slne.surf.cloud.api.common.netty.network.codec.streamCodecComposite
5+
import dev.slne.surf.cloud.api.common.netty.network.codec.StreamCodec
66
import dev.slne.surf.cloud.api.common.netty.network.protocol.PacketFlow
77
import dev.slne.surf.cloud.api.common.netty.packet.NettyPacket
88
import dev.slne.surf.cloud.core.common.player.ppdc.network.PdcPatch
99
import java.util.*
1010

11-
@SurfNettyPacket("cloud:clientbound:player_pdc/update", PacketFlow.CLIENTBOUND)
12-
class ClientboundUpdatePlayerPersistentDataContainerPacket(
11+
@SurfNettyPacket("cloud:bidirectional:player_pdc/update", PacketFlow.BIDIRECTIONAL)
12+
class UpdatePlayerPersistentDataContainerPacket(
1313
val uuid: UUID,
1414
val patch: PdcPatch
1515
) : NettyPacket() {
1616
companion object {
17-
val STREAM_CODEC = streamCodecComposite(
17+
val STREAM_CODEC = StreamCodec.composite(
1818
ByteBufCodecs.UUID_CODEC,
19-
ClientboundUpdatePlayerPersistentDataContainerPacket::uuid,
19+
UpdatePlayerPersistentDataContainerPacket::uuid,
2020
PdcPatch.STREAM_CODEC,
21-
ClientboundUpdatePlayerPersistentDataContainerPacket::patch,
22-
::ClientboundUpdatePlayerPersistentDataContainerPacket
21+
UpdatePlayerPersistentDataContainerPacket::patch,
22+
::UpdatePlayerPersistentDataContainerPacket
2323
)
2424
}
2525
}

0 commit comments

Comments
 (0)