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

Commit a0bfe11

Browse files
committed
feat: implement deep copy for CompoundBinaryTag in node-based approach
- Added a non-recursive `deepCopy` method to safely handle deeply nested `CompoundBinaryTag` structures. - Updated `snapshot` to utilize the new deep copy logic for better reliability and stack safety.
1 parent 2bcffc7 commit a0bfe11

File tree

1 file changed

+83
-1
lines changed

1 file changed

+83
-1
lines changed

surf-cloud-core/surf-cloud-core-common/src/main/kotlin/dev/slne/surf/cloud/core/common/player/ppdc/PersistentPlayerDataContainerViewImpl.kt

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ import dev.slne.surf.cloud.api.common.player.ppdc.PersistentPlayerDataAdapterCon
55
import dev.slne.surf.cloud.api.common.player.ppdc.PersistentPlayerDataContainerView
66
import dev.slne.surf.cloud.api.common.player.ppdc.PersistentPlayerDataType
77
import dev.slne.surf.cloud.api.common.util.toObjectSet
8+
import it.unimi.dsi.fastutil.objects.ObjectArrayList
89
import it.unimi.dsi.fastutil.objects.ObjectSet
910
import net.kyori.adventure.key.Key
1011
import net.kyori.adventure.nbt.*
1112
import org.jetbrains.annotations.Unmodifiable
13+
import java.util.*
1214

1315
abstract class PersistentPlayerDataContainerViewImpl : PersistentPlayerDataContainerView {
1416

@@ -112,8 +114,11 @@ abstract class PersistentPlayerDataContainerViewImpl : PersistentPlayerDataConta
112114
}
113115

114116
override fun snapshot(): PersistentPlayerDataContainerViewImpl {
117+
val tag = deepCopy(toTagCompound())
118+
119+
115120
val tagCopy = CompoundBinaryTag.builder() // TODO: deep copy
116-
.put(toTagCompound())
121+
.put(tag)
117122
.build()
118123

119124
return object : PersistentPlayerDataContainerViewImpl() {
@@ -122,4 +127,81 @@ abstract class PersistentPlayerDataContainerViewImpl : PersistentPlayerDataConta
122127
}
123128
}
124129

130+
131+
/**
132+
* Creates a deep copy of the provided `CompoundBinaryTag` without using recursion.
133+
*
134+
* This function iterates through the tree structure of the `CompoundBinaryTag` in a non-recursive manner
135+
* to build a complete copy. It avoids stack overflow issues that can occur with deeply nested structures
136+
* when using a recursive approach.
137+
*
138+
* @param root The root `CompoundBinaryTag` to be deep copied.
139+
* @return A deep copy of the specified `CompoundBinaryTag`.
140+
*/
141+
private fun deepCopy(root: CompoundBinaryTag): CompoundBinaryTag {
142+
data class Frame(
143+
val entries: List<Pair<String, BinaryTag>>,
144+
var idx: Int,
145+
val builder: CompoundBinaryTag.Builder,
146+
val parent: Frame?,
147+
val parentKey: String?
148+
)
149+
150+
fun entriesOf(tag: CompoundBinaryTag): List<Pair<String, BinaryTag>> {
151+
val list = ObjectArrayList<Pair<String, BinaryTag>>(tag.size())
152+
tag.forEach { (k, v) -> list.add(k to v) }
153+
return list
154+
}
155+
156+
val stack = ArrayDeque<Frame>()
157+
stack.addLast(
158+
Frame(
159+
entries = entriesOf(root),
160+
idx = 0,
161+
builder = CompoundBinaryTag.builder(),
162+
parent = null,
163+
parentKey = null
164+
)
165+
)
166+
167+
var result: CompoundBinaryTag? = null
168+
169+
while (stack.isNotEmpty()) {
170+
val top = stack.removeLast()
171+
172+
while (top.idx < top.entries.size) {
173+
val (key, value) = top.entries[top.idx++]
174+
175+
if (value is CompoundBinaryTag) {
176+
stack.addLast(top)
177+
stack.addLast(
178+
Frame(
179+
entries = entriesOf(value),
180+
idx = 0,
181+
builder = CompoundBinaryTag.builder(),
182+
parent = top,
183+
parentKey = key
184+
)
185+
)
186+
187+
break
188+
} else {
189+
top.builder.put(key, value)
190+
}
191+
}
192+
193+
194+
if (top.idx >= top.entries.size) {
195+
val built = top.builder.build()
196+
if (top.parent == null) {
197+
result = built
198+
} else {
199+
val parent = top.parent
200+
parent.builder.put(requireNotNull(top.parentKey), built)
201+
}
202+
}
203+
}
204+
205+
return requireNotNull(result)
206+
}
125207
}

0 commit comments

Comments
 (0)