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

Commit 4136747

Browse files
committed
feat: replace static binary tag type management with proxy-based mapping
- Introduced `BinaryTagTypeProxy` to dynamically handle `BinaryTagType` mappings, removing static `TAG_TYPES`. - Replaced static tag type resolution with `ByIdMap.continuous` using the proxy for better flexibility and error handling. - Enhanced `ByIdMap` with additional out-of-bounds strategies, including `DECODE_ERROR` and custom error factories.
1 parent 7c64467 commit 4136747

File tree

3 files changed

+62
-37
lines changed

3 files changed

+62
-37
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package dev.slne.surf.cloud.api.common.internal
2+
3+
import dev.slne.surf.cloud.api.common.util.annotation.InternalApi
4+
import dev.slne.surf.surfapi.core.api.reflection.*
5+
import net.kyori.adventure.nbt.BinaryTag
6+
import net.kyori.adventure.nbt.BinaryTagType
7+
8+
@InternalApi
9+
@SurfProxy(BinaryTagType::class)
10+
internal interface BinaryTagTypeProxy {
11+
12+
@Static
13+
@Field("TYPES", Field.Type.GETTER)
14+
fun getTypes(): List<BinaryTagType<out BinaryTag>>
15+
16+
companion object {
17+
internal val instance = surfReflection.createProxy<BinaryTagTypeProxy>()
18+
}
19+
}

surf-cloud-api/surf-cloud-api-common/src/main/kotlin/dev/slne/surf/cloud/api/common/netty/network/codec/ByteBufCodecs.kt

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package dev.slne.surf.cloud.api.common.netty.network.codec
22

3+
import dev.slne.surf.cloud.api.common.internal.BinaryTagTypeProxy
34
import dev.slne.surf.cloud.api.common.netty.protocol.buffer.*
45
import dev.slne.surf.cloud.api.common.netty.protocol.buffer.types.Utf8String
56
import dev.slne.surf.cloud.api.common.util.ByIdMap
7+
import dev.slne.surf.cloud.api.common.util.ByIdMap.OutOfBoundsStrategy
68
import dev.slne.surf.cloud.api.common.util.createUnresolvedInetSocketAddress
79
import io.netty.buffer.ByteBuf
810
import io.netty.buffer.ByteBufInputStream
@@ -16,7 +18,6 @@ import net.kyori.adventure.key.Key
1618
import net.kyori.adventure.nbt.BinaryTag
1719
import net.kyori.adventure.nbt.BinaryTagIO
1820
import net.kyori.adventure.nbt.BinaryTagType
19-
import net.kyori.adventure.nbt.BinaryTagTypes
2021
import net.kyori.adventure.sound.Sound
2122
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
2223
import java.io.ByteArrayInputStream
@@ -76,7 +77,7 @@ object ByteBufCodecs {
7677
private val SOUND_SOURCE_BY_ID = ByIdMap.continuous(
7778
{ it.ordinal },
7879
Sound.Source.entries.toTypedArray(),
79-
ByIdMap.OutOfBoundsStrategy.ZERO
80+
OutOfBoundsStrategy.ZERO
8081
)
8182
val SOUND_CODEC = streamCodecComposite(
8283
KEY_CODEC,
@@ -155,36 +156,22 @@ object ByteBufCodecs {
155156
BigDecimal(unscaledValue, scale, MathContext(precision))
156157
}
157158

158-
private val TAG_TYPES = arrayOf(
159-
BinaryTagTypes.END,
160-
BinaryTagTypes.BYTE,
161-
BinaryTagTypes.SHORT,
162-
BinaryTagTypes.INT,
163-
BinaryTagTypes.LONG,
164-
BinaryTagTypes.FLOAT,
165-
BinaryTagTypes.DOUBLE,
166-
BinaryTagTypes.BYTE_ARRAY,
167-
BinaryTagTypes.STRING,
168-
BinaryTagTypes.LIST,
169-
BinaryTagTypes.COMPOUND,
170-
BinaryTagTypes.INT_ARRAY,
171-
BinaryTagTypes.LONG_ARRAY,
172-
)
173159

174-
fun getTagType(id: Int): BinaryTagType<*> {
175-
return if (id >= 0 && id < TAG_TYPES.size) TAG_TYPES[id] else error("Unknown tag type id: $id")
176-
}
160+
private val BINARY_TAG_BY_ID = ByIdMap.continuous(
161+
{ it.id().toInt() },
162+
BinaryTagTypeProxy.instance.getTypes().toTypedArray(),
163+
OutOfBoundsStrategy.DECODE_ERROR
164+
)
177165

178166
val BINARY_TAG_CODEC: StreamCodec<ByteBuf, BinaryTag> = streamCodec({ buf, tag ->
179167
val type = tag.type() as BinaryTagType<BinaryTag>
180168
buf.writeByte(type.id().toInt())
181169
DataOutputStream(FastBufferedOutputStream(ByteBufOutputStream(buf))).use {
182170
type.write(tag, it)
183171
}
184-
}, { bytes ->
185-
val typeId = bytes.readByte().toInt()
186-
val type = getTagType(typeId)
187-
DataInputStream(FastBufferedInputStream(ByteBufInputStream(bytes))).use {
172+
}, { buf ->
173+
val type = BINARY_TAG_BY_ID(buf.readByte().toInt())
174+
DataInputStream(FastBufferedInputStream(ByteBufInputStream(buf))).use {
188175
type.read(it)
189176
}
190177
})
@@ -195,11 +182,9 @@ object ByteBufCodecs {
195182
DataOutputStream(FastBufferedOutputStream(GZIPOutputStream(ByteBufOutputStream(buf)))).use {
196183
type.write(tag, it)
197184
}
198-
}, { bytes ->
199-
val typeId = bytes.readByte().toInt()
200-
val type = getTagType(typeId)
201-
202-
DataInputStream(FastBufferedInputStream(GZIPInputStream(ByteBufInputStream(bytes)))).use {
185+
}, { buf ->
186+
val type = BINARY_TAG_BY_ID(buf.readByte().toInt())
187+
DataInputStream(FastBufferedInputStream(GZIPInputStream(ByteBufInputStream(buf)))).use {
203188
type.read(it)
204189
}
205190
})
@@ -275,4 +260,12 @@ object ByteBufCodecs {
275260
fun <B : ByteBuf, V> list(maxSize: Int): CodecOperation<B, V, MutableList<V>> {
276261
return CodecOperation { size -> collection(::ObjectArrayList, size, maxSize) }
277262
}
263+
264+
@Suppress("NOTHING_TO_INLINE")
265+
private inline fun decodeError(message: Any): Nothing =
266+
throw DecoderException(message.toString())
267+
268+
@Suppress("NOTHING_TO_INLINE")
269+
private inline fun encodeError(message: Any): Nothing =
270+
throw EncoderException(message.toString())
278271
}

surf-cloud-api/surf-cloud-api-common/src/main/kotlin/dev/slne/surf/cloud/api/common/util/ByIdMap.kt

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package dev.slne.surf.cloud.api.common.util
22

3+
import dev.slne.surf.cloud.api.common.util.ByIdMap.OutOfBoundsStrategy.*
4+
import io.netty.handler.codec.DecoderException
35
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
46
import org.spongepowered.math.GenericMath
57

@@ -58,36 +60,47 @@ object ByIdMap {
5860
keyExtractor: (T) -> Int,
5961
values: Array<T>,
6062
outOfBoundsStrategy: OutOfBoundsStrategy
61-
): (Int) -> T {
63+
): (id: Int) -> T {
6264
val objects = createSortedArray(keyExtractor, values)
6365
val size = objects.size
6466

6567
return when (outOfBoundsStrategy) {
66-
OutOfBoundsStrategy.ZERO -> {
68+
ZERO -> {
6769
val first = objects[0]
6870
{ key -> if (key >= 0 && key < size) objects[key] else first }
6971
}
7072

71-
OutOfBoundsStrategy.WRAP -> { key ->
73+
WRAP -> { key ->
7274
objects[Math.floorMod(
7375
key,
7476
size
7577
)]
7678
}
7779

78-
OutOfBoundsStrategy.CLAMP -> { key ->
80+
CLAMP -> { key ->
7981
objects[GenericMath.clamp(
8082
key,
8183
0,
8284
size - 1
8385
)]
8486
}
87+
88+
DECODE_ERROR -> { key ->
89+
if (key >= 0 && key < size) objects[key] else throw DecoderException("Invalid key index: $key")
90+
}
91+
92+
is ERROR -> { key ->
93+
if (key in 0..<size) objects[key] else throw outOfBoundsStrategy.errorFactory(key)
94+
}
8595
}
8696
}
8797

88-
enum class OutOfBoundsStrategy {
89-
ZERO,
90-
WRAP,
91-
CLAMP
98+
@Suppress("ClassName")
99+
sealed class OutOfBoundsStrategy {
100+
data object ZERO : OutOfBoundsStrategy()
101+
data object WRAP : OutOfBoundsStrategy()
102+
data object CLAMP : OutOfBoundsStrategy()
103+
data object DECODE_ERROR : OutOfBoundsStrategy()
104+
data class ERROR(val errorFactory: (Int) -> Throwable) : OutOfBoundsStrategy()
92105
}
93106
}

0 commit comments

Comments
 (0)