diff --git a/.gitignore b/.gitignore index 37afbbb..1d7675e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ /.gradle/ -/build/ -/blokk-api/build/ -/blokk-server/build/ +build/ +!src/**/build /data/ diff --git a/README.md b/README.md index cee167e..50d4776 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,5 @@ # Blokk ## To Do - Move packets to their own project -- Move packet encoders and decoders to their own project +- Stop Using Spek +- Support packet compression diff --git a/blokk-api/src/main/kotlin/space/blokk/chat/FormattingCode.kt b/blokk-api/src/main/kotlin/space/blokk/chat/FormattingCode.kt index 283fbcf..bfd1c42 100644 --- a/blokk-api/src/main/kotlin/space/blokk/chat/FormattingCode.kt +++ b/blokk-api/src/main/kotlin/space/blokk/chat/FormattingCode.kt @@ -3,7 +3,7 @@ package space.blokk.chat /** * Legacy formatting codes. You should use [ChatComponent][space.blokk.chat.ChatComponent] whenever it's possible, * but sometimes these codes are required, for example in - * [the name of a player in a server list sample][space.blokk.net.protocols.status.ResponsePacket.Players.SampleEntry.name]. + * [the name of a player in a server list sample][space.blokk.net.packets.status.ResponsePacket.Players.SampleEntry.name]. */ enum class FormattingCode(private val char: Char) { BLACK('0'), diff --git a/blokk-api/src/main/kotlin/space/blokk/net/Session.kt b/blokk-api/src/main/kotlin/space/blokk/net/Session.kt index 4e39a7f..0d90d9c 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/Session.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/Session.kt @@ -4,8 +4,8 @@ import io.netty.buffer.ByteBuf import kotlinx.coroutines.CoroutineScope import space.blokk.events.EventTarget import space.blokk.net.events.SessionEvent -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.Protocol +import space.blokk.net.packets.OutgoingPacket +import space.blokk.net.packets.Protocol import java.net.InetAddress interface Session : EventTarget { diff --git a/blokk-api/src/main/kotlin/space/blokk/net/events/PacketReceivedEvent.kt b/blokk-api/src/main/kotlin/space/blokk/net/events/PacketReceivedEvent.kt index 94eb150..f3bd320 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/events/PacketReceivedEvent.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/events/PacketReceivedEvent.kt @@ -2,7 +2,7 @@ package space.blokk.net.events import space.blokk.events.Cancellable import space.blokk.net.Session -import space.blokk.net.protocols.IncomingPacket +import space.blokk.net.packets.IncomingPacket /** * Emitted when a packet is received. **You should only listen to this event when there is no other option.** diff --git a/blokk-api/src/main/kotlin/space/blokk/net/events/PacketSendEvent.kt b/blokk-api/src/main/kotlin/space/blokk/net/events/PacketSendEvent.kt index 19a7420..159837a 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/events/PacketSendEvent.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/events/PacketSendEvent.kt @@ -2,7 +2,7 @@ package space.blokk.net.events import space.blokk.events.Cancellable import space.blokk.net.Session -import space.blokk.net.protocols.OutgoingPacket +import space.blokk.net.packets.OutgoingPacket /** * Emitted when a packet is going to be sent. **You should only listen to this event when there is no other option.** diff --git a/blokk-api/src/main/kotlin/space/blokk/net/events/ServerListInfoRequestEvent.kt b/blokk-api/src/main/kotlin/space/blokk/net/events/ServerListInfoRequestEvent.kt index 21ece6f..a7036b5 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/events/ServerListInfoRequestEvent.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/events/ServerListInfoRequestEvent.kt @@ -2,7 +2,7 @@ package space.blokk.net.events import space.blokk.events.Cancellable import space.blokk.net.Session -import space.blokk.net.protocols.status.ResponsePacket +import space.blokk.net.packets.status.ResponsePacket /** * Emitted when a client requests general info about the server, most likely to show it in the server list. diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/Packet.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/Packet.kt new file mode 100644 index 0000000..a370a8c --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/Packet.kt @@ -0,0 +1,8 @@ +package space.blokk.net.packets + +abstract class Packet { + override fun toString(): String = this::class.java.simpleName + "(no data)" +} + +abstract class IncomingPacket : Packet() +abstract class OutgoingPacket : Packet() diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/PacketCodec.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/PacketCodec.kt new file mode 100644 index 0000000..12e2861 --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/PacketCodec.kt @@ -0,0 +1,14 @@ +package space.blokk.net.packets + +import io.netty.buffer.ByteBuf +import kotlin.reflect.KClass + +abstract class PacketCodec(val id: Int, val dataType: KClass) + +abstract class IncomingPacketCodec(id: Int, dataType: KClass) : PacketCodec(id, dataType) { + abstract fun decode(msg: ByteBuf): T +} + +abstract class OutgoingPacketCodec(id: Int, dataType: KClass) : PacketCodec(id, dataType) { + abstract fun T.encode(dst: ByteBuf) +} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/Protocol.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/Protocol.kt new file mode 100644 index 0000000..0c11342 --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/Protocol.kt @@ -0,0 +1,16 @@ +package space.blokk.net.packets + +import kotlin.reflect.KClass + +abstract class Protocol constructor(val name: String, vararg codecs: PacketCodec<*>) { + val test = emptyList() + private val codecsByPacketType = codecs.map { it.dataType to it }.toMap() + val incomingPacketCodecsByID = codecs.filterIsInstance>().map { it.id to it }.toMap() + + @Suppress("UNCHECKED_CAST") + fun getCodecByType(type: KClass): PacketCodec = codecsByPacketType[type] as PacketCodec? + ?: throw Exception( + "No packet companion found for this packet type. " + + "This can happen if the packet is not part of the current protocol." + ) +} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakePacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakePacket.kt new file mode 100644 index 0000000..7493238 --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakePacket.kt @@ -0,0 +1,22 @@ +package space.blokk.net.packets.handshaking + +import space.blokk.net.packets.IncomingPacket + +/** + * This is the first packet a client should send. Per default, the server immediately switches + * the [session's currentProtocol][space.blokk.net.Session.currentProtocol] to + * `STATUS` or `LOGIN`, + * depending on the value of [loginAttempt]. + * + * @param protocolVersion The number of the [protocol version](https://wiki.vg/Protocol_version_numbers) used by the client. + * @param serverAddress Hostname or IP address that was used to connect. + * @param serverPort Port that was used to connect. + * @param loginAttempt Whether the server should use the `STATUS` or + * the `LOGIN` protocol from now on. + */ +data class HandshakePacket( + val protocolVersion: Int, + val serverAddress: String, + val serverPort: Int, + val loginAttempt: Boolean +) : IncomingPacket() diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/login/DisconnectPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/DisconnectPacket.kt new file mode 100644 index 0000000..30891dc --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/DisconnectPacket.kt @@ -0,0 +1,11 @@ +package space.blokk.net.packets.login + +import space.blokk.chat.ChatComponent +import space.blokk.net.packets.OutgoingPacket + +/** + * Sent by the server to cancel an ongoing login process. + * + * @param reason The reason why the login process was cancelled. + */ +data class DisconnectPacket(val reason: ChatComponent) : OutgoingPacket() diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/EncryptionRequestPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/EncryptionRequestPacket.kt similarity index 58% rename from blokk-api/src/main/kotlin/space/blokk/net/protocols/login/EncryptionRequestPacket.kt rename to blokk-api/src/main/kotlin/space/blokk/net/packets/login/EncryptionRequestPacket.kt index e2ba96a..4303cc2 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/EncryptionRequestPacket.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/EncryptionRequestPacket.kt @@ -1,10 +1,6 @@ -package space.blokk.net.protocols.login +package space.blokk.net.packets.login -import io.netty.buffer.ByteBuf -import space.blokk.net.MinecraftDataTypes.writeString -import space.blokk.net.MinecraftDataTypes.writeVarInt -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.OutgoingPacketCompanion +import space.blokk.net.packets.OutgoingPacket /** * Sent by the server to request authentication and encryption from the client. The client must respond with @@ -16,16 +12,6 @@ data class EncryptionRequestPacket( val publicKey: ByteArray, val verifyToken: ByteArray ) : OutgoingPacket() { - companion object : OutgoingPacketCompanion(0x01, EncryptionRequestPacket::class) - - override fun encode(dst: ByteBuf) { - dst.writeString("") // Required for legacy reasons - dst.writeVarInt(publicKey.size) - dst.writeBytes(publicKey) - dst.writeVarInt(verifyToken.size) - dst.writeBytes(verifyToken) - } - override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/login/EncryptionResponsePacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/EncryptionResponsePacket.kt new file mode 100644 index 0000000..491b87d --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/EncryptionResponsePacket.kt @@ -0,0 +1,31 @@ +package space.blokk.net.packets.login + +import space.blokk.net.packets.IncomingPacket + +/** + * Sent by the client in response to an [EncryptionRequestPacket]. + * + * @see https://wiki.vg/Protocol_Encryption + */ +data class EncryptionResponsePacket( + val sharedSecret: ByteArray, + val verifyToken: ByteArray +) : IncomingPacket() { + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + + other as EncryptionResponsePacket + + if (!sharedSecret.contentEquals(other.sharedSecret)) return false + if (!verifyToken.contentEquals(other.verifyToken)) return false + + return true + } + + override fun hashCode(): Int { + var result = sharedSecret.contentHashCode() + result = 31 * result + verifyToken.contentHashCode() + return result + } +} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginPluginRequestPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginPluginRequestPacket.kt similarity index 67% rename from blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginPluginRequestPacket.kt rename to blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginPluginRequestPacket.kt index d94f9fb..6b9088b 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginPluginRequestPacket.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginPluginRequestPacket.kt @@ -1,10 +1,6 @@ -package space.blokk.net.protocols.login +package space.blokk.net.packets.login -import io.netty.buffer.ByteBuf -import space.blokk.net.MinecraftDataTypes.writeString -import space.blokk.net.MinecraftDataTypes.writeVarInt -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.OutgoingPacketCompanion +import space.blokk.net.packets.OutgoingPacket /** * Optionally sent by the server to transfer additional, non-standard information required for the login process. @@ -19,14 +15,6 @@ data class LoginPluginRequestPacket( val channel: String, val data: ByteArray ) : OutgoingPacket() { - companion object : OutgoingPacketCompanion(0x04, LoginPluginRequestPacket::class) - - override fun encode(dst: ByteBuf) { - dst.writeVarInt(messageID) - dst.writeString(channel) - dst.writeBytes(data) - } - override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginPluginResponsePacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginPluginResponsePacket.kt similarity index 51% rename from blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginPluginResponsePacket.kt rename to blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginPluginResponsePacket.kt index 6ece806..87115cf 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginPluginResponsePacket.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginPluginResponsePacket.kt @@ -1,9 +1,6 @@ -package space.blokk.net.protocols.login +package space.blokk.net.packets.login -import io.netty.buffer.ByteBuf -import space.blokk.net.MinecraftDataTypes -import space.blokk.net.protocols.IncomingPacket -import space.blokk.net.protocols.IncomingPacketCompanion +import space.blokk.net.packets.IncomingPacket /** * Sent by the client in response to a [LoginPluginRequestPacket]. @@ -14,22 +11,6 @@ data class LoginPluginResponsePacket( val messageID: Int, val data: ByteArray? ) : IncomingPacket() { - companion object : IncomingPacketCompanion(0x02, LoginPluginResponsePacket::class) { - override fun decode(msg: ByteBuf): LoginPluginResponsePacket { - return with(MinecraftDataTypes) { - val messageID = msg.readVarInt() - val successful = msg.readBoolean() - - // TODO: Test this - val data = - if (successful) ByteArray(msg.readableBytes()).also { msg.readBytes(it) } - else null - - LoginPluginResponsePacket(messageID, data) - } - } - } - override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginStartPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginStartPacket.kt new file mode 100644 index 0000000..c056630 --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginStartPacket.kt @@ -0,0 +1,14 @@ +package space.blokk.net.packets.login + +import space.blokk.net.packets.IncomingPacket + +/** + * Sent by the client to initialize the login process. + * + * @param username The username of the client. This is not validated (yet). Can only be 16 characters long. + */ +data class LoginStartPacket(val username: String) : IncomingPacket() { + init { + if (username.length > 16) throw IllegalArgumentException("username can only be 16 characters long") + } +} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginSuccessPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginSuccessPacket.kt similarity index 52% rename from blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginSuccessPacket.kt rename to blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginSuccessPacket.kt index 50103b5..dbb5027 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginSuccessPacket.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/LoginSuccessPacket.kt @@ -1,28 +1,18 @@ -package space.blokk.net.protocols.login +package space.blokk.net.packets.login -import io.netty.buffer.ByteBuf -import space.blokk.net.MinecraftDataTypes.writeString -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.OutgoingPacketCompanion +import space.blokk.net.packets.OutgoingPacket import java.util.* /** * Sent by the server to indicate that the login process succeeded. * After this packet is sent, the [session's currentProtocol][space.blokk.net.Session.currentProtocol] will be switched to - * [PLAY][space.blokk.net.protocols.play.PlayProtocol]. + * `PLAY`. * * @param uuid The UUID of the player. * @param username The username of the player. Can only be 16 characters long. */ data class LoginSuccessPacket(val uuid: UUID, val username: String) : OutgoingPacket() { - companion object : OutgoingPacketCompanion(0x02, LoginSuccessPacket::class) - init { if (username.length > 16) throw IllegalArgumentException("username can only be 16 characters long") } - - override fun encode(dst: ByteBuf) { - dst.writeString(uuid.toString()) - dst.writeString(username) - } } diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/login/SetCompressionPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/SetCompressionPacket.kt new file mode 100644 index 0000000..7e5da66 --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/login/SetCompressionPacket.kt @@ -0,0 +1,11 @@ +package space.blokk.net.packets.login + +import space.blokk.net.packets.OutgoingPacket + +/** + * Sent by the server to indicate that all following packets are compressed and the client should also compress its + * packets. + * + * @param threshold Maximum size before a packet is compressed. Values lower than 1 will disable compression. + */ +data class SetCompressionPacket(val threshold: Int) : OutgoingPacket() diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/play/ClientSettingsPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/ClientSettingsPacket.kt new file mode 100644 index 0000000..d4ca601 --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/ClientSettingsPacket.kt @@ -0,0 +1,18 @@ +package space.blokk.net.packets.play + +import space.blokk.net.packets.IncomingPacket +import space.blokk.players.ChatMode +import space.blokk.players.DisplayedSkinParts +import space.blokk.players.MainHand + +/** + * Sent by the client when the player joins or the settings changed. + */ +data class ClientSettingsPacket( + val locale: String, + val viewDistance: Byte, + val chatMode: ChatMode, + val chatColorsEnabled: Boolean, + val displayedSkinParts: DisplayedSkinParts, + val mainHand: MainHand +) : IncomingPacket() diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/IncomingPluginMessagePacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/IncomingPluginMessagePacket.kt similarity index 55% rename from blokk-api/src/main/kotlin/space/blokk/net/protocols/play/IncomingPluginMessagePacket.kt rename to blokk-api/src/main/kotlin/space/blokk/net/packets/play/IncomingPluginMessagePacket.kt index 1d6643b..565b992 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/IncomingPluginMessagePacket.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/IncomingPluginMessagePacket.kt @@ -1,9 +1,6 @@ -package space.blokk.net.protocols.play +package space.blokk.net.packets.play -import io.netty.buffer.ByteBuf -import space.blokk.net.MinecraftDataTypes -import space.blokk.net.protocols.IncomingPacket -import space.blokk.net.protocols.IncomingPacketCompanion +import space.blokk.net.packets.IncomingPacket /** * Can be used by client-side mods to communicate with a potentially modded server. @@ -13,19 +10,6 @@ import space.blokk.net.protocols.IncomingPacketCompanion * @param data Data which was sent. */ data class IncomingPluginMessagePacket(val channel: String, val data: ByteArray) : IncomingPacket() { - companion object : IncomingPacketCompanion(0x0B, IncomingPluginMessagePacket::class) { - override fun decode(msg: ByteBuf): IncomingPluginMessagePacket { - return with(MinecraftDataTypes) { - val channel = msg.readString() - - // TODO: Test this - val data = ByteArray(msg.readableBytes()).also { msg.readBytes(it) } - - IncomingPluginMessagePacket(channel, data) - } - } - } - override fun equals(other: Any?): Boolean { if (this === other) return true if (javaClass != other?.javaClass) return false diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/play/JoinGamePacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/JoinGamePacket.kt new file mode 100644 index 0000000..f06616b --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/JoinGamePacket.kt @@ -0,0 +1,35 @@ +package space.blokk.net.packets.play + +import space.blokk.net.packets.OutgoingPacket +import space.blokk.players.GameMode +import space.blokk.worlds.WorldDimension +import space.blokk.worlds.WorldType + +/** + * Sent by the server after the client logged in. + * + * @param entityID ID of the player entity. + * @param gameMode Game mode of the player. + * @param hardcore Whether the player is in hardcore mode. + * @param worldDimension Dimension of the world the player joins. + * @param worldSeedHash First 8 bytes of the SHA-256 hash of the world's seed. + * @param worldType Type of the world the player joins. + * @param viewDistance Maximum view distance. + * @param reducedDebugInfo Whether the debug screen shows only reduced info. + * @param respawnScreenEnabled Whether the respawn screen is shown when the player dies. + */ +data class JoinGamePacket( + val entityID: Int, + val gameMode: GameMode, + val hardcore: Boolean, + val worldDimension: WorldDimension, + val worldSeedHash: Long, + val worldType: WorldType, + val viewDistance: Byte, + val reducedDebugInfo: Boolean, + val respawnScreenEnabled: Boolean +) : OutgoingPacket() { + init { + if (viewDistance < 2 || viewDistance > 32) throw IllegalArgumentException("viewDistance must be between 2 and 32.") + } +} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/play/OutgoingPluginMessagePacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/OutgoingPluginMessagePacket.kt new file mode 100644 index 0000000..ebcde54 --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/OutgoingPluginMessagePacket.kt @@ -0,0 +1,13 @@ +package space.blokk.net.packets.play + +import io.netty.buffer.ByteBuf +import space.blokk.net.packets.OutgoingPacket + +/** + * Can be used by mods or plugins to communicate with a potentially modded client. + * Minecraft itself [also uses this for some things](https://wiki.vg/Plugin_channels#Channels_internal_to_Minecraft). + * + * @param channel Channel in which the message should be send. + * @param data Data which should be send. The ByteBuf needs to be released by the caller. + */ +data class OutgoingPluginMessagePacket(val channel: String, val data: ByteBuf) : OutgoingPacket() diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/PlayerAbilitiesPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/PlayerAbilitiesPacket.kt similarity index 51% rename from blokk-api/src/main/kotlin/space/blokk/net/protocols/play/PlayerAbilitiesPacket.kt rename to blokk-api/src/main/kotlin/space/blokk/net/packets/play/PlayerAbilitiesPacket.kt index 09b9141..0267986 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/PlayerAbilitiesPacket.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/PlayerAbilitiesPacket.kt @@ -1,8 +1,6 @@ -package space.blokk.net.protocols.play +package space.blokk.net.packets.play -import io.netty.buffer.ByteBuf -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.OutgoingPacketCompanion +import space.blokk.net.packets.OutgoingPacket /** * Tells the client some things about the player. @@ -21,18 +19,4 @@ data class PlayerAbilitiesPacket( val instantlyBreakBlocks: Boolean, val flyingSpeed: Float = 0.5f, val fieldOfView: Float = 0.1f -) : OutgoingPacket() { - companion object : OutgoingPacketCompanion(0x32, PlayerAbilitiesPacket::class) - - override fun encode(dst: ByteBuf) { - var flags = 0 - if (invulnerable) flags = flags and 0x01 - if (flying) flags = flags and 0x02 - if (flyingAllowed) flags = flags and 0x04 - if (instantlyBreakBlocks) flags = flags and 0x08 - - dst.writeByte(flags) - dst.writeFloat(flyingSpeed) - dst.writeFloat(fieldOfView) - } -} +) : OutgoingPacket() diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/play/ServerDifficultyPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/ServerDifficultyPacket.kt new file mode 100644 index 0000000..fe5b8f2 --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/play/ServerDifficultyPacket.kt @@ -0,0 +1,9 @@ +package space.blokk.net.packets.play + +import space.blokk.net.packets.OutgoingPacket +import space.blokk.worlds.WorldDifficulty + +/** + * Sets the difficulty shown in the pause menu. + */ +data class ServerDifficultyPacket(val difficulty: WorldDifficulty, val locked: Boolean) : OutgoingPacket() diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/status/PingPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/status/PingPacket.kt new file mode 100644 index 0000000..8ce91f0 --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/status/PingPacket.kt @@ -0,0 +1,10 @@ +package space.blokk.net.packets.status + +import space.blokk.net.packets.IncomingPacket + +/** + * Sent by the client to determine the RTT of the connection. The server responds with a [PongPacket]. + * + * @param payload A random value generated by the client. The [PongPacket] sent in response must use the same payload. + */ +data class PingPacket(val payload: Long) : IncomingPacket() diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/status/PongPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/status/PongPacket.kt new file mode 100644 index 0000000..fe5b26c --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/status/PongPacket.kt @@ -0,0 +1,10 @@ +package space.blokk.net.packets.status + +import space.blokk.net.packets.OutgoingPacket + +/** + * Sent by the server in response to a [PingPacket]. + * + * @param payload A random value generated by the client. This must be the same as in the corresponding [PingPacket]. + */ +data class PongPacket(val payload: Long) : OutgoingPacket() diff --git a/blokk-api/src/main/kotlin/space/blokk/net/packets/status/RequestPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/status/RequestPacket.kt new file mode 100644 index 0000000..8c0946d --- /dev/null +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/status/RequestPacket.kt @@ -0,0 +1,12 @@ +package space.blokk.net.packets.status + +import space.blokk.net.packets.IncomingPacket + +/** + * Sent by the client to request general information about the server. + * + * The server responds with a [ResponsePacket]. + * + * @see [space.blokk.net.events.ServerListInfoRequestEvent] + */ +class RequestPacket : IncomingPacket() diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/ResponsePacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/packets/status/ResponsePacket.kt similarity index 65% rename from blokk-api/src/main/kotlin/space/blokk/net/protocols/status/ResponsePacket.kt rename to blokk-api/src/main/kotlin/space/blokk/net/packets/status/ResponsePacket.kt index 092fe63..0e79c8d 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/ResponsePacket.kt +++ b/blokk-api/src/main/kotlin/space/blokk/net/packets/status/ResponsePacket.kt @@ -1,13 +1,8 @@ -package space.blokk.net.protocols.status +package space.blokk.net.packets.status import com.squareup.moshi.JsonClass -import io.netty.buffer.ByteBuf -import space.blokk.Blokk import space.blokk.chat.TextComponent -import space.blokk.net.MinecraftDataTypes -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.OutgoingPacketCompanion -import space.blokk.utils.toJson +import space.blokk.net.packets.OutgoingPacket /** * Sent by the server in response to a [RequestPacket]. @@ -26,27 +21,11 @@ data class ResponsePacket( val players: Players, val favicon: String? = null ) : OutgoingPacket() { - companion object : OutgoingPacketCompanion(0x00, ResponsePacket::class) - init { if (description.getExtraTypes().find { it != TextComponent::class } != null) throw Exception("description may only contain instances of TextComponent") } - override fun encode(dst: ByteBuf) { - with(MinecraftDataTypes) { - dst.writeString(Blokk.json.toJson(mapOf( - "version" to mapOf( - "name" to versionName, - "protocol" to protocolVersion - ), - "players" to players, - "description" to description, - "favicon" to favicon?.let { "data:image/png;base64,$it" } - ))) - } - } - @JsonClass(generateAdapter = true) data class Players(val max: Int, val online: Int, val sample: List) { /** diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/Packet.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/Packet.kt deleted file mode 100644 index 522241f..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/Packet.kt +++ /dev/null @@ -1,29 +0,0 @@ -package space.blokk.net.protocols - -import io.netty.buffer.ByteBuf -import kotlin.reflect.KClass - -abstract class Packet { - override fun toString(): String = this::class.java.simpleName + "(no data)" -} - -abstract class IncomingPacket : Packet() - -abstract class OutgoingPacket : Packet() { - abstract fun encode(dst: ByteBuf) -} - -sealed class PacketCompanion(val id: Int, val packetType: KClass) - -abstract class IncomingPacketCompanion( - id: Int, - packetType: KClass -) : PacketCompanion(id, packetType) { - abstract fun decode(msg: ByteBuf): T -} - -abstract class OutgoingPacketCompanion( - id: Int, - packetType: KClass -) : PacketCompanion(id, packetType) - diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/Protocol.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/Protocol.kt deleted file mode 100644 index 8ef8619..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/Protocol.kt +++ /dev/null @@ -1,27 +0,0 @@ -package space.blokk.net.protocols - -abstract class Protocol internal constructor(val name: String, vararg packets: PacketCompanion<*>) { - val incomingPackets = packets.filterIsInstance>() - val incomingPacketsByID = incomingPackets.mapToIDMap() - val outgoingPackets = packets.filterIsInstance>() - val outgoingPacketsByID = outgoingPackets.mapToIDMap() - val packetCompanionsByPacketType = packets.map { it.packetType to it }.toMap() - - private fun > Iterable.mapToIDMap() = map { it.id to it }.toMap() - - fun validate() { - ensureDistinctIDs(incomingPackets, "serverbound") - ensureDistinctIDs(outgoingPackets, "clientbound") - } - - override fun toString() = name - - private fun ensureDistinctIDs(packets: Iterable>, type: String) { - packets.groupBy { it.id }.forEach { (id, p) -> - if (p.count() > 1) { - val packetsString = p.joinToString(", ", limit = 4) { it.packetType.simpleName.toString() } - throw Error("Multiple $type packets use the same ID (0x${id.toString(16)}): $packetsString") - } - } - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/Protocols.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/Protocols.kt deleted file mode 100644 index 3411d55..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/Protocols.kt +++ /dev/null @@ -1,10 +0,0 @@ -package space.blokk.net.protocols - -import space.blokk.net.protocols.handshaking.HandshakingProtocol -import space.blokk.net.protocols.login.LoginProtocol -import space.blokk.net.protocols.status.StatusProtocol - -object Protocols { - val all = setOf(HandshakingProtocol, StatusProtocol, LoginProtocol) - fun validate() = all.forEach(Protocol::validate) -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/handshaking/HandshakePacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/handshaking/HandshakePacket.kt deleted file mode 100644 index d8a6055..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/handshaking/HandshakePacket.kt +++ /dev/null @@ -1,38 +0,0 @@ -package space.blokk.net.protocols.handshaking - -import io.netty.buffer.ByteBuf -import space.blokk.net.MinecraftDataTypes -import space.blokk.net.protocols.IncomingPacket -import space.blokk.net.protocols.IncomingPacketCompanion - -/** - * This is the first packet a client should send. Per default, the server immediately switches - * the [session's currentProtocol][space.blokk.net.Session.currentProtocol] to - * [STATUS][space.blokk.net.protocols.status.StatusProtocol] or [LOGIN][space.blokk.net.protocols.login.LoginProtocol], - * depending on the value of [loginAttempt]. - * - * @param protocolVersion The number of the [protocol version](https://wiki.vg/Protocol_version_numbers) used by the client. - * @param serverAddress Hostname or IP address that was used to connect. - * @param serverPort Port that was used to connect. - * @param loginAttempt Whether the server should use the [STATUS][space.blokk.net.protocols.status.StatusProtocol] or - * the [LOGIN][space.blokk.net.protocols.login.LoginProtocol] protocol from now on. - */ -data class HandshakePacket( - val protocolVersion: Int, - val serverAddress: String, - val serverPort: Int, - val loginAttempt: Boolean -) : IncomingPacket() { - companion object : IncomingPacketCompanion(0x00, HandshakePacket::class) { - override fun decode(msg: ByteBuf): HandshakePacket { - return with(MinecraftDataTypes) { - HandshakePacket( - protocolVersion = msg.readVarInt(), - serverAddress = msg.readString(), - serverPort = msg.readUnsignedShort(), - loginAttempt = msg.readVarInt() == 2 - ) - } - } - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/handshaking/HandshakingProtocol.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/handshaking/HandshakingProtocol.kt deleted file mode 100644 index d8a61c2..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/handshaking/HandshakingProtocol.kt +++ /dev/null @@ -1,5 +0,0 @@ -package space.blokk.net.protocols.handshaking - -import space.blokk.net.protocols.Protocol - -object HandshakingProtocol : Protocol("HANDSHAKING", HandshakePacket) diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/DisconnectPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/DisconnectPacket.kt deleted file mode 100644 index a1aa62d..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/DisconnectPacket.kt +++ /dev/null @@ -1,20 +0,0 @@ -package space.blokk.net.protocols.login - -import io.netty.buffer.ByteBuf -import space.blokk.chat.ChatComponent -import space.blokk.net.MinecraftDataTypes.writeString -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.OutgoingPacketCompanion - -/** - * Sent by the server to cancel an ongoing login process. - * - * @param reason The reason why the login process was cancelled. - */ -data class DisconnectPacket(val reason: ChatComponent) : OutgoingPacket() { - companion object : OutgoingPacketCompanion(0x00, DisconnectPacket::class) - - override fun encode(dst: ByteBuf) { - dst.writeString(reason.toJson()) - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/EncryptionResponsePacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/EncryptionResponsePacket.kt deleted file mode 100644 index 1c14a64..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/EncryptionResponsePacket.kt +++ /dev/null @@ -1,50 +0,0 @@ -package space.blokk.net.protocols.login - -import io.netty.buffer.ByteBuf -import space.blokk.net.MinecraftDataTypes -import space.blokk.net.protocols.IncomingPacket -import space.blokk.net.protocols.IncomingPacketCompanion - -/** - * Sent by the client in response to an [EncryptionRequestPacket]. - * - * @see https://wiki.vg/Protocol_Encryption - */ -data class EncryptionResponsePacket( - val sharedSecret: ByteArray, - val verifyToken: ByteArray -) : IncomingPacket() { - companion object : IncomingPacketCompanion(0x01, EncryptionResponsePacket::class) { - override fun decode(msg: ByteBuf): EncryptionResponsePacket { - return with(MinecraftDataTypes) { - val sharedSecretLength = msg.readVarInt() - val sharedSecret = ByteArray(sharedSecretLength) - msg.readBytes(sharedSecret) - - val verifyTokenLength = msg.readVarInt() - val verifyToken = ByteArray(verifyTokenLength) - msg.readBytes(verifyToken) - - EncryptionResponsePacket(sharedSecret, verifyToken) - } - } - } - - override fun equals(other: Any?): Boolean { - if (this === other) return true - if (javaClass != other?.javaClass) return false - - other as EncryptionResponsePacket - - if (!sharedSecret.contentEquals(other.sharedSecret)) return false - if (!verifyToken.contentEquals(other.verifyToken)) return false - - return true - } - - override fun hashCode(): Int { - var result = sharedSecret.contentHashCode() - result = 31 * result + verifyToken.contentHashCode() - return result - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginProtocol.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginProtocol.kt deleted file mode 100644 index 80360f2..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginProtocol.kt +++ /dev/null @@ -1,15 +0,0 @@ -package space.blokk.net.protocols.login - -import space.blokk.net.protocols.Protocol - -object LoginProtocol : Protocol( - "LOGIN", - DisconnectPacket, - LoginStartPacket, - EncryptionRequestPacket, - EncryptionResponsePacket, - SetCompressionPacket, - LoginSuccessPacket, - LoginPluginRequestPacket, - LoginPluginResponsePacket -) diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginStartPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginStartPacket.kt deleted file mode 100644 index fa7907e..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/LoginStartPacket.kt +++ /dev/null @@ -1,23 +0,0 @@ -package space.blokk.net.protocols.login - -import io.netty.buffer.ByteBuf -import space.blokk.net.MinecraftDataTypes -import space.blokk.net.protocols.IncomingPacket -import space.blokk.net.protocols.IncomingPacketCompanion - -/** - * Sent by the client to initialize the login process. - * - * @param username The username of the client. This is not validated (yet). Can only be 16 characters long. - */ -data class LoginStartPacket(val username: String) : IncomingPacket() { - companion object : IncomingPacketCompanion(0x00, LoginStartPacket::class) { - override fun decode(msg: ByteBuf): LoginStartPacket { - return with(MinecraftDataTypes) { LoginStartPacket(msg.readString()) } - } - } - - init { - if (username.length > 16) throw IllegalArgumentException("username can only be 16 characters long") - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/SetCompressionPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/SetCompressionPacket.kt deleted file mode 100644 index d8ab811..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/login/SetCompressionPacket.kt +++ /dev/null @@ -1,20 +0,0 @@ -package space.blokk.net.protocols.login - -import io.netty.buffer.ByteBuf -import space.blokk.net.MinecraftDataTypes.writeVarInt -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.OutgoingPacketCompanion - -/** - * Sent by the server to indicate that all following packets are compressed and the client should also compress its - * packets. - * - * @param threshold Maximum size before a packet is compressed. Values lower than 1 will disable compression. - */ -data class SetCompressionPacket(val threshold: Int) : OutgoingPacket() { - companion object : OutgoingPacketCompanion(0x03, SetCompressionPacket::class) - - override fun encode(dst: ByteBuf) { - dst.writeVarInt(threshold) - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/ClientSettingsPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/ClientSettingsPacket.kt deleted file mode 100644 index 5e0fb78..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/ClientSettingsPacket.kt +++ /dev/null @@ -1,67 +0,0 @@ -package space.blokk.net.protocols.play - -import io.netty.buffer.ByteBuf -import space.blokk.net.MinecraftDataTypes -import space.blokk.net.PacketDecodingException -import space.blokk.net.protocols.IncomingPacket -import space.blokk.net.protocols.IncomingPacketCompanion -import space.blokk.players.ChatMode -import space.blokk.players.DisplayedSkinParts -import space.blokk.players.MainHand -import space.blokk.utils.checkBit - -/** - * Sent by the client when the player joins or the settings changed. - */ -data class ClientSettingsPacket( - val locale: String, - val viewDistance: Byte, - val chatMode: ChatMode, - val chatColorsEnabled: Boolean, - val displayedSkinParts: DisplayedSkinParts, - val mainHand: MainHand -) : IncomingPacket() { - companion object : IncomingPacketCompanion(0x05, ClientSettingsPacket::class) { - override fun decode(msg: ByteBuf): ClientSettingsPacket { - return with(MinecraftDataTypes) { - val locale = msg.readString() - val viewDistance = msg.readByte() - - val chatMode = when (msg.readVarInt()) { - 0 -> ChatMode.ENABLED - 1 -> ChatMode.COMMANDS_ONLY - 2 -> ChatMode.HIDDEN - else -> throw PacketDecodingException() - } - - val chatColorsEnabled = msg.readBoolean() - - val skinFlags = msg.readByte() - val displayedSkinParts = DisplayedSkinParts( - cape = skinFlags.checkBit(0), - jacket = skinFlags.checkBit(1), - leftSleeve = skinFlags.checkBit(2), - rightSleeve = skinFlags.checkBit(3), - leftPantsLeg = skinFlags.checkBit(4), - rightPantsLeg = skinFlags.checkBit(5), - hat = skinFlags.checkBit(6) - ) - - val mainHand = when (msg.readVarInt()) { - 0 -> MainHand.LEFT - 1 -> MainHand.RIGHT - else -> throw PacketDecodingException() - } - - ClientSettingsPacket( - locale, - viewDistance, - chatMode, - chatColorsEnabled, - displayedSkinParts, - mainHand - ) - } - } - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/OutgoingPluginMessagePacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/OutgoingPluginMessagePacket.kt deleted file mode 100644 index 29d82bf..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/OutgoingPluginMessagePacket.kt +++ /dev/null @@ -1,22 +0,0 @@ -package space.blokk.net.protocols.play - -import io.netty.buffer.ByteBuf -import space.blokk.net.MinecraftDataTypes.writeString -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.OutgoingPacketCompanion - -/** - * Can be used by mods or plugins to communicate with a potentially modded client. - * Minecraft itself [also uses this for some things](https://wiki.vg/Plugin_channels#Channels_internal_to_Minecraft). - * - * @param channel Channel in which the message should be send. - * @param data Data which should be send. The ByteBuf needs to be released by the caller. - */ -data class OutgoingPluginMessagePacket(val channel: String, val data: ByteBuf) : OutgoingPacket() { - companion object : OutgoingPacketCompanion(0x19, OutgoingPluginMessagePacket::class) - - override fun encode(dst: ByteBuf) { - dst.writeString(channel) - dst.writeBytes(data) - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/PlayProtocol.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/PlayProtocol.kt deleted file mode 100644 index 2616742..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/PlayProtocol.kt +++ /dev/null @@ -1,13 +0,0 @@ -package space.blokk.net.protocols.play - -import space.blokk.net.protocols.Protocol - -object PlayProtocol : Protocol( - "PLAY", - JoinGamePacket, - ClientSettingsPacket, - IncomingPluginMessagePacket, - OutgoingPluginMessagePacket, - PlayerAbilitiesPacket, - ServerDifficultyPacket -) diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/ServerDifficultyPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/ServerDifficultyPacket.kt deleted file mode 100644 index e5c9704..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/ServerDifficultyPacket.kt +++ /dev/null @@ -1,26 +0,0 @@ -package space.blokk.net.protocols.play - -import io.netty.buffer.ByteBuf -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.OutgoingPacketCompanion -import space.blokk.worlds.WorldDifficulty - -/** - * Sets the difficulty shown in the pause menu. - */ -data class ServerDifficultyPacket(val difficulty: WorldDifficulty, val locked: Boolean) : OutgoingPacket() { - companion object : OutgoingPacketCompanion(0x0E, ServerDifficultyPacket::class) - - override fun encode(dst: ByteBuf) { - dst.writeByte( - when (difficulty) { - WorldDifficulty.PEACEFUL -> 0 - WorldDifficulty.EASY -> 1 - WorldDifficulty.NORMAL -> 2 - WorldDifficulty.HARD -> 3 - } - ) - - dst.writeBoolean(locked) - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/PingPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/PingPacket.kt deleted file mode 100644 index 99eb302..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/PingPacket.kt +++ /dev/null @@ -1,18 +0,0 @@ -package space.blokk.net.protocols.status - -import io.netty.buffer.ByteBuf -import space.blokk.net.protocols.IncomingPacket -import space.blokk.net.protocols.IncomingPacketCompanion - -/** - * Sent by the client to determine the RTT of the connection. The server responds with a [PongPacket]. - * - * @param payload A random value generated by the client. The [PongPacket] sent in response must use the same payload. - */ -data class PingPacket(val payload: Long) : IncomingPacket() { - companion object : IncomingPacketCompanion(0x01, PingPacket::class) { - override fun decode(msg: ByteBuf): PingPacket { - return PingPacket(msg.readLong()) - } - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/PongPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/PongPacket.kt deleted file mode 100644 index 06ea075..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/PongPacket.kt +++ /dev/null @@ -1,18 +0,0 @@ -package space.blokk.net.protocols.status - -import io.netty.buffer.ByteBuf -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.OutgoingPacketCompanion - -/** - * Sent by the server in response to a [PingPacket]. - * - * @param payload A random value generated by the client. This must be the same as in the corresponding [PingPacket]. - */ -data class PongPacket(val payload: Long) : OutgoingPacket() { - companion object : OutgoingPacketCompanion(0x01, PongPacket::class) - - override fun encode(dst: ByteBuf) { - dst.writeLong(payload) - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/RequestPacket.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/RequestPacket.kt deleted file mode 100644 index d241e7e..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/RequestPacket.kt +++ /dev/null @@ -1,18 +0,0 @@ -package space.blokk.net.protocols.status - -import io.netty.buffer.ByteBuf -import space.blokk.net.protocols.IncomingPacket -import space.blokk.net.protocols.IncomingPacketCompanion - -/** - * Sent by the client to request general information about the server. - * - * The server responds with a [ResponsePacket]. - * - * @see [space.blokk.net.events.ServerListInfoRequestEvent] - */ -class RequestPacket : IncomingPacket() { - companion object : IncomingPacketCompanion(0x00, RequestPacket::class) { - override fun decode(msg: ByteBuf): RequestPacket = RequestPacket() - } -} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/StatusProtocol.kt b/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/StatusProtocol.kt deleted file mode 100644 index 195f998..0000000 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/status/StatusProtocol.kt +++ /dev/null @@ -1,11 +0,0 @@ -package space.blokk.net.protocols.status - -import space.blokk.net.protocols.Protocol - -object StatusProtocol : Protocol( - "STATUS", - RequestPacket, - ResponsePacket, - PingPacket, - PongPacket -) diff --git a/blokk-api/src/test/kotlin/space/blokk/net/protocols/ProtocolsTest.kt b/blokk-api/src/test/kotlin/space/blokk/net/protocols/ProtocolsTest.kt deleted file mode 100644 index ffd54b4..0000000 --- a/blokk-api/src/test/kotlin/space/blokk/net/protocols/ProtocolsTest.kt +++ /dev/null @@ -1,12 +0,0 @@ -package space.blokk.net.protocols - -import org.spekframework.spek2.Spek -import org.spekframework.spek2.style.specification.describe - -object ProtocolsTest : Spek({ - describe("Protocols") { - it("are valid") { - Protocols.validate() - } - } -}) diff --git a/blokk-packet-codecs/build.gradle.kts b/blokk-packet-codecs/build.gradle.kts new file mode 100644 index 0000000..aa7ec09 --- /dev/null +++ b/blokk-packet-codecs/build.gradle.kts @@ -0,0 +1,25 @@ +plugins { + kotlin("jvm") +} + +group = rootProject.group +version = rootProject.version + +repositories { + mavenCentral() +} + +val nettyVersion = properties["version.netty"].toString() + +dependencies { + api(project(":blokk-api")) + + // Netty + api("io.netty:netty-buffer:${nettyVersion}") +} + +tasks { + compileKotlin { + kotlinOptions.jvmTarget = "1.8" + } +} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/MinecraftDataTypes.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/MinecraftDataTypes.kt similarity index 100% rename from blokk-api/src/main/kotlin/space/blokk/net/MinecraftDataTypes.kt rename to blokk-packet-codecs/src/main/kotlin/space/blokk/net/MinecraftDataTypes.kt diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakePacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakePacketCodec.kt new file mode 100644 index 0000000..7994fc3 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakePacketCodec.kt @@ -0,0 +1,15 @@ +package space.blokk.net.packets.handshaking + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.readString +import space.blokk.net.MinecraftDataTypes.readVarInt +import space.blokk.net.packets.IncomingPacketCodec + +object HandshakePacketCodec : IncomingPacketCodec(0x00, HandshakePacket::class) { + override fun decode(msg: ByteBuf): HandshakePacket = HandshakePacket( + protocolVersion = msg.readVarInt(), + serverAddress = msg.readString(), + serverPort = msg.readUnsignedShort(), + loginAttempt = msg.readVarInt() == 2 + ) +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakingProtocol.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakingProtocol.kt new file mode 100644 index 0000000..937ffc1 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakingProtocol.kt @@ -0,0 +1,5 @@ +package space.blokk.net.packets.handshaking + +import space.blokk.net.packets.Protocol + +object HandshakingProtocol : Protocol("HANDSHAKING", HandshakePacketCodec) diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/DisconnectPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/DisconnectPacketCodec.kt new file mode 100644 index 0000000..6761ae7 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/DisconnectPacketCodec.kt @@ -0,0 +1,11 @@ +package space.blokk.net.packets.login + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.writeString +import space.blokk.net.packets.OutgoingPacketCodec + +object DisconnectPacketCodec : OutgoingPacketCodec(0x00, DisconnectPacket::class) { + override fun DisconnectPacket.encode(dst: ByteBuf) { + dst.writeString(reason.toJson()) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/EncryptionRequestPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/EncryptionRequestPacketCodec.kt new file mode 100644 index 0000000..f5c25b8 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/EncryptionRequestPacketCodec.kt @@ -0,0 +1,17 @@ +package space.blokk.net.packets.login + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.writeString +import space.blokk.net.MinecraftDataTypes.writeVarInt +import space.blokk.net.packets.OutgoingPacketCodec + +object EncryptionRequestPacketCodec : + OutgoingPacketCodec(0x01, EncryptionRequestPacket::class) { + override fun EncryptionRequestPacket.encode(dst: ByteBuf) { + dst.writeString("") // Required for legacy reasons + dst.writeVarInt(publicKey.size) + dst.writeBytes(publicKey) + dst.writeVarInt(verifyToken.size) + dst.writeBytes(verifyToken) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/EncryptionResponsePacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/EncryptionResponsePacketCodec.kt new file mode 100644 index 0000000..8ad2f0f --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/EncryptionResponsePacketCodec.kt @@ -0,0 +1,20 @@ +package space.blokk.net.packets.login + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.readVarInt +import space.blokk.net.packets.IncomingPacketCodec + +object EncryptionResponsePacketCodec : + IncomingPacketCodec(0x01, EncryptionResponsePacket::class) { + override fun decode(msg: ByteBuf): EncryptionResponsePacket { + val sharedSecretLength = msg.readVarInt() + val sharedSecret = ByteArray(sharedSecretLength) + msg.readBytes(sharedSecret) + + val verifyTokenLength = msg.readVarInt() + val verifyToken = ByteArray(verifyTokenLength) + msg.readBytes(verifyToken) + + return EncryptionResponsePacket(sharedSecret, verifyToken) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginPluginRequestPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginPluginRequestPacketCodec.kt new file mode 100644 index 0000000..a168eb4 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginPluginRequestPacketCodec.kt @@ -0,0 +1,15 @@ +package space.blokk.net.packets.login + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.writeString +import space.blokk.net.MinecraftDataTypes.writeVarInt +import space.blokk.net.packets.OutgoingPacketCodec + +object LoginPluginRequestPacketCodec : + OutgoingPacketCodec(0x04, LoginPluginRequestPacket::class) { + override fun LoginPluginRequestPacket.encode(dst: ByteBuf) { + dst.writeVarInt(messageID) + dst.writeString(channel) + dst.writeBytes(data) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginPluginResponsePacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginPluginResponsePacketCodec.kt new file mode 100644 index 0000000..969c1d5 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginPluginResponsePacketCodec.kt @@ -0,0 +1,20 @@ +package space.blokk.net.packets.login + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.readVarInt +import space.blokk.net.packets.IncomingPacketCodec + +object LoginPluginResponsePacketCodec : + IncomingPacketCodec(0x02, LoginPluginResponsePacket::class) { + override fun decode(msg: ByteBuf): LoginPluginResponsePacket { + val messageID = msg.readVarInt() + val successful = msg.readBoolean() + + // TODO: Test this + val data = + if (successful) ByteArray(msg.readableBytes()).also { msg.readBytes(it) } + else null + + return LoginPluginResponsePacket(messageID, data) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginProtocol.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginProtocol.kt new file mode 100644 index 0000000..02a5196 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginProtocol.kt @@ -0,0 +1,15 @@ +package space.blokk.net.packets.login + +import space.blokk.net.packets.Protocol + +object LoginProtocol : Protocol( + "LOGIN", + DisconnectPacketCodec, + EncryptionRequestPacketCodec, + EncryptionResponsePacketCodec, + LoginPluginRequestPacketCodec, + LoginPluginResponsePacketCodec, + LoginStartPacketCodec, + LoginSuccessPacketCodec, + SetCompressionPacketCodec +) diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginStartPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginStartPacketCodec.kt new file mode 100644 index 0000000..1123cb9 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginStartPacketCodec.kt @@ -0,0 +1,9 @@ +package space.blokk.net.packets.login + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.readString +import space.blokk.net.packets.IncomingPacketCodec + +object LoginStartPacketCodec : IncomingPacketCodec(0x00, LoginStartPacket::class) { + override fun decode(msg: ByteBuf): LoginStartPacket = LoginStartPacket(msg.readString()) +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginSuccessPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginSuccessPacketCodec.kt new file mode 100644 index 0000000..7853362 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/LoginSuccessPacketCodec.kt @@ -0,0 +1,12 @@ +package space.blokk.net.packets.login + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.writeString +import space.blokk.net.packets.OutgoingPacketCodec + +object LoginSuccessPacketCodec : OutgoingPacketCodec(0x02, LoginSuccessPacket::class) { + override fun LoginSuccessPacket.encode(dst: ByteBuf) { + dst.writeString(uuid.toString()) + dst.writeString(username) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/SetCompressionPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/SetCompressionPacketCodec.kt new file mode 100644 index 0000000..a9e5be5 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/login/SetCompressionPacketCodec.kt @@ -0,0 +1,11 @@ +package space.blokk.net.packets.login + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.writeVarInt +import space.blokk.net.packets.OutgoingPacketCodec + +object SetCompressionPacketCodec : OutgoingPacketCodec(0x03, SetCompressionPacket::class) { + override fun SetCompressionPacket.encode(dst: ByteBuf) { + dst.writeVarInt(threshold) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/ClientSettingsPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/ClientSettingsPacketCodec.kt new file mode 100644 index 0000000..689b583 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/ClientSettingsPacketCodec.kt @@ -0,0 +1,53 @@ +package space.blokk.net.packets.play + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.readString +import space.blokk.net.MinecraftDataTypes.readVarInt +import space.blokk.net.PacketDecodingException +import space.blokk.net.packets.IncomingPacketCodec +import space.blokk.players.ChatMode +import space.blokk.players.DisplayedSkinParts +import space.blokk.players.MainHand +import space.blokk.utils.checkBit + +object ClientSettingsPacketCodec : IncomingPacketCodec(0x05, ClientSettingsPacket::class) { + override fun decode(msg: ByteBuf): ClientSettingsPacket { + val locale = msg.readString() + val viewDistance = msg.readByte() + + val chatMode = when (msg.readVarInt()) { + 0 -> ChatMode.ENABLED + 1 -> ChatMode.COMMANDS_ONLY + 2 -> ChatMode.HIDDEN + else -> throw PacketDecodingException() + } + + val chatColorsEnabled = msg.readBoolean() + + val skinFlags = msg.readByte() + val displayedSkinParts = DisplayedSkinParts( + cape = skinFlags.checkBit(0), + jacket = skinFlags.checkBit(1), + leftSleeve = skinFlags.checkBit(2), + rightSleeve = skinFlags.checkBit(3), + leftPantsLeg = skinFlags.checkBit(4), + rightPantsLeg = skinFlags.checkBit(5), + hat = skinFlags.checkBit(6) + ) + + val mainHand = when (msg.readVarInt()) { + 0 -> MainHand.LEFT + 1 -> MainHand.RIGHT + else -> throw PacketDecodingException() + } + + return ClientSettingsPacket( + locale, + viewDistance, + chatMode, + chatColorsEnabled, + displayedSkinParts, + mainHand + ) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/IncomingPluginMessagePacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/IncomingPluginMessagePacketCodec.kt new file mode 100644 index 0000000..a2700b8 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/IncomingPluginMessagePacketCodec.kt @@ -0,0 +1,17 @@ +package space.blokk.net.packets.play + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.readString +import space.blokk.net.packets.IncomingPacketCodec + +object IncomingPluginMessagePacketCodec : + IncomingPacketCodec(0x0B, IncomingPluginMessagePacket::class) { + override fun decode(msg: ByteBuf): IncomingPluginMessagePacket { + val channel = msg.readString() + + // TODO: Test this + val data = ByteArray(msg.readableBytes()).also { msg.readBytes(it) } + + return IncomingPluginMessagePacket(channel, data) + } +} diff --git a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/JoinGamePacket.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/JoinGamePacketCodec.kt similarity index 50% rename from blokk-api/src/main/kotlin/space/blokk/net/protocols/play/JoinGamePacket.kt rename to blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/JoinGamePacketCodec.kt index cb155cc..3f4ef7c 100644 --- a/blokk-api/src/main/kotlin/space/blokk/net/protocols/play/JoinGamePacket.kt +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/JoinGamePacketCodec.kt @@ -1,45 +1,15 @@ -package space.blokk.net.protocols.play +package space.blokk.net.packets.play import io.netty.buffer.ByteBuf import space.blokk.net.MinecraftDataTypes.writeString import space.blokk.net.MinecraftDataTypes.writeVarInt -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.OutgoingPacketCompanion +import space.blokk.net.packets.OutgoingPacketCodec import space.blokk.players.GameMode import space.blokk.worlds.WorldDimension import space.blokk.worlds.WorldType -/** - * Sent by the server after the client logged in. - * - * @param entityID ID of the player entity. - * @param gameMode Game mode of the player. - * @param hardcore Whether the player is in hardcore mode. - * @param worldDimension Dimension of the world the player joins. - * @param worldSeedHash First 8 bytes of the SHA-256 hash of the world's seed. - * @param worldType Type of the world the player joins. - * @param viewDistance Maximum view distance. - * @param reducedDebugInfo Whether the debug screen shows only reduced info. - * @param respawnScreenEnabled Whether the respawn screen is shown when the player dies. - */ -data class JoinGamePacket( - val entityID: Int, - val gameMode: GameMode, - val hardcore: Boolean, - val worldDimension: WorldDimension, - val worldSeedHash: Long, - val worldType: WorldType, - val viewDistance: Byte, - val reducedDebugInfo: Boolean, - val respawnScreenEnabled: Boolean -) : OutgoingPacket() { - companion object : OutgoingPacketCompanion(0x26, JoinGamePacket::class) - - init { - if (viewDistance < 2 || viewDistance > 32) throw IllegalArgumentException("viewDistance must be between 2 and 32.") - } - - override fun encode(dst: ByteBuf) { +object JoinGamePacketCodec : OutgoingPacketCodec(0x26, JoinGamePacket::class) { + override fun JoinGamePacket.encode(dst: ByteBuf) { dst.writeInt(entityID) var gameMode = when (gameMode) { GameMode.SURVIVAL -> 0 diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/OutgoingPluginMessagePacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/OutgoingPluginMessagePacketCodec.kt new file mode 100644 index 0000000..e239604 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/OutgoingPluginMessagePacketCodec.kt @@ -0,0 +1,13 @@ +package space.blokk.net.packets.play + +import io.netty.buffer.ByteBuf +import space.blokk.net.MinecraftDataTypes.writeString +import space.blokk.net.packets.OutgoingPacketCodec + +object OutgoingPluginMessagePacketCodec : + OutgoingPacketCodec(0x19, OutgoingPluginMessagePacket::class) { + override fun OutgoingPluginMessagePacket.encode(dst: ByteBuf) { + dst.writeString(channel) + dst.writeBytes(data) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/PlayProtocol.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/PlayProtocol.kt new file mode 100644 index 0000000..071b9f5 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/PlayProtocol.kt @@ -0,0 +1,13 @@ +package space.blokk.net.packets.play + +import space.blokk.net.packets.Protocol + +object PlayProtocol : Protocol( + "PLAY", + ClientSettingsPacketCodec, + IncomingPluginMessagePacketCodec, + JoinGamePacketCodec, + OutgoingPluginMessagePacketCodec, + PlayerAbilitiesPacketCodec, + ServerDifficultyPacketCodec +) diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/PlayerAbilitiesPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/PlayerAbilitiesPacketCodec.kt new file mode 100644 index 0000000..022f2b5 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/PlayerAbilitiesPacketCodec.kt @@ -0,0 +1,18 @@ +package space.blokk.net.packets.play + +import io.netty.buffer.ByteBuf +import space.blokk.net.packets.OutgoingPacketCodec + +object PlayerAbilitiesPacketCodec : OutgoingPacketCodec(0x32, PlayerAbilitiesPacket::class) { + override fun PlayerAbilitiesPacket.encode(dst: ByteBuf) { + var flags = 0 + if (invulnerable) flags = flags and 0x01 + if (flying) flags = flags and 0x02 + if (flyingAllowed) flags = flags and 0x04 + if (instantlyBreakBlocks) flags = flags and 0x08 + + dst.writeByte(flags) + dst.writeFloat(flyingSpeed) + dst.writeFloat(fieldOfView) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/ServerDifficultyPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/ServerDifficultyPacketCodec.kt new file mode 100644 index 0000000..c3892ee --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/play/ServerDifficultyPacketCodec.kt @@ -0,0 +1,20 @@ +package space.blokk.net.packets.play + +import io.netty.buffer.ByteBuf +import space.blokk.net.packets.OutgoingPacketCodec +import space.blokk.worlds.WorldDifficulty + +object ServerDifficultyPacketCodec : OutgoingPacketCodec(0x0E, ServerDifficultyPacket::class) { + override fun ServerDifficultyPacket.encode(dst: ByteBuf) { + dst.writeByte( + when (difficulty) { + WorldDifficulty.PEACEFUL -> 0 + WorldDifficulty.EASY -> 1 + WorldDifficulty.NORMAL -> 2 + WorldDifficulty.HARD -> 3 + } + ) + + dst.writeBoolean(locked) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/PingPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/PingPacketCodec.kt new file mode 100644 index 0000000..ac65b74 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/PingPacketCodec.kt @@ -0,0 +1,8 @@ +package space.blokk.net.packets.status + +import io.netty.buffer.ByteBuf +import space.blokk.net.packets.IncomingPacketCodec + +object PingPacketCodec : IncomingPacketCodec(0x01, PingPacket::class) { + override fun decode(msg: ByteBuf): PingPacket = PingPacket(msg.readLong()) +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/PongPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/PongPacketCodec.kt new file mode 100644 index 0000000..e2349e9 --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/PongPacketCodec.kt @@ -0,0 +1,10 @@ +package space.blokk.net.packets.status + +import io.netty.buffer.ByteBuf +import space.blokk.net.packets.OutgoingPacketCodec + +object PongPacketCodec : OutgoingPacketCodec(0x01, PongPacket::class) { + override fun PongPacket.encode(dst: ByteBuf) { + dst.writeLong(payload) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/RequestPacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/RequestPacketCodec.kt new file mode 100644 index 0000000..12b037a --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/RequestPacketCodec.kt @@ -0,0 +1,8 @@ +package space.blokk.net.packets.status + +import io.netty.buffer.ByteBuf +import space.blokk.net.packets.IncomingPacketCodec + +object RequestPacketCodec : IncomingPacketCodec(0x00, RequestPacket::class) { + override fun decode(msg: ByteBuf): RequestPacket = RequestPacket() +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/ResponsePacketCodec.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/ResponsePacketCodec.kt new file mode 100644 index 0000000..fa92c0b --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/ResponsePacketCodec.kt @@ -0,0 +1,22 @@ +package space.blokk.net.packets.status + +import io.netty.buffer.ByteBuf +import space.blokk.Blokk +import space.blokk.net.MinecraftDataTypes.writeString +import space.blokk.net.packets.OutgoingPacketCodec +import space.blokk.utils.toJson + +object ResponsePacketCodec : OutgoingPacketCodec(0x00, ResponsePacket::class) { + override fun ResponsePacket.encode(dst: ByteBuf) { + dst.writeString( + Blokk.json.toJson(mapOf( + "version" to mapOf( + "name" to versionName, + "protocol" to protocolVersion + ), + "players" to players, + "description" to description, + "favicon" to favicon?.let { "data:image/png;base64,$it" } + ))) + } +} diff --git a/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/StatusProtocol.kt b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/StatusProtocol.kt new file mode 100644 index 0000000..eb1e74b --- /dev/null +++ b/blokk-packet-codecs/src/main/kotlin/space/blokk/net/packets/status/StatusProtocol.kt @@ -0,0 +1,11 @@ +package space.blokk.net.packets.status + +import space.blokk.net.packets.Protocol + +object StatusProtocol : Protocol( + "STATUS", + PingPacketCodec, + RequestPacketCodec, + PongPacketCodec, + ResponsePacketCodec +) diff --git a/blokk-server/build.gradle.kts b/blokk-server/build.gradle.kts index ab0e915..7a8029a 100644 --- a/blokk-server/build.gradle.kts +++ b/blokk-server/build.gradle.kts @@ -1,6 +1,5 @@ plugins { kotlin("jvm") - kotlin("kapt") id("com.github.johnrengelman.shadow") version "6.0.0" } @@ -24,6 +23,7 @@ dependencies { // Blokk implementation(project(":blokk-api")) + implementation(project(":blokk-packet-codecs")) // Logging implementation("org.slf4j:slf4j-api:${slf4jVersion}") @@ -42,7 +42,6 @@ dependencies { implementation("com.squareup.okhttp3:okhttp:4.8.1") implementation("com.sksamuel.hoplite:hoplite-core:1.3.3") implementation("com.sksamuel.hoplite:hoplite-yaml:1.3.3") - kapt("com.squareup.moshi:moshi-kotlin-codegen:${moshiVersion}") } tasks { diff --git a/blokk-server/src/main/kotlin/space/blokk/BlokkServer.kt b/blokk-server/src/main/kotlin/space/blokk/BlokkServer.kt index 517918f..130aa3d 100644 --- a/blokk-server/src/main/kotlin/space/blokk/BlokkServer.kt +++ b/blokk-server/src/main/kotlin/space/blokk/BlokkServer.kt @@ -5,21 +5,14 @@ import com.sksamuel.hoplite.ConfigLoader import com.sksamuel.hoplite.ConfigSource import kotlinx.coroutines.CoroutineName import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.launch -import space.blokk.chat.ChatComponent -import space.blokk.chat.TextComponent import space.blokk.config.BlokkConfig import space.blokk.events.EventBus -import space.blokk.events.EventHandler -import space.blokk.events.Listener import space.blokk.logging.Logger import space.blokk.net.BlokkSocketServer -import space.blokk.net.events.ServerListInfoRequestEvent import space.blokk.server.Server import space.blokk.server.events.ServerEvent import space.blokk.utils.EncryptionUtils import space.blokk.utils.Ticker -import space.blokk.utils.delayTicks import java.io.File import java.security.KeyPair import kotlin.system.exitProcess @@ -105,22 +98,7 @@ class BlokkServer internal constructor() : Server { @JvmStatic fun main(args: Array) { - val server = BlokkServer() - Blokk.sessions.registerListener(object : Listener { - @EventHandler - fun onServerListInfoRequest(event: ServerListInfoRequestEvent) { - event.response = event.response.copy( - description = TextComponent( - event.session.address.hostAddress, - bold = true, - underlined = true, - color = ChatComponent.Color.RED - ) - ) - } - }) - - server.start() + BlokkServer().start() } } } diff --git a/blokk-server/src/main/kotlin/space/blokk/net/BlokkChannelInitializer.kt b/blokk-server/src/main/kotlin/space/blokk/net/BlokkChannelInitializer.kt index d2a9be6..164d571 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/BlokkChannelInitializer.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/BlokkChannelInitializer.kt @@ -23,7 +23,7 @@ class BlokkChannelInitializer(private val blokkSocketServer: BlokkSocketServer) channel.pipeline() .addLast("idle", IdleStateHandler(20, 15, 0)) .addLast("framing", FramingCodec()) - .addLast("packets", PacketCodec(session)) + .addLast("packets", PacketMessageCodec(session)) .addLast("handler", PacketMessageHandler(session)) } diff --git a/blokk-server/src/main/kotlin/space/blokk/net/BlokkSession.kt b/blokk-server/src/main/kotlin/space/blokk/net/BlokkSession.kt index 652c0d5..b3c9554 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/BlokkSession.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/BlokkSession.kt @@ -10,13 +10,13 @@ import space.blokk.logging.Logger import space.blokk.net.events.PacketReceivedEvent import space.blokk.net.events.PacketSendEvent import space.blokk.net.events.SessionEvent -import space.blokk.net.protocols.OutgoingPacket -import space.blokk.net.protocols.Protocol -import space.blokk.net.protocols.handshaking.HandshakingProtocol -import space.blokk.net.protocols.login.DisconnectPacket -import space.blokk.net.protocols.login.LoginProtocol -import space.blokk.net.protocols.play.OutgoingPluginMessagePacket -import space.blokk.net.protocols.play.PlayProtocol +import space.blokk.net.packets.OutgoingPacket +import space.blokk.net.packets.Protocol +import space.blokk.net.packets.handshaking.HandshakingProtocol +import space.blokk.net.packets.login.DisconnectPacket +import space.blokk.net.packets.login.LoginProtocol +import space.blokk.net.packets.play.OutgoingPluginMessagePacket +import space.blokk.net.packets.play.PlayProtocol import space.blokk.server.events.SessionInitializedEvent import space.blokk.utils.awaitSuspending import java.net.InetAddress @@ -107,7 +107,7 @@ class BlokkSession(private val channel: Channel) : Session { logger trace { "Sending packet: $packet" } eventBus.emit(PacketSendEvent(this@BlokkSession, packet)).ifNotCancelled { try { - channel.writeAndFlush(PacketMessage(this@BlokkSession, it.packet)).awaitSuspending() + channel.writeAndFlush(OutgoingPacketMessage(this@BlokkSession, it.packet)).awaitSuspending() } catch (t: Throwable) { logger.error("Packet send failed:", t) } diff --git a/blokk-server/src/main/kotlin/space/blokk/net/DefaultPacketReceivedEventHandler.kt b/blokk-server/src/main/kotlin/space/blokk/net/DefaultPacketReceivedEventHandler.kt index 8f55848..2b4fd50 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/DefaultPacketReceivedEventHandler.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/DefaultPacketReceivedEventHandler.kt @@ -1,22 +1,21 @@ package space.blokk.net -import space.blokk.net.protocols.IncomingPacket -import space.blokk.net.protocols.IncomingPacketCompanion -import space.blokk.net.protocols.handshaking.HandshakingProtocol -import space.blokk.net.protocols.handshaking.HandshakingProtocolHandler -import space.blokk.net.protocols.login.LoginProtocol -import space.blokk.net.protocols.login.LoginProtocolHandler -import space.blokk.net.protocols.play.PlayProtocol -import space.blokk.net.protocols.play.PlayProtocolHandler -import space.blokk.net.protocols.status.StatusProtocol -import space.blokk.net.protocols.status.StatusProtocolHandler - -open class ProtocolPacketReceivedEventHandler(handlers: Map, PacketReceivedEventHandler>) { - private val handlers = handlers.mapKeys { it.key.packetType } +import space.blokk.net.packets.IncomingPacket +import space.blokk.net.packets.handshaking.HandshakingProtocol +import space.blokk.net.packets.handshaking.HandshakingProtocolHandler +import space.blokk.net.packets.login.LoginProtocol +import space.blokk.net.packets.login.LoginProtocolHandler +import space.blokk.net.packets.play.PlayProtocol +import space.blokk.net.packets.play.PlayProtocolHandler +import space.blokk.net.packets.status.StatusProtocol +import space.blokk.net.packets.status.StatusProtocolHandler +import kotlin.reflect.KClass +open class ProtocolPacketReceivedEventHandler(private val handlers: Map, PacketReceivedEventHandler>) { suspend fun handle(session: BlokkSession, packet: IncomingPacket) { @Suppress("UNCHECKED_CAST") - val handler = handlers[packet::class] as PacketReceivedEventHandler? + val handler: PacketReceivedEventHandler? = + handlers[packet::class] as PacketReceivedEventHandler? handler?.handle(session, packet) } } diff --git a/blokk-server/src/main/kotlin/space/blokk/net/FramingCodec.kt b/blokk-server/src/main/kotlin/space/blokk/net/FramingCodec.kt index a007cfe..49147f6 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/FramingCodec.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/FramingCodec.kt @@ -3,31 +3,32 @@ package space.blokk.net import io.netty.buffer.ByteBuf import io.netty.channel.ChannelHandlerContext import io.netty.handler.codec.ByteToMessageCodec +import space.blokk.net.MinecraftDataTypes.readVarInt +import space.blokk.net.MinecraftDataTypes.varIntReadable +import space.blokk.net.MinecraftDataTypes.writeVarInt class FramingCodec : ByteToMessageCodec() { private var currentLength: Int? = null override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: ByteBuf) { - with(MinecraftDataTypes) { out.writeVarInt(msg.readableBytes()) } + out.writeVarInt(msg.readableBytes()) msg.readerIndex(0) out.writeBytes(msg) } override fun decode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList) { - with(MinecraftDataTypes) { - var length = currentLength + var length = currentLength - if (length == null) { - if (msg.varIntReadable()) { - length = msg.readVarInt() - currentLength = length - } else return - } + if (length == null) { + if (msg.varIntReadable()) { + length = msg.readVarInt() + currentLength = length + } else return + } - if (msg.readableBytes() >= length) { - out.add(msg.readBytes(length)) - currentLength = null - } + if (msg.readableBytes() >= length) { + out.add(msg.readBytes(length)) + currentLength = null } } } diff --git a/blokk-server/src/main/kotlin/space/blokk/net/JoinProcedure.kt b/blokk-server/src/main/kotlin/space/blokk/net/JoinProcedure.kt index 711b040..b2ab9c8 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/JoinProcedure.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/JoinProcedure.kt @@ -4,14 +4,14 @@ import io.netty.buffer.Unpooled import space.blokk.BlokkServer import space.blokk.chat.TextComponent import space.blokk.net.MinecraftDataTypes.writeString -import space.blokk.net.protocols.login.EncryptionRequestPacket -import space.blokk.net.protocols.login.EncryptionResponsePacket -import space.blokk.net.protocols.login.LoginStartPacket -import space.blokk.net.protocols.login.LoginSuccessPacket -import space.blokk.net.protocols.play.JoinGamePacket -import space.blokk.net.protocols.play.PlayProtocol -import space.blokk.net.protocols.play.PlayerAbilitiesPacket -import space.blokk.net.protocols.play.ServerDifficultyPacket +import space.blokk.net.packets.login.EncryptionRequestPacket +import space.blokk.net.packets.login.EncryptionResponsePacket +import space.blokk.net.packets.login.LoginStartPacket +import space.blokk.net.packets.login.LoginSuccessPacket +import space.blokk.net.packets.play.JoinGamePacket +import space.blokk.net.packets.play.PlayProtocol +import space.blokk.net.packets.play.PlayerAbilitiesPacket +import space.blokk.net.packets.play.ServerDifficultyPacket import space.blokk.players.GameMode import space.blokk.utils.AuthenticationHelper import space.blokk.utils.EncryptionUtils diff --git a/blokk-server/src/main/kotlin/space/blokk/net/OutgoingPacketMessage.kt b/blokk-server/src/main/kotlin/space/blokk/net/OutgoingPacketMessage.kt new file mode 100644 index 0000000..1ddda87 --- /dev/null +++ b/blokk-server/src/main/kotlin/space/blokk/net/OutgoingPacketMessage.kt @@ -0,0 +1,17 @@ +package space.blokk.net + +import io.netty.buffer.ByteBuf +import space.blokk.net.packets.IncomingPacket +import space.blokk.net.packets.OutgoingPacket +import space.blokk.net.packets.OutgoingPacketCodec +import space.blokk.net.packets.Packet + +abstract class PacketMessage(val session: BlokkSession, val packet: T) + +class OutgoingPacketMessage(session: BlokkSession, packet: T) : PacketMessage(session, packet) { + @Suppress("UNCHECKED_CAST") + val packetCodec = session.currentProtocol.getCodecByType(packet::class) as OutgoingPacketCodec + fun encodePacket(dst: ByteBuf) = with(packetCodec) { packet.encode(dst) } +} + +class IncomingPacketMessage(session: BlokkSession, packet: T) : PacketMessage(session, packet) diff --git a/blokk-server/src/main/kotlin/space/blokk/net/PacketMessage.kt b/blokk-server/src/main/kotlin/space/blokk/net/PacketMessage.kt deleted file mode 100644 index f66467f..0000000 --- a/blokk-server/src/main/kotlin/space/blokk/net/PacketMessage.kt +++ /dev/null @@ -1,15 +0,0 @@ -package space.blokk.net - -import space.blokk.net.protocols.Packet -import space.blokk.net.protocols.PacketCompanion - -data class PacketMessage(val session: BlokkSession, val packet: T) { - val packetCompanion by lazy { - @Suppress("UNCHECKED_CAST") - session.currentProtocol.packetCompanionsByPacketType[packet::class] as PacketCompanion? - ?: throw Exception( - "No packet companion found for this packet type. " + - "This can happen if the packet is not part of the current protocol." - ) - } -} diff --git a/blokk-server/src/main/kotlin/space/blokk/net/PacketCodec.kt b/blokk-server/src/main/kotlin/space/blokk/net/PacketMessageCodec.kt similarity index 56% rename from blokk-server/src/main/kotlin/space/blokk/net/PacketCodec.kt rename to blokk-server/src/main/kotlin/space/blokk/net/PacketMessageCodec.kt index 90a0f82..ce06d6e 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/PacketCodec.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/PacketMessageCodec.kt @@ -3,10 +3,11 @@ package space.blokk.net import io.netty.buffer.ByteBuf import io.netty.channel.ChannelHandlerContext import io.netty.handler.codec.MessageToMessageCodec -import space.blokk.net.protocols.OutgoingPacket +import space.blokk.net.MinecraftDataTypes.readVarInt +import space.blokk.net.MinecraftDataTypes.writeVarInt import java.io.IOException -class PacketCodec(private val session: BlokkSession) : MessageToMessageCodec>() { +class PacketMessageCodec(private val session: BlokkSession) : MessageToMessageCodec>() { override fun channelActive(ctx: ChannelHandlerContext) { session.onConnect() } @@ -16,21 +17,22 @@ class PacketCodec(private val session: BlokkSession) : MessageToMessageCodec, out: MutableList) { - if (msg.packet !is OutgoingPacket) throw Error("Only clientbound packets are allowed. This should never happen.") - val buffer = ctx.alloc().buffer() - with(MinecraftDataTypes) { buffer.writeVarInt(msg.packetCompanion.id) } - msg.packet.encode(buffer) - out.add(buffer) + if (msg !is OutgoingPacketMessage<*>) throw UnsupportedOperationException("Only outgoing packets can get encoded") + + val dst = ctx.alloc().buffer() + dst.writeVarInt(msg.packetCodec.id) + msg.encodePacket(dst) + out.add(dst) } override fun decode(ctx: ChannelHandlerContext, msg: ByteBuf, out: MutableList) { - val packetID = with(MinecraftDataTypes) { msg.readVarInt() } + val packetID = msg.readVarInt() val data = msg.readBytes(msg.readableBytes()) - val packetCompanion = session.currentProtocol.incomingPacketsByID[packetID] + val codec = session.currentProtocol.incomingPacketCodecsByID[packetID] ?: throw IOException("Client sent an unknown packet (ID: $packetID)") - out.add(PacketMessage(session, packetCompanion.decode(data))) + out.add(IncomingPacketMessage(session, codec.decode(data))) } override fun exceptionCaught(ctx: ChannelHandlerContext, cause: Throwable) { diff --git a/blokk-server/src/main/kotlin/space/blokk/net/PacketMessageHandler.kt b/blokk-server/src/main/kotlin/space/blokk/net/PacketMessageHandler.kt index 89a8fce..e775c2c 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/PacketMessageHandler.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/PacketMessageHandler.kt @@ -4,11 +4,10 @@ import io.netty.channel.ChannelHandlerContext import io.netty.channel.SimpleChannelInboundHandler import kotlinx.coroutines.launch import space.blokk.net.events.PacketReceivedEvent -import space.blokk.net.protocols.IncomingPacket -class PacketMessageHandler(private val session: BlokkSession) : SimpleChannelInboundHandler>() { - override fun channelRead0(ctx: ChannelHandlerContext, msg: PacketMessage<*>) { - if (msg.packet !is IncomingPacket) throw Error("Only serverbound packets are allowed. This should never happen.") +class PacketMessageHandler(private val session: BlokkSession) : + SimpleChannelInboundHandler>() { + override fun channelRead0(ctx: ChannelHandlerContext, msg: IncomingPacketMessage<*>) { session.logger.trace { "Packet received: ${msg.packet}" } session.scope.launch { session.eventBus.emit(PacketReceivedEvent(session, msg.packet)) } } diff --git a/blokk-server/src/main/kotlin/space/blokk/net/protocols/handshaking/HandshakingProtocolHandler.kt b/blokk-server/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakingProtocolHandler.kt similarity index 54% rename from blokk-server/src/main/kotlin/space/blokk/net/protocols/handshaking/HandshakingProtocolHandler.kt rename to blokk-server/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakingProtocolHandler.kt index bcaabb6..6b11a53 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/protocols/handshaking/HandshakingProtocolHandler.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/packets/handshaking/HandshakingProtocolHandler.kt @@ -1,12 +1,12 @@ -package space.blokk.net.protocols.handshaking +package space.blokk.net.packets.handshaking import space.blokk.net.PacketReceivedEventHandler import space.blokk.net.ProtocolPacketReceivedEventHandler -import space.blokk.net.protocols.login.LoginProtocol -import space.blokk.net.protocols.status.StatusProtocol +import space.blokk.net.packets.login.LoginProtocol +import space.blokk.net.packets.status.StatusProtocol object HandshakingProtocolHandler : ProtocolPacketReceivedEventHandler(mapOf( - HandshakePacket to PacketReceivedEventHandler.of { session, packet -> + HandshakePacket::class to PacketReceivedEventHandler.of { session, packet -> session.currentProtocol = if (packet.loginAttempt) LoginProtocol else StatusProtocol } )) diff --git a/blokk-server/src/main/kotlin/space/blokk/net/protocols/login/EncryptionResponsePacketHandler.kt b/blokk-server/src/main/kotlin/space/blokk/net/packets/login/EncryptionResponsePacketHandler.kt similarity index 93% rename from blokk-server/src/main/kotlin/space/blokk/net/protocols/login/EncryptionResponsePacketHandler.kt rename to blokk-server/src/main/kotlin/space/blokk/net/packets/login/EncryptionResponsePacketHandler.kt index 3b6e334..a50d440 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/protocols/login/EncryptionResponsePacketHandler.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/packets/login/EncryptionResponsePacketHandler.kt @@ -1,4 +1,4 @@ -package space.blokk.net.protocols.login +package space.blokk.net.packets.login import space.blokk.net.BlokkSession import space.blokk.net.PacketReceivedEventHandler diff --git a/blokk-server/src/main/kotlin/space/blokk/net/protocols/login/LoginProtocolHandler.kt b/blokk-server/src/main/kotlin/space/blokk/net/packets/login/LoginProtocolHandler.kt similarity index 54% rename from blokk-server/src/main/kotlin/space/blokk/net/protocols/login/LoginProtocolHandler.kt rename to blokk-server/src/main/kotlin/space/blokk/net/packets/login/LoginProtocolHandler.kt index 79733e2..6fa360a 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/protocols/login/LoginProtocolHandler.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/packets/login/LoginProtocolHandler.kt @@ -1,9 +1,11 @@ -package space.blokk.net.protocols.login +package space.blokk.net.packets.login import space.blokk.net.ProtocolPacketReceivedEventHandler // NOTE: PacketReceivedEventHandler.of MUST have T specified correctly, otherwise the code breaks at runtime -object LoginProtocolHandler : ProtocolPacketReceivedEventHandler(mapOf( - LoginStartPacket to LoginStartPacketHandler, - EncryptionResponsePacket to EncryptionResponsePacketHandler -)) +object LoginProtocolHandler : ProtocolPacketReceivedEventHandler( + mapOf( + LoginStartPacket::class to LoginStartPacketHandler, + EncryptionResponsePacket::class to EncryptionResponsePacketHandler + ) +) diff --git a/blokk-server/src/main/kotlin/space/blokk/net/protocols/login/LoginStartPacketHandler.kt b/blokk-server/src/main/kotlin/space/blokk/net/packets/login/LoginStartPacketHandler.kt similarity index 92% rename from blokk-server/src/main/kotlin/space/blokk/net/protocols/login/LoginStartPacketHandler.kt rename to blokk-server/src/main/kotlin/space/blokk/net/packets/login/LoginStartPacketHandler.kt index 5de6547..f0e4a0e 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/protocols/login/LoginStartPacketHandler.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/packets/login/LoginStartPacketHandler.kt @@ -1,4 +1,4 @@ -package space.blokk.net.protocols.login +package space.blokk.net.packets.login import space.blokk.net.BlokkSession import space.blokk.net.PacketReceivedEventHandler diff --git a/blokk-server/src/main/kotlin/space/blokk/net/protocols/play/ClientSettingsPacketHandler.kt b/blokk-server/src/main/kotlin/space/blokk/net/packets/play/ClientSettingsPacketHandler.kt similarity index 88% rename from blokk-server/src/main/kotlin/space/blokk/net/protocols/play/ClientSettingsPacketHandler.kt rename to blokk-server/src/main/kotlin/space/blokk/net/packets/play/ClientSettingsPacketHandler.kt index ad40662..9b9a495 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/protocols/play/ClientSettingsPacketHandler.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/packets/play/ClientSettingsPacketHandler.kt @@ -1,4 +1,4 @@ -package space.blokk.net.protocols.play +package space.blokk.net.packets.play import space.blokk.net.BlokkSession import space.blokk.net.PacketReceivedEventHandler diff --git a/blokk-server/src/main/kotlin/space/blokk/net/protocols/play/IncomingPluginMessagePacketHandler.kt b/blokk-server/src/main/kotlin/space/blokk/net/packets/play/IncomingPluginMessagePacketHandler.kt similarity index 96% rename from blokk-server/src/main/kotlin/space/blokk/net/protocols/play/IncomingPluginMessagePacketHandler.kt rename to blokk-server/src/main/kotlin/space/blokk/net/packets/play/IncomingPluginMessagePacketHandler.kt index d24b57a..53a051c 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/protocols/play/IncomingPluginMessagePacketHandler.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/packets/play/IncomingPluginMessagePacketHandler.kt @@ -1,4 +1,4 @@ -package space.blokk.net.protocols.play +package space.blokk.net.packets.play import io.netty.buffer.ByteBuf import io.netty.buffer.Unpooled diff --git a/blokk-server/src/main/kotlin/space/blokk/net/protocols/play/PlayProtocolHandler.kt b/blokk-server/src/main/kotlin/space/blokk/net/packets/play/PlayProtocolHandler.kt similarity index 57% rename from blokk-server/src/main/kotlin/space/blokk/net/protocols/play/PlayProtocolHandler.kt rename to blokk-server/src/main/kotlin/space/blokk/net/packets/play/PlayProtocolHandler.kt index e084df7..fcca208 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/protocols/play/PlayProtocolHandler.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/packets/play/PlayProtocolHandler.kt @@ -1,11 +1,11 @@ -package space.blokk.net.protocols.play +package space.blokk.net.packets.play import space.blokk.net.ProtocolPacketReceivedEventHandler // NOTE: PacketReceivedEventHandler.of MUST have T specified correctly, otherwise the code breaks at runtime object PlayProtocolHandler : ProtocolPacketReceivedEventHandler( mapOf( - ClientSettingsPacket to ClientSettingsPacketHandler, - IncomingPluginMessagePacket to IncomingPluginMessagePacketHandler + ClientSettingsPacket::class to ClientSettingsPacketHandler, + IncomingPluginMessagePacket::class to IncomingPluginMessagePacketHandler ) ) diff --git a/blokk-server/src/main/kotlin/space/blokk/net/protocols/status/StatusProtocolHandler.kt b/blokk-server/src/main/kotlin/space/blokk/net/packets/status/StatusProtocolHandler.kt similarity index 86% rename from blokk-server/src/main/kotlin/space/blokk/net/protocols/status/StatusProtocolHandler.kt rename to blokk-server/src/main/kotlin/space/blokk/net/packets/status/StatusProtocolHandler.kt index cbf48c3..29f9c88 100644 --- a/blokk-server/src/main/kotlin/space/blokk/net/protocols/status/StatusProtocolHandler.kt +++ b/blokk-server/src/main/kotlin/space/blokk/net/packets/status/StatusProtocolHandler.kt @@ -1,4 +1,4 @@ -package space.blokk.net.protocols.status +package space.blokk.net.packets.status import space.blokk.chat.FormattingCode import space.blokk.chat.TextComponent @@ -10,7 +10,7 @@ import java.util.* // NOTE: PacketReceivedEventHandler.of MUST have T specified correctly, otherwise the code breaks at runtime object StatusProtocolHandler : ProtocolPacketReceivedEventHandler(mapOf( - RequestPacket to PacketReceivedEventHandler.of { session, _ -> + RequestPacket::class to PacketReceivedEventHandler.of { session, _ -> session.eventBus.emit( ServerListInfoRequestEvent( session, @@ -33,7 +33,7 @@ object StatusProtocolHandler : ProtocolPacketReceivedEventHandler(mapOf( ) ).ifNotCancelled { session.send(it.response) } }, - PingPacket to PacketReceivedEventHandler.of { session, packet -> + PingPacket::class to PacketReceivedEventHandler.of { session, packet -> session.send(PongPacket(packet.payload)) } )) diff --git a/blokk-server/src/main/resources/logback.xml b/blokk-server/src/main/resources/logback.xml index 50c0d17..1e9b670 100644 --- a/blokk-server/src/main/resources/logback.xml +++ b/blokk-server/src/main/resources/logback.xml @@ -4,4 +4,5 @@ + diff --git a/settings.gradle.kts b/settings.gradle.kts index 8b3efc0..a914d5d 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -9,3 +9,4 @@ rootProject.name = "blokk" include(":blokk-api") include(":blokk-server") +include(":blokk-packet-codecs")