Created
August 15, 2022 03:46
-
-
Save aripiprazole/33b13abb79ff051f669fbcf40d01878b to your computer and use it in GitHub Desktop.
Empty server with Andesite
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import andesite.protocol.java.handshake.HandshakePacket | |
import andesite.protocol.java.handshake.NextState | |
import andesite.protocol.java.handshake.PingPacket | |
import andesite.protocol.java.handshake.Players | |
import andesite.protocol.java.handshake.PongPacket | |
import andesite.protocol.java.handshake.Response | |
import andesite.protocol.java.handshake.ResponsePacket | |
import andesite.protocol.java.handshake.Version | |
import andesite.protocol.misc.Chat | |
import andesite.protocol.misc.UuidSerializer | |
import andesite.protocol.serialization.MinecraftCodec | |
import io.ktor.network.selector.ActorSelectorManager | |
import io.ktor.network.sockets.aSocket | |
import kotlinx.coroutines.CoroutineName | |
import kotlinx.coroutines.Dispatchers | |
import kotlinx.coroutines.coroutineScope | |
import kotlinx.coroutines.launch | |
import kotlinx.serialization.json.Json | |
import kotlinx.serialization.modules.SerializersModule | |
import kotlinx.serialization.modules.contextual | |
import net.benwoodworth.knbt.Nbt | |
import net.benwoodworth.knbt.NbtCompression | |
import net.benwoodworth.knbt.NbtVariant | |
suspend fun main(): Unit = coroutineScope { | |
val server = aSocket(ActorSelectorManager(Dispatchers.IO)).tcp().bind("0.0.0.0", 25565) | |
val codec = MinecraftCodec { | |
protocolVersion = 756 | |
nbt = Nbt { | |
variant = NbtVariant.Java | |
compression = NbtCompression.None | |
ignoreUnknownKeys = true | |
} | |
json = Json { | |
prettyPrint = true | |
} | |
serializersModule = SerializersModule { | |
contextual(UuidSerializer) | |
} | |
} | |
while (true) { | |
val client = server.accept() | |
launch(CoroutineName("session-${client.remoteAddress}")) { | |
val session = Session(codec, client, this) | |
val handshake = session.receivePacket(HandshakePacket.serializer()) | |
when (handshake.nextState) { | |
NextState.Status -> { | |
session.sendPacket( | |
ResponsePacket.serializer(), | |
ResponsePacket( | |
Response( | |
version = Version(name = "Andesite for 1.17.1", protocol = 756), | |
players = Players(max = 10, online = 0, sample = listOf()), | |
description = Chat.of("&eAndesite for 1.17.1"), | |
), | |
), | |
) | |
session.receivePacket(PingPacket.serializer()) | |
session.sendPacket(PongPacket.serializer(), PongPacket()) | |
} | |
NextState.Login -> TODO("implement login logic") | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import andesite.protocol.ProtocolPacket | |
import andesite.protocol.extractPacketId | |
import andesite.protocol.java.JavaPacket | |
import andesite.protocol.readVarInt | |
import andesite.protocol.serialization.MinecraftCodec | |
import andesite.protocol.writeVarInt | |
import io.ktor.network.sockets.Socket | |
import io.ktor.network.sockets.openReadChannel | |
import io.ktor.network.sockets.openWriteChannel | |
import io.ktor.utils.io.core.buildPacket | |
import io.ktor.utils.io.core.readBytes | |
import io.ktor.utils.io.core.writeFully | |
import io.ktor.utils.io.writePacket | |
import kotlinx.coroutines.CoroutineScope | |
import kotlinx.serialization.DeserializationStrategy | |
import kotlinx.serialization.ExperimentalSerializationApi | |
import kotlinx.serialization.SerializationStrategy | |
@OptIn(ExperimentalSerializationApi::class) | |
class Session(val codec: MinecraftCodec, val socket: Socket, val scope: CoroutineScope) : CoroutineScope by scope { | |
val input = socket.openReadChannel() | |
val output = socket.openWriteChannel() | |
suspend fun <T : JavaPacket> receivePacket(deserializer: DeserializationStrategy<T>): T { | |
val name = deserializer.descriptor.serialName | |
val size = input.readVarInt() | |
val packet = input.readPacket(size.toInt()) | |
val id = packet.readVarInt().toInt() | |
println("Packet `$name` received with id [0x%02x] and size [$size]".format(id)) | |
return codec.decodeFromByteArray(deserializer, packet.readBytes()) | |
} | |
suspend fun <T : JavaPacket> sendPacket(serializer: SerializationStrategy<T>, packet: T) { | |
val packetName = serializer.descriptor.serialName | |
val packetId = extractPacketId(serializer.descriptor) | |
output.writePacket { | |
val data = buildPacket { | |
writeVarInt(packetId) | |
writeFully(codec.encodeToByteArray(serializer, packet)) | |
} | |
println("Packet `$packetName` sent with id [0x%02x] with size [${data.remaining}]".format(packetId)) | |
writeVarInt(data.remaining.toInt()) | |
writePacket(data) | |
} | |
output.flush() | |
} | |
override fun toString(): String { | |
return "Session(remoteAddress=${socket.remoteAddress})" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment