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

Commit f5dbe9f

Browse files
authored
Merge pull request #107 from SLNE-Development/feat/player-cache
Feat/player cache
2 parents f574cd3 + 1e8433e commit f5dbe9f

File tree

92 files changed

+2660
-278
lines changed

Some content is hidden

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

92 files changed

+2660
-278
lines changed

buildSrc/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ dependencies {
1111
// val kotlinVersion = "2.1.0"
1212
// val dokkaVersion = "2.0.0-Beta"
1313

14-
implementation("org.springframework.boot:org.springframework.boot.gradle.plugin:3.5.3")
14+
implementation("org.springframework.boot:org.springframework.boot.gradle.plugin:3.5.6")
1515
// implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion")
1616
// implementation("org.jetbrains.kotlin:kotlin-allopen:$kotlinVersion")
1717
// implementation("org.jetbrains.kotlin:kotlin-lombok:$kotlinVersion")
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
import java.nio.file.Files
2+
import java.nio.file.StandardOpenOption
3+
4+
val streamCodecPackage = "dev.slne.surf.cloud.api.common.netty.network.codec"
5+
val compositeStartFrom = 2
6+
val compositeMaxArity = 20
7+
8+
val generatedDir = layout.buildDirectory.dir("generated/sources/streamcodec")
9+
10+
plugins {
11+
java
12+
}
13+
14+
val genComposites = tasks.register("generateStreamCodecComposites") {
15+
group = "generate"
16+
17+
outputs.dir(generatedDir)
18+
inputs.property("startFrom", compositeStartFrom)
19+
inputs.property("maxArity", compositeMaxArity)
20+
21+
doLast {
22+
require(compositeMaxArity >= compositeStartFrom) { "maxArity ($compositeMaxArity) must be >= startFrom ($compositeStartFrom)" }
23+
val file = generatedDir.get().file("StreamCodecComposites.kt").asFile
24+
file.parentFile.mkdirs()
25+
val content = buildString {
26+
appendLine("// GENERATED FILE — do not edit manually")
27+
appendLine("package $streamCodecPackage")
28+
appendLine()
29+
appendLine("import java.util.function.Function")
30+
appendLine()
31+
appendLine("@Suppress(\"UNCHECKED_CAST\", \"RedundantVisibilityModifier\")")
32+
appendLine("private object _CompositeGenSupport {")
33+
appendLine(" @JvmStatic inline fun <B, T> dec(c: StreamCodec<in B, T>, buf: B): T = (c as StreamCodec<B, T>).decode(buf)")
34+
appendLine(" @JvmStatic inline fun <B, T> enc(c: StreamCodec<in B, T>, buf: B, v: T) = (c as StreamCodec<B, T>).encode(buf, v)")
35+
appendLine("}")
36+
appendLine()
37+
38+
39+
fun genArity(n: Int) {
40+
val typeParams = (1..n).joinToString(", ") { "T$it" }
41+
val params = buildString {
42+
for (i in 1..n) {
43+
appendLine(" codec$i: StreamCodec<in B, T$i>,")
44+
appendLine(" from$i: Function<C, T$i>,")
45+
}
46+
append(" to: (")
47+
append((1..n).joinToString(", ") { "T$it" })
48+
appendLine(") -> C")
49+
}
50+
val decodeVars = (1..n).joinToString("\n") { i ->
51+
" val o$i: T$i = _CompositeGenSupport.dec(codec$i, buf)"
52+
}
53+
val encodeLines = (1..n).joinToString("\n") { i ->
54+
" _CompositeGenSupport.enc(codec$i, buf, from$i.apply(value))"
55+
}
56+
val toArgs = (1..n).joinToString(", ") { "o$it" }
57+
58+
appendLine("public fun <B, C, $typeParams> StreamCodec.Companion.composite(")
59+
appendLine(params)
60+
appendLine("): StreamCodec<B, C> {")
61+
appendLine(" return object : StreamCodec<B, C> {")
62+
appendLine(" override fun decode(buf: B): C {")
63+
appendLine(decodeVars)
64+
appendLine(" return to($toArgs)")
65+
appendLine(" }")
66+
appendLine()
67+
appendLine(" override fun encode(buf: B, value: C) {")
68+
appendLine(encodeLines)
69+
appendLine(" }")
70+
appendLine(" }")
71+
appendLine("}")
72+
appendLine()
73+
}
74+
75+
for (n in compositeStartFrom..compositeMaxArity) genArity(n)
76+
77+
}
78+
Files.write(
79+
file.toPath(),
80+
content.toByteArray(),
81+
StandardOpenOption.CREATE,
82+
StandardOpenOption.TRUNCATE_EXISTING,
83+
StandardOpenOption.WRITE
84+
)
85+
86+
println("Generated ${file.relativeTo(project.projectDir)} with composite ${compositeStartFrom}..$compositeMaxArity")
87+
}
88+
}
89+
90+
sourceSets {
91+
named("main") {
92+
java.srcDir(generatedDir)
93+
}
94+
}
95+
96+
tasks.named("compileKotlin") {
97+
mustRunAfter(genComposites)
98+
}

gradle/libs.versions.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
[versions]
22
velocity-version = "3.4.0-SNAPSHOT"
33
aide-reflection = "1.3"
4-
netty = "4.2.3.Final"
5-
netty-tcnative = "2.0.72.Final"
4+
netty = "4.2.6.Final"
5+
netty-tcnative = "2.0.74.Final"
66
datafixerupper = "8.0.16"
77
#byte-buddy = "1.15.10"
88
exposed = "0.61.0"
99
maven-impl = "4.0.0-rc-2"
1010
maven-resolver = "2.0.5"
11-
jline = "3.30.4"
11+
jline = "3.30.6"
1212
brigadier = "1.3.10"
1313
terminalconsoleappender = "1.3.0"
1414
bson-kotlinx = "5.4.0"
1515
aspectjweaver = "1.9.22.1"
1616
zstd-jni = "1.5.7-4"
17-
luckperms-api = "5.4"
17+
luckperms-api = "5.5"
1818
reactive-streams = "1.0.4"
1919
ehcache = "3.10.8"
2020
kotlin-byte-buf-serializer = "1.1.0"
21-
voicechat-api = "2.5.27"
21+
voicechat-api = "2.6.0"
2222
discord-webhooks = "1.0"
2323
konf = "1.1.2"
2424

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import dev.slne.surf.surfapi.gradle.util.slneReleases
33
plugins {
44
`exclude-kotlin`
55
id("dev.slne.surf.surfapi.gradle.core")
6+
`generate-stream-codec`
67
}
78

89
dependencies {
@@ -51,4 +52,4 @@ publishing {
5152
repositories {
5253
slneReleases()
5354
}
54-
}
55+
}
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
package dev.slne.surf.cloud.api.common.netty.network.codec
2+
3+
import dev.slne.surf.cloud.api.common.netty.protocol.buffer.*
4+
import dev.slne.surf.cloud.api.common.netty.protocol.buffer.types.Utf8String
5+
import dev.slne.surf.cloud.api.common.util.ByIdMap
6+
import dev.slne.surf.cloud.api.common.util.createUnresolvedInetSocketAddress
7+
import io.netty.buffer.ByteBuf
8+
import net.kyori.adventure.key.Key
9+
import net.kyori.adventure.nbt.BinaryTagIO
10+
import net.kyori.adventure.sound.Sound
11+
import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer
12+
import java.io.ByteArrayInputStream
13+
import java.io.ByteArrayOutputStream
14+
import java.math.BigDecimal
15+
import java.math.BigInteger
16+
import java.math.MathContext
17+
import java.net.Inet4Address
18+
import java.net.InetSocketAddress
19+
import java.net.URI
20+
import java.time.Instant
21+
import java.time.ZoneId
22+
import java.time.ZonedDateTime
23+
import java.util.*
24+
import kotlin.time.Duration
25+
import kotlin.time.Duration.Companion.milliseconds
26+
27+
object ByteBufCodecs {
28+
val BOOLEAN_CODEC = streamCodec(ByteBuf::writeBoolean, ByteBuf::readBoolean)
29+
val BYTE_CODEC = streamCodec({ buf, byte -> buf.writeByte(byte.toInt()) }, ByteBuf::readByte)
30+
val SHORT_CODEC =
31+
streamCodec({ buf, short -> buf.writeShort(short.toInt()) }, ByteBuf::readShort)
32+
33+
val INT_CODEC = streamCodec(ByteBuf::writeInt, ByteBuf::readInt)
34+
val VAR_INT_CODEC = streamCodec(ByteBuf::writeVarInt, ByteBuf::readVarInt)
35+
val FLOAT_CODEC = streamCodec(ByteBuf::writeFloat, ByteBuf::readFloat)
36+
val DOUBLE_CODEC = streamCodec(ByteBuf::writeDouble, ByteBuf::readDouble)
37+
val LONG_CODEC = streamCodec(ByteBuf::writeLong, ByteBuf::readLong)
38+
val VAR_LONG_CODEC = streamCodec(ByteBuf::writeVarLong, ByteBuf::readVarLong)
39+
val STRING_CODEC = Utf8String.STREAM_CODEC
40+
41+
42+
val UUID_CODEC = streamCodec(ByteBuf::writeUuid, ByteBuf::readUuid)
43+
val BYTE_ARRAY_CODEC = streamCodec(ByteBuf::writeByteArray, ByteBuf::readByteArray)
44+
45+
val OPTIONAL_LONG_CODEC = streamCodec<ByteBuf, OptionalLong>({ buf, optionalLong ->
46+
BOOLEAN_CODEC.encode(buf, optionalLong.isPresent)
47+
optionalLong.ifPresent { LONG_CODEC.encode(buf, it) }
48+
}) { buf ->
49+
if (BOOLEAN_CODEC.decode(buf)) {
50+
OptionalLong.of(LONG_CODEC.decode(buf))
51+
} else {
52+
OptionalLong.empty()
53+
}
54+
}
55+
56+
val KEY_CODEC = streamCodecComposite(STRING_CODEC, Key::asString, Key::key)
57+
58+
59+
private val SOUND_SOURCE_BY_ID = ByIdMap.continuous(
60+
{ it.ordinal },
61+
Sound.Source.entries.toTypedArray(),
62+
ByIdMap.OutOfBoundsStrategy.ZERO
63+
)
64+
val SOUND_CODEC = streamCodecComposite(
65+
KEY_CODEC,
66+
Sound::name,
67+
idMapper(SOUND_SOURCE_BY_ID) { it.ordinal },
68+
{ it.source() },
69+
FLOAT_CODEC,
70+
Sound::volume,
71+
FLOAT_CODEC,
72+
Sound::pitch,
73+
OPTIONAL_LONG_CODEC,
74+
Sound::seed
75+
) { type, source, volume, pitch, seed ->
76+
Sound.sound()
77+
.type(type)
78+
.source(source)
79+
.volume(volume)
80+
.pitch(pitch)
81+
.seed(seed)
82+
.build()
83+
}
84+
85+
val COMPONENT_CODEC = streamCodecComposite(
86+
STRING_CODEC,
87+
{ GsonComponentSerializer.gson().serialize(it.compact()) },
88+
{ GsonComponentSerializer.gson().deserialize(it) }
89+
)
90+
91+
val COMPOUND_TAG_CODEC = streamCodecComposite(BYTE_ARRAY_CODEC, { tag ->
92+
ByteArrayOutputStream().use { out ->
93+
BinaryTagIO.writer().write(tag, out, BinaryTagIO.Compression.GZIP)
94+
out.toByteArray()
95+
}
96+
}, { bytes ->
97+
ByteArrayInputStream(bytes).use { input ->
98+
BinaryTagIO.unlimitedReader().read(input, BinaryTagIO.Compression.GZIP)
99+
}
100+
})
101+
102+
val URI_CODEC = streamCodecComposite(STRING_CODEC, URI::toString, URI::create)
103+
val INET_SOCKET_ADDRESS_CODEC = streamCodecComposite(
104+
STRING_CODEC,
105+
InetSocketAddress::getHostString,
106+
INT_CODEC,
107+
InetSocketAddress::getPort,
108+
::createUnresolvedInetSocketAddress
109+
)
110+
val INET_4_ADDRESS_CODEC = streamCodecComposite(
111+
BYTE_ARRAY_CODEC,
112+
Inet4Address::getAddress
113+
) { Inet4Address.getByAddress(it) as Inet4Address }
114+
115+
val ZONED_DATE_TIME_CODEC = streamCodecComposite(
116+
LONG_CODEC,
117+
{ it.toInstant().toEpochMilli() },
118+
STRING_CODEC,
119+
{ it.zone.id },
120+
{ epoch, zoneId -> ZonedDateTime.ofInstant(Instant.ofEpochMilli(epoch), ZoneId.of(zoneId)) }
121+
)
122+
123+
val DURATION_CODEC = streamCodecComposite(
124+
LONG_CODEC,
125+
Duration::inWholeMilliseconds
126+
) { it.milliseconds }
127+
128+
val BIG_INTEGER_CODEC =
129+
streamCodecComposite(BYTE_ARRAY_CODEC, BigInteger::toByteArray, ::BigInteger)
130+
val BIG_DECIMAL_CODEC = streamCodecComposite(
131+
BIG_INTEGER_CODEC,
132+
BigDecimal::unscaledValue,
133+
VAR_INT_CODEC,
134+
BigDecimal::scale,
135+
VAR_INT_CODEC,
136+
BigDecimal::precision
137+
) { unscaledValue, scale, precision ->
138+
BigDecimal(unscaledValue, scale, MathContext(precision))
139+
}
140+
141+
142+
fun <E : Enum<E>> enumStreamCodec(clazz: Class<E>): StreamCodec<ByteBuf, E> =
143+
streamCodec(ByteBuf::writeEnum) { it.readEnum(clazz) }
144+
145+
inline fun <reified E : Enum<E>> enumStreamCodec(): StreamCodec<ByteBuf, E> =
146+
streamCodec(ByteBuf::writeEnum) { it.readEnum<E>() }
147+
148+
149+
fun <T> idMapper(
150+
idLookup: (Int) -> T,
151+
idGetter: (T) -> Int
152+
): StreamCodec<ByteBuf, T> = object : StreamCodec<ByteBuf, T> {
153+
override fun decode(buf: ByteBuf): T = idLookup(buf.readVarInt())
154+
override fun encode(buf: ByteBuf, value: T) {
155+
buf.writeVarInt(idGetter(value))
156+
}
157+
}
158+
}

0 commit comments

Comments
 (0)