Archived
1
0
Fork 0

Reformat code to use the official kotlin code style

This commit is contained in:
Moritz Ruth 2020-08-14 20:54:07 +02:00
parent da7397e7f2
commit 0a4f835327
No known key found for this signature in database
GPG key ID: AFD57E23E753841B
47 changed files with 199 additions and 153 deletions

View file

@ -13,18 +13,18 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Set up JDK 1.8 - name: Set up JDK 1.8
uses: actions/setup-java@v1 uses: actions/setup-java@v1
with: with:
java-version: 1.8 java-version: 1.8
- name: Cache Gradle packages - name: Cache Gradle packages
uses: actions/cache@v2 uses: actions/cache@v2
with: with:
path: ~/.gradle/caches path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }} key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle restore-keys: ${{ runner.os }}-gradle
- name: Build with Gradle - name: Build with Gradle
run: ./gradlew build run: ./gradlew build
- name: Test with Gradle - name: Test with Gradle
run: ./gradlew test run: ./gradlew test

View file

@ -15,7 +15,7 @@ interface BlokkProvider {
val sessions: EventTargetGroup<Session> val sessions: EventTargetGroup<Session>
} }
object Blokk: BlokkProvider { object Blokk : BlokkProvider {
// Is assigned by BlokkServer using reflection // Is assigned by BlokkServer using reflection
private var provider: BlokkProvider? = null private var provider: BlokkProvider? = null
override val server get() = provider!!.server override val server get() = provider!!.server

View file

@ -55,17 +55,21 @@ sealed class ChatComponent {
WHITE; WHITE;
object Adapter { object Adapter {
@ToJson fun toJson(value: Color) = value.name.toLowerCase() @ToJson
@FromJson fun fromJson(value: String) = valueOf(value.toUpperCase()) fun toJson(value: Color) = value.name.toLowerCase()
@FromJson
fun fromJson(value: String) = valueOf(value.toUpperCase())
} }
} }
object Adapter { object Adapter {
@FromJson fun fromJson(reader: JsonReader): ChatComponent? { @FromJson
fun fromJson(reader: JsonReader): ChatComponent? {
throw UnsupportedOperationException("ChatComponent cannot be deserialized.") throw UnsupportedOperationException("ChatComponent cannot be deserialized.")
} }
@ToJson fun toJson(writer: JsonWriter, value: ChatComponent?) { @ToJson
fun toJson(writer: JsonWriter, value: ChatComponent?) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
if (value == null) writer.nullValue() if (value == null) writer.nullValue()
else (Blokk.json.adapter(value::class.java) as JsonAdapter<ChatComponent>).toJson(writer, value) else (Blokk.json.adapter(value::class.java) as JsonAdapter<ChatComponent>).toJson(writer, value)
@ -85,7 +89,7 @@ data class TextComponent(
override val obfuscated: Boolean = false, override val obfuscated: Boolean = false,
override val color: Color? = null, override val color: Color? = null,
override val extra: List<ChatComponent>? = null override val extra: List<ChatComponent>? = null
): ChatComponent() { ) : ChatComponent() {
companion object { companion object {
/** /**
* Creates a new [TextComponent] instance using [text] and returns it. * Creates a new [TextComponent] instance using [text] and returns it.

View file

@ -7,9 +7,9 @@ interface Cancellable {
/** /**
* Only executes [fn] if [isCancelled][Cancellable.isCancelled] is true. * Only executes [fn] if [isCancelled][Cancellable.isCancelled] is true.
*/ */
inline fun <T: Cancellable, R> T.ifCancelled(fn: (T) -> R): R? = if (isCancelled) fn(this) else null inline fun <T : Cancellable, R> T.ifCancelled(fn: (T) -> R): R? = if (isCancelled) fn(this) else null
/** /**
* Only executes [fn] if [isCancelled][Cancellable.isCancelled] is false. * Only executes [fn] if [isCancelled][Cancellable.isCancelled] is false.
*/ */
inline fun <T: Cancellable, R> T.ifNotCancelled(fn: (T) -> R): R? = if (!isCancelled) fn(this) else null inline fun <T : Cancellable, R> T.ifNotCancelled(fn: (T) -> R): R? = if (!isCancelled) fn(this) else null

View file

@ -7,7 +7,7 @@ import kotlin.reflect.KClass
import kotlin.reflect.KFunction import kotlin.reflect.KFunction
import kotlin.reflect.full.* import kotlin.reflect.full.*
class EventBus<EventT: Event>(private val eventClass: KClass<EventT>, private val scope: CoroutineScope) { class EventBus<EventT : Event>(private val eventClass: KClass<EventT>, private val scope: CoroutineScope) {
/** /**
* All event handlers, sorted by their priority and the order in which they were registered. * All event handlers, sorted by their priority and the order in which they were registered.
*/ */
@ -19,12 +19,12 @@ class EventBus<EventT: Event>(private val eventClass: KClass<EventT>, private va
* *
* @return [event] * @return [event]
*/ */
suspend fun <T: EventT> emit(event: T): T { suspend fun <T : EventT> emit(event: T): T {
handlers.filter { it.eventType.isInstance(event) }.forEach { it.fn.callSuspend(it.listener, event) } handlers.filter { it.eventType.isInstance(event) }.forEach { it.fn.callSuspend(it.listener, event) }
return event return event
} }
fun <T: EventT> emitAsync(event: T) = scope.async { emit(event) } fun <T : EventT> emitAsync(event: T) = scope.async { emit(event) }
/** /**
* Registers all [event handlers][EventHandler] in [listener] to be invoked when their corresponding event is emitted. * Registers all [event handlers][EventHandler] in [listener] to be invoked when their corresponding event is emitted.
@ -32,10 +32,10 @@ class EventBus<EventT: Event>(private val eventClass: KClass<EventT>, private va
* @return [listener] * @return [listener]
* @throws InvalidEventHandlerException if one of the event handlers does not meet the requirements * @throws InvalidEventHandlerException if one of the event handlers does not meet the requirements
*/ */
fun <T: Listener> register(listener: T): T { fun <T : Listener> register(listener: T): T {
val handlersOfListener = listener::class.functions val handlersOfListener = listener::class.functions
.mapNotNull { method -> method.findAnnotation<EventHandler>()?.let { method to it } } .mapNotNull { method -> method.findAnnotation<EventHandler>()?.let { method to it } }
.toMap() .toMap()
for ((method, data) in handlersOfListener) { for ((method, data) in handlersOfListener) {
if (method.valueParameters.count() != 1) if (method.valueParameters.count() != 1)
@ -45,8 +45,10 @@ class EventBus<EventT: Event>(private val eventClass: KClass<EventT>, private va
val klass = method.parameters[1].type.classifier as KClass<EventT> val klass = method.parameters[1].type.classifier as KClass<EventT>
if (!eventClass.isSuperclassOf(klass)) if (!eventClass.isSuperclassOf(klass))
throw InvalidEventHandlerException("${method.name}'s first parameter type is incompatible with the " + throw InvalidEventHandlerException(
"one required by the EventBus") "${method.name}'s first parameter type is incompatible with the " +
"one required by the EventBus"
)
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
val handler = Handler( val handler = Handler(
@ -71,9 +73,9 @@ class EventBus<EventT: Event>(private val eventClass: KClass<EventT>, private va
handlers.removeIf { it.listener === listener } handlers.removeIf { it.listener === listener }
} }
class InvalidEventHandlerException internal constructor(message: String): Exception(message) class InvalidEventHandlerException internal constructor(message: String) : Exception(message)
private data class Handler<T: Event>( private data class Handler<T : Event>(
val eventType: KClass<T>, val eventType: KClass<T>,
val listener: Listener, val listener: Listener,
val fn: KFunction<T>, val fn: KFunction<T>,

View file

@ -1,5 +1,5 @@
package space.blokk.events package space.blokk.events
interface EventTarget<T: Event> { interface EventTarget<T : Event> {
val eventBus: EventBus<T> val eventBus: EventBus<T>
} }

View file

@ -1,13 +1,13 @@
package space.blokk.events package space.blokk.events
interface EventTargetGroup<T: EventTarget<*>> : Iterable<T> { interface EventTargetGroup<T : EventTarget<*>> : Iterable<T> {
/** /**
* Register a listener for all elements in this group. * Register a listener for all elements in this group.
* You should never reuse [listener] for other groups or directly on event targets * You should never reuse [listener] for other groups or directly on event targets
* because this may lead to strange behaviour. * because this may lead to strange behaviour.
*/ */
fun <T: Listener> registerListener(listener: T): T fun <T : Listener> registerListener(listener: T): T
/** /**
* Unregister a listener for all elements in this group. * Unregister a listener for all elements in this group.

View file

@ -14,9 +14,23 @@ class Logger(name: String) {
infix fun debug(msg: String) = logger.debug(msg) infix fun debug(msg: String) = logger.debug(msg)
infix fun trace(msg: String) = logger.trace(msg) infix fun trace(msg: String) = logger.trace(msg)
infix fun error(fn: () -> String) { if (logger.isErrorEnabled) logger.error(fn()) } infix fun error(fn: () -> String) {
infix fun info(fn: () -> String) { if (logger.isInfoEnabled) logger.info(fn()) } if (logger.isErrorEnabled) logger.error(fn())
infix fun warn(fn: () -> String) { if (logger.isWarnEnabled) logger.warn(fn()) } }
infix fun debug(fn: () -> String) { if (logger.isDebugEnabled) logger.debug(fn()) }
infix fun trace(fn: () -> String) { if (logger.isTraceEnabled) logger.trace(fn()) } infix fun info(fn: () -> String) {
if (logger.isInfoEnabled) logger.info(fn())
}
infix fun warn(fn: () -> String) {
if (logger.isWarnEnabled) logger.warn(fn())
}
infix fun debug(fn: () -> String) {
if (logger.isDebugEnabled) logger.debug(fn())
}
infix fun trace(fn: () -> String) {
if (logger.isTraceEnabled) logger.trace(fn())
}
} }

View file

@ -7,7 +7,7 @@ import space.blokk.net.protocols.OutgoingPacket
import space.blokk.net.protocols.Protocol import space.blokk.net.protocols.Protocol
import java.net.InetAddress import java.net.InetAddress
interface Session: EventTarget<SessionEvent> { interface Session : EventTarget<SessionEvent> {
/** /**
* The protocol this session is currently using. * The protocol this session is currently using.
*/ */

View file

@ -3,7 +3,7 @@ package space.blokk.net
import space.blokk.events.EventTargetGroup import space.blokk.events.EventTargetGroup
import space.blokk.events.Listener import space.blokk.events.Listener
class SessionGroup: EventTargetGroup<Session> { class SessionGroup : EventTargetGroup<Session> {
private val sessions = mutableSetOf<Session>() private val sessions = mutableSetOf<Session>()
private val listeners = mutableSetOf<Listener>() private val listeners = mutableSetOf<Listener>()

View file

@ -4,6 +4,6 @@ import space.blokk.events.Cancellable
import space.blokk.net.Session import space.blokk.net.Session
import space.blokk.net.protocols.IncomingPacket import space.blokk.net.protocols.IncomingPacket
class PacketReceivedEvent<T: IncomingPacket>(session: Session, var packet: T): SessionEvent(session), Cancellable { class PacketReceivedEvent<T : IncomingPacket>(session: Session, var packet: T) : SessionEvent(session), Cancellable {
override var isCancelled = false override var isCancelled = false
} }

View file

@ -4,6 +4,6 @@ import space.blokk.events.Cancellable
import space.blokk.net.Session import space.blokk.net.Session
import space.blokk.net.protocols.OutgoingPacket import space.blokk.net.protocols.OutgoingPacket
class PacketSendEvent(session: Session, var packet: OutgoingPacket): SessionEvent(session), Cancellable { class PacketSendEvent(session: Session, var packet: OutgoingPacket) : SessionEvent(session), Cancellable {
override var isCancelled = false override var isCancelled = false
} }

View file

@ -7,6 +7,6 @@ import space.blokk.net.protocols.status.ResponsePacket
class ServerListInfoRequestEvent( class ServerListInfoRequestEvent(
session: Session, session: Session,
var response: ResponsePacket var response: ResponsePacket
): SessionEvent(session), Cancellable { ) : SessionEvent(session), Cancellable {
override var isCancelled = false override var isCancelled = false
} }

View file

@ -3,4 +3,4 @@ package space.blokk.net.events
import space.blokk.events.Event import space.blokk.events.Event
import space.blokk.net.Session import space.blokk.net.Session
abstract class SessionEvent(val session: Session): Event() abstract class SessionEvent(val session: Session) : Event()

View file

@ -7,23 +7,23 @@ abstract class Packet {
override fun toString(): String = this::class.java.simpleName + "(no data)" override fun toString(): String = this::class.java.simpleName + "(no data)"
} }
abstract class IncomingPacket: Packet() abstract class IncomingPacket : Packet()
abstract class OutgoingPacket: Packet() { abstract class OutgoingPacket : Packet() {
abstract fun encode(dst: ByteBuf) abstract fun encode(dst: ByteBuf)
} }
sealed class PacketCompanion<T: Packet>(val id: Int, val packetType: KClass<T>) sealed class PacketCompanion<T : Packet>(val id: Int, val packetType: KClass<T>)
abstract class IncomingPacketCompanion<T: IncomingPacket>( abstract class IncomingPacketCompanion<T : IncomingPacket>(
id: Int, id: Int,
packetType: KClass<T> packetType: KClass<T>
): PacketCompanion<T>(id, packetType) { ) : PacketCompanion<T>(id, packetType) {
abstract fun decode(msg: ByteBuf): T abstract fun decode(msg: ByteBuf): T
} }
abstract class OutgoingPacketCompanion<T: OutgoingPacket>( abstract class OutgoingPacketCompanion<T : OutgoingPacket>(
id: Int, id: Int,
packetType: KClass<T> packetType: KClass<T>
): PacketCompanion<T>(id, packetType) ) : PacketCompanion<T>(id, packetType)

View file

@ -7,7 +7,7 @@ abstract class Protocol internal constructor(val name: String, packets: Set<Pack
val outgoingPacketsByID = outgoingPackets.mapToIDMap() val outgoingPacketsByID = outgoingPackets.mapToIDMap()
val packetCompanionsByPacketType = packets.map { it.packetType to it }.toMap() val packetCompanionsByPacketType = packets.map { it.packetType to it }.toMap()
private fun <T: PacketCompanion<*>> Iterable<T>.mapToIDMap() = map { it.id to it }.toMap() private fun <T : PacketCompanion<*>> Iterable<T>.mapToIDMap() = map { it.id to it }.toMap()
fun validate() { fun validate() {
ensureDistinctIDs(incomingPackets, "serverbound") ensureDistinctIDs(incomingPackets, "serverbound")

View file

@ -22,15 +22,15 @@ data class HandshakePacket(
val serverAddress: String, val serverAddress: String,
val serverPort: Int, val serverPort: Int,
val loginAttempt: Boolean val loginAttempt: Boolean
): IncomingPacket() { ) : IncomingPacket() {
companion object: IncomingPacketCompanion<HandshakePacket>(0x00, HandshakePacket::class) { companion object : IncomingPacketCompanion<HandshakePacket>(0x00, HandshakePacket::class) {
override fun decode(msg: ByteBuf): HandshakePacket { override fun decode(msg: ByteBuf): HandshakePacket {
return with(MinecraftDataTypes) { return with(MinecraftDataTypes) {
HandshakePacket( HandshakePacket(
protocolVersion = msg.readVarInt(), protocolVersion = msg.readVarInt(),
serverAddress = msg.readString(), serverAddress = msg.readString(),
serverPort = msg.readUnsignedShort(), serverPort = msg.readUnsignedShort(),
loginAttempt = msg.readVarInt() == 2 loginAttempt = msg.readVarInt() == 2
) )
} }
} }

View file

@ -11,8 +11,8 @@ import space.blokk.net.protocols.OutgoingPacketCompanion
* *
* @param reason The reason why the login process was cancelled. * @param reason The reason why the login process was cancelled.
*/ */
data class DisconnectPacket(val reason: ChatComponent): OutgoingPacket() { data class DisconnectPacket(val reason: ChatComponent) : OutgoingPacket() {
companion object: OutgoingPacketCompanion<DisconnectPacket>(0x00, DisconnectPacket::class) companion object : OutgoingPacketCompanion<DisconnectPacket>(0x00, DisconnectPacket::class)
override fun encode(dst: ByteBuf) { override fun encode(dst: ByteBuf) {
dst.writeString(reason.toJson()) dst.writeString(reason.toJson())

View file

@ -13,11 +13,11 @@ import space.blokk.net.protocols.OutgoingPacketCompanion
* @see <a href="https://wiki.vg/Protocol_Encryption">https://wiki.vg/Protocol_Encryption</a> * @see <a href="https://wiki.vg/Protocol_Encryption">https://wiki.vg/Protocol_Encryption</a>
*/ */
data class EncryptionRequestPacket( data class EncryptionRequestPacket(
val serverID: String, val serverID: String,
val publicKey: ByteArray, val publicKey: ByteArray,
val verifyToken: ByteArray val verifyToken: ByteArray
): OutgoingPacket() { ) : OutgoingPacket() {
companion object: OutgoingPacketCompanion<EncryptionRequestPacket>(0x01, EncryptionRequestPacket::class) companion object : OutgoingPacketCompanion<EncryptionRequestPacket>(0x01, EncryptionRequestPacket::class)
init { init {
if (serverID.length > 20) throw IllegalArgumentException("serverID can only be 16 characters long") if (serverID.length > 20) throw IllegalArgumentException("serverID can only be 16 characters long")

View file

@ -11,10 +11,10 @@ import space.blokk.net.protocols.IncomingPacketCompanion
* @see <a href="https://wiki.vg/Protocol_Encryption">https://wiki.vg/Protocol_Encryption</a> * @see <a href="https://wiki.vg/Protocol_Encryption">https://wiki.vg/Protocol_Encryption</a>
*/ */
data class EncryptionResponsePacket( data class EncryptionResponsePacket(
val sharedSecret: ByteArray, val sharedSecret: ByteArray,
val verifyToken: ByteArray val verifyToken: ByteArray
): IncomingPacket() { ) : IncomingPacket() {
companion object: IncomingPacketCompanion<EncryptionResponsePacket>(0x01, EncryptionResponsePacket::class) { companion object : IncomingPacketCompanion<EncryptionResponsePacket>(0x01, EncryptionResponsePacket::class) {
override fun decode(msg: ByteBuf): EncryptionResponsePacket { override fun decode(msg: ByteBuf): EncryptionResponsePacket {
return with(MinecraftDataTypes) { return with(MinecraftDataTypes) {
val sharedSecretLength = msg.readVarInt() val sharedSecretLength = msg.readVarInt()

View file

@ -14,11 +14,11 @@ import space.blokk.net.protocols.OutgoingPacketCompanion
* @param data Any data, depending on the channel. * @param data Any data, depending on the channel.
*/ */
data class LoginPluginRequestPacket( data class LoginPluginRequestPacket(
val messageID: Int, val messageID: Int,
val channel: String, val channel: String,
val data: ByteBuf val data: ByteBuf
): OutgoingPacket() { ) : OutgoingPacket() {
companion object: OutgoingPacketCompanion<LoginPluginRequestPacket>(0x04, LoginPluginRequestPacket::class) companion object : OutgoingPacketCompanion<LoginPluginRequestPacket>(0x04, LoginPluginRequestPacket::class)
override fun encode(dst: ByteBuf) { override fun encode(dst: ByteBuf) {
dst.writeVarInt(messageID) dst.writeVarInt(messageID)

View file

@ -13,8 +13,8 @@ import space.blokk.net.protocols.IncomingPacketCompanion
data class LoginPluginResponsePacket( data class LoginPluginResponsePacket(
val messageID: Int, val messageID: Int,
val data: ByteArray? val data: ByteArray?
): IncomingPacket() { ) : IncomingPacket() {
companion object: IncomingPacketCompanion<LoginPluginResponsePacket>(0x02, LoginPluginResponsePacket::class) { companion object : IncomingPacketCompanion<LoginPluginResponsePacket>(0x02, LoginPluginResponsePacket::class) {
override fun decode(msg: ByteBuf): LoginPluginResponsePacket { override fun decode(msg: ByteBuf): LoginPluginResponsePacket {
return with(MinecraftDataTypes) { return with(MinecraftDataTypes) {
val messageID = msg.readVarInt() val messageID = msg.readVarInt()

View file

@ -2,7 +2,8 @@ package space.blokk.net.protocols.login
import space.blokk.net.protocols.Protocol import space.blokk.net.protocols.Protocol
object LoginProtocol: Protocol("LOGIN", setOf( object LoginProtocol : Protocol(
"LOGIN", setOf(
DisconnectPacket, DisconnectPacket,
LoginStartPacket, LoginStartPacket,
EncryptionRequestPacket, EncryptionRequestPacket,
@ -11,4 +12,5 @@ object LoginProtocol: Protocol("LOGIN", setOf(
LoginSuccessPacket, LoginSuccessPacket,
LoginPluginRequestPacket, LoginPluginRequestPacket,
LoginPluginResponsePacket LoginPluginResponsePacket
)) )
)

View file

@ -10,8 +10,8 @@ import space.blokk.net.protocols.IncomingPacketCompanion
* *
* @param username The username of the client. This is not validated (yet). Can only be 16 characters long. * @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() { data class LoginStartPacket(val username: String) : IncomingPacket() {
companion object: IncomingPacketCompanion<LoginStartPacket>(0x00, LoginStartPacket::class) { companion object : IncomingPacketCompanion<LoginStartPacket>(0x00, LoginStartPacket::class) {
override fun decode(msg: ByteBuf): LoginStartPacket { override fun decode(msg: ByteBuf): LoginStartPacket {
return with(MinecraftDataTypes) { LoginStartPacket(msg.readString()) } return with(MinecraftDataTypes) { LoginStartPacket(msg.readString()) }
} }

View file

@ -14,8 +14,8 @@ import java.util.*
* @param uuid The UUID of the player. * @param uuid The UUID of the player.
* @param username The username of the player. Can only be 16 characters long. * @param username The username of the player. Can only be 16 characters long.
*/ */
data class LoginSuccessPacket(val uuid: UUID, val username: String): OutgoingPacket() { data class LoginSuccessPacket(val uuid: UUID, val username: String) : OutgoingPacket() {
companion object: OutgoingPacketCompanion<LoginSuccessPacket>(0x02, LoginSuccessPacket::class) companion object : OutgoingPacketCompanion<LoginSuccessPacket>(0x02, LoginSuccessPacket::class)
init { init {
if (username.length > 16) throw IllegalArgumentException("username can only be 16 characters long") if (username.length > 16) throw IllegalArgumentException("username can only be 16 characters long")

View file

@ -11,8 +11,8 @@ import space.blokk.net.protocols.OutgoingPacketCompanion
* *
* @param threshold Maximum size before a packet is compressed. Values lower than 1 will disable compression. * @param threshold Maximum size before a packet is compressed. Values lower than 1 will disable compression.
*/ */
data class SetCompressionPacket(val threshold: Int): OutgoingPacket() { data class SetCompressionPacket(val threshold: Int) : OutgoingPacket() {
companion object: OutgoingPacketCompanion<SetCompressionPacket>(0x03, SetCompressionPacket::class) companion object : OutgoingPacketCompanion<SetCompressionPacket>(0x03, SetCompressionPacket::class)
override fun encode(dst: ByteBuf) { override fun encode(dst: ByteBuf) {
dst.writeVarInt(threshold) dst.writeVarInt(threshold)

View file

@ -11,7 +11,7 @@ import space.blokk.net.protocols.IncomingPacketCompanion
* *
* @see [space.blokk.net.events.ServerListInfoRequestEvent] * @see [space.blokk.net.events.ServerListInfoRequestEvent]
*/ */
class RequestPacket: IncomingPacket() { class RequestPacket : IncomingPacket() {
companion object : IncomingPacketCompanion<RequestPacket>(0x00, RequestPacket::class) { companion object : IncomingPacketCompanion<RequestPacket>(0x00, RequestPacket::class) {
override fun decode(msg: ByteBuf): RequestPacket = RequestPacket() override fun decode(msg: ByteBuf): RequestPacket = RequestPacket()
} }

View file

@ -2,4 +2,4 @@ package space.blokk.net.protocols.status
import space.blokk.net.protocols.Protocol import space.blokk.net.protocols.Protocol
object StatusProtocol: Protocol("STATUS", setOf(RequestPacket, ResponsePacket, PingPacket, PongPacket)) object StatusProtocol : Protocol("STATUS", setOf(RequestPacket, ResponsePacket, PingPacket, PongPacket))

View file

@ -5,7 +5,7 @@ import space.blokk.events.EventBus
import space.blokk.events.EventTarget import space.blokk.events.EventTarget
import space.blokk.server.events.ServerEvent import space.blokk.server.events.ServerEvent
interface Server: EventTarget<ServerEvent> { interface Server : EventTarget<ServerEvent> {
override val eventBus: EventBus<ServerEvent> override val eventBus: EventBus<ServerEvent>
val scope: CoroutineScope val scope: CoroutineScope
} }

View file

@ -2,4 +2,4 @@ package space.blokk.server.events
import space.blokk.events.Event import space.blokk.events.Event
abstract class ServerEvent: Event() abstract class ServerEvent : Event()

View file

@ -3,6 +3,6 @@ package space.blokk.server.events
import space.blokk.events.Cancellable import space.blokk.events.Cancellable
import space.blokk.net.Session import space.blokk.net.Session
class SessionInitializedEvent(val session: Session): ServerEvent(), Cancellable { class SessionInitializedEvent(val session: Session) : ServerEvent(), Cancellable {
override var isCancelled: Boolean = false override var isCancelled: Boolean = false
} }

View file

@ -5,7 +5,7 @@ import org.spekframework.spek2.style.specification.describe
import strikt.api.expectThat import strikt.api.expectThat
import strikt.assertions.isEqualTo import strikt.assertions.isEqualTo
object FormattingCodeTest: Spek({ object FormattingCodeTest : Spek({
describe("FormattingCode") { describe("FormattingCode") {
it("correctly translates to a string") { it("correctly translates to a string") {
expectThat("${FormattingCode.AQUA}").isEqualTo("§b") expectThat("${FormattingCode.AQUA}").isEqualTo("§b")

View file

@ -1,4 +1,5 @@
package space.blokk.events package space.blokk.events
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay import kotlinx.coroutines.delay
@ -10,11 +11,11 @@ import strikt.api.expectThrows
import strikt.assertions.* import strikt.assertions.*
import kotlin.system.measureTimeMillis import kotlin.system.measureTimeMillis
private abstract class TestEvent: Event() private abstract class TestEvent : Event()
private class FirstEvent: TestEvent() private class FirstEvent : TestEvent()
private class SecondEvent: TestEvent() private class SecondEvent : TestEvent()
object EventBusTest: Spek({ object EventBusTest : Spek({
describe("EventBus") { describe("EventBus") {
val eventBus by memoized { EventBus(TestEvent::class, CoroutineScope(Dispatchers.Default)) } val eventBus by memoized { EventBus(TestEvent::class, CoroutineScope(Dispatchers.Default)) }

View file

@ -3,7 +3,7 @@ package space.blokk.net.protocols
import org.spekframework.spek2.Spek import org.spekframework.spek2.Spek
import org.spekframework.spek2.style.specification.describe import org.spekframework.spek2.style.specification.describe
object ProtocolsTest: Spek({ object ProtocolsTest : Spek({
describe("Protocols") { describe("Protocols") {
it("are valid") { it("are valid") {
Protocols.validate() Protocols.validate()

View file

@ -1,5 +1,3 @@
plugins { plugins {
kotlin("jvm") kotlin("jvm")
id("com.github.johnrengelman.shadow") version "6.0.0" id("com.github.johnrengelman.shadow") version "6.0.0"

View file

@ -13,8 +13,10 @@ import space.blokk.net.events.ServerListInfoRequestEvent
import space.blokk.server.Server import space.blokk.server.Server
import space.blokk.server.events.ServerEvent import space.blokk.server.events.ServerEvent
class BlokkServer internal constructor(): Server { class BlokkServer internal constructor() : Server {
init { i = this } init {
i = this
}
override val scope = CoroutineScope(CoroutineName("BlokkServer")) override val scope = CoroutineScope(CoroutineName("BlokkServer"))
override val eventBus = EventBus(ServerEvent::class, scope) override val eventBus = EventBus(ServerEvent::class, scope)
@ -52,7 +54,14 @@ class BlokkServer internal constructor(): Server {
Blokk.sessions.registerListener(object : Listener { Blokk.sessions.registerListener(object : Listener {
@EventHandler @EventHandler
fun onServerListInfoRequest(event: ServerListInfoRequestEvent) { fun onServerListInfoRequest(event: ServerListInfoRequestEvent) {
event.response = event.response.copy(description = TextComponent(event.session.address.hostAddress, bold = true, underlined = true, color = ChatComponent.Color.RED)) event.response = event.response.copy(
description = TextComponent(
event.session.address.hostAddress,
bold = true,
underlined = true,
color = ChatComponent.Color.RED
)
)
} }
}) })

View file

@ -8,7 +8,7 @@ import java.io.PrintStream
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
class ConsoleAppender: AppenderBase<ILoggingEvent>() { class ConsoleAppender : AppenderBase<ILoggingEvent>() {
private val dateFormat = SimpleDateFormat("HH:mm:ss.SSS") private val dateFormat = SimpleDateFormat("HH:mm:ss.SSS")
override fun append(event: ILoggingEvent) { override fun append(event: ILoggingEvent) {
@ -23,13 +23,15 @@ class ConsoleAppender: AppenderBase<ILoggingEvent>() {
else -> khalk else -> khalk
} }
stream.println(listOf( stream.println(
khalk.gray { dateFormat.format(Date(event.timeStamp)) }, listOf(
color { event.level.toString().padEnd(5) }, khalk.gray { dateFormat.format(Date(event.timeStamp)) },
khalk.bold { event.threadName }, color { event.level.toString().padEnd(5) },
color.inverse { " ${event.loggerName} " }, khalk.bold { event.threadName },
color { "" }, color.inverse { " ${event.loggerName} " },
event.message color { "" },
).joinToString(" ")) event.message
).joinToString(" ")
)
} }
} }

View file

@ -7,7 +7,7 @@ import io.netty.channel.ChannelOption
import io.netty.handler.timeout.IdleStateHandler import io.netty.handler.timeout.IdleStateHandler
import space.blokk.BlokkServer import space.blokk.BlokkServer
class BlokkChannelInitializer(private val blokkSocketServer: BlokkSocketServer): ChannelInitializer<Channel>() { class BlokkChannelInitializer(private val blokkSocketServer: BlokkSocketServer) : ChannelInitializer<Channel>() {
private val logger = BlokkServer.i.logger private val logger = BlokkServer.i.logger
override fun initChannel(channel: Channel) { override fun initChannel(channel: Channel) {
@ -21,10 +21,10 @@ class BlokkChannelInitializer(private val blokkSocketServer: BlokkSocketServer):
val session = BlokkSession(channel) val session = BlokkSession(channel)
channel.pipeline() channel.pipeline()
.addLast(IdleStateHandler(20, 15, 0)) .addLast(IdleStateHandler(20, 15, 0))
.addLast(FramingCodec()) .addLast(FramingCodec())
.addLast(PacketCodec(session)) .addLast(PacketCodec(session))
.addLast(PacketMessageHandler(session)) .addLast(PacketMessageHandler(session))
} }
companion object { companion object {

View file

@ -4,6 +4,7 @@ import io.netty.channel.Channel
import kotlinx.coroutines.* import kotlinx.coroutines.*
import space.blokk.BlokkServer import space.blokk.BlokkServer
import space.blokk.events.* import space.blokk.events.*
import space.blokk.logging.Logger
import space.blokk.net.events.PacketReceivedEvent import space.blokk.net.events.PacketReceivedEvent
import space.blokk.net.events.PacketSendEvent import space.blokk.net.events.PacketSendEvent
import space.blokk.net.events.SessionEvent import space.blokk.net.events.SessionEvent
@ -11,7 +12,6 @@ import space.blokk.net.protocols.OutgoingPacket
import space.blokk.net.protocols.Protocol import space.blokk.net.protocols.Protocol
import space.blokk.net.protocols.handshaking.HandshakingProtocol import space.blokk.net.protocols.handshaking.HandshakingProtocol
import space.blokk.server.events.SessionInitializedEvent import space.blokk.server.events.SessionInitializedEvent
import space.blokk.logging.Logger
import space.blokk.utils.awaitSuspending import space.blokk.utils.awaitSuspending
import java.net.InetAddress import java.net.InetAddress
import java.net.InetSocketAddress import java.net.InetSocketAddress

View file

@ -19,14 +19,16 @@ class BlokkSocketServer(private val blokkServer: BlokkServer) {
private val bossGroup = createEventLoopGroup() private val bossGroup = createEventLoopGroup()
private val workerGroup = createEventLoopGroup() private val workerGroup = createEventLoopGroup()
private val bootstrap: ServerBootstrap = ServerBootstrap() private val bootstrap: ServerBootstrap = ServerBootstrap()
.group(bossGroup, workerGroup) .group(bossGroup, workerGroup)
.channel(when { .channel(
when {
EPOLL_AVAILABLE -> EpollServerSocketChannel::class.java EPOLL_AVAILABLE -> EpollServerSocketChannel::class.java
KQUEUE_AVAILABLE -> KQueueServerSocketChannel::class.java KQUEUE_AVAILABLE -> KQueueServerSocketChannel::class.java
else -> NioServerSocketChannel::class.java else -> NioServerSocketChannel::class.java
}) }
.childOption(ChannelOption.SO_KEEPALIVE, true) )
.childOption(ChannelOption.TCP_NODELAY, true) .childOption(ChannelOption.SO_KEEPALIVE, true)
.childOption(ChannelOption.TCP_NODELAY, true)
.childHandler(BlokkChannelInitializer(this)) .childHandler(BlokkChannelInitializer(this))
internal val allSessionsGroup = SessionGroup() internal val allSessionsGroup = SessionGroup()

View file

@ -17,20 +17,20 @@ open class ProtocolPacketReceivedEventHandler(handlers: Map<out IncomingPacketCo
} }
} }
abstract class PacketReceivedEventHandler<T: IncomingPacket> { abstract class PacketReceivedEventHandler<T : IncomingPacket> {
abstract suspend fun handle(session: BlokkSession, packet: T) abstract suspend fun handle(session: BlokkSession, packet: T)
companion object { companion object {
fun <T: IncomingPacket> of(fn: suspend (session: BlokkSession, packet: T) -> Unit) = fun <T : IncomingPacket> of(fn: suspend (session: BlokkSession, packet: T) -> Unit) =
object : PacketReceivedEventHandler<T>() { object : PacketReceivedEventHandler<T>() {
override suspend fun handle(session: BlokkSession, packet: T) = fn(session, packet) override suspend fun handle(session: BlokkSession, packet: T) = fn(session, packet)
} }
} }
} }
object SessionPacketReceivedEventHandler { object SessionPacketReceivedEventHandler {
suspend fun handle(session: BlokkSession, packet: IncomingPacket) { suspend fun handle(session: BlokkSession, packet: IncomingPacket) {
val handler = when(session.currentProtocol) { val handler = when (session.currentProtocol) {
HandshakingProtocol -> HandshakingProtocolHandler HandshakingProtocol -> HandshakingProtocolHandler
StatusProtocol -> StatusProtocolHandler StatusProtocol -> StatusProtocolHandler
else -> return else -> return

View file

@ -4,7 +4,7 @@ import io.netty.buffer.ByteBuf
import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelHandlerContext
import io.netty.handler.codec.ByteToMessageCodec import io.netty.handler.codec.ByteToMessageCodec
class FramingCodec: ByteToMessageCodec<ByteBuf>() { class FramingCodec : ByteToMessageCodec<ByteBuf>() {
private var currentLength: Int? = null private var currentLength: Int? = null
override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: ByteBuf) { override fun encode(ctx: ChannelHandlerContext, msg: ByteBuf, out: ByteBuf) {
@ -21,8 +21,7 @@ class FramingCodec: ByteToMessageCodec<ByteBuf>() {
if (msg.varIntReadable()) { if (msg.varIntReadable()) {
length = msg.readVarInt() length = msg.readVarInt()
currentLength = length currentLength = length
} } else return
else return
} }
if (msg.readableBytes() >= length) { if (msg.readableBytes() >= length) {

View file

@ -7,9 +7,14 @@ import space.blokk.BlokkServer
import space.blokk.net.protocols.OutgoingPacket import space.blokk.net.protocols.OutgoingPacket
import java.io.IOException import java.io.IOException
class PacketCodec(private val session: BlokkSession): MessageToMessageCodec<ByteBuf, PacketMessage<*>>() { class PacketCodec(private val session: BlokkSession) : MessageToMessageCodec<ByteBuf, PacketMessage<*>>() {
override fun channelActive(ctx: ChannelHandlerContext) { session.onConnect() } override fun channelActive(ctx: ChannelHandlerContext) {
override fun channelInactive(ctx: ChannelHandlerContext) { session.onDisconnect() } session.onConnect()
}
override fun channelInactive(ctx: ChannelHandlerContext) {
session.onDisconnect()
}
override fun encode(ctx: ChannelHandlerContext, msg: PacketMessage<*>, out: MutableList<Any>) { override fun encode(ctx: ChannelHandlerContext, msg: PacketMessage<*>, out: MutableList<Any>) {
if (msg.packet !is OutgoingPacket) throw Error("Only clientbound packets are allowed. This should never happen.") if (msg.packet !is OutgoingPacket) throw Error("Only clientbound packets are allowed. This should never happen.")

View file

@ -3,11 +3,13 @@ package space.blokk.net
import space.blokk.net.protocols.Packet import space.blokk.net.protocols.Packet
import space.blokk.net.protocols.PacketCompanion import space.blokk.net.protocols.PacketCompanion
data class PacketMessage<T: Packet>(val session: BlokkSession, val packet: T) { data class PacketMessage<T : Packet>(val session: BlokkSession, val packet: T) {
val packetCompanion by lazy { val packetCompanion by lazy {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
session.currentProtocol.packetCompanionsByPacketType[packet::class] as PacketCompanion<T>? session.currentProtocol.packetCompanionsByPacketType[packet::class] as PacketCompanion<T>?
?: throw Exception("No packet companion found for this packet type. " + ?: throw Exception(
"This can happen if the packet is not part of the current protocol.") "No packet companion found for this packet type. " +
"This can happen if the packet is not part of the current protocol."
)
} }
} }

View file

@ -6,7 +6,7 @@ import kotlinx.coroutines.launch
import space.blokk.net.events.PacketReceivedEvent import space.blokk.net.events.PacketReceivedEvent
import space.blokk.net.protocols.IncomingPacket import space.blokk.net.protocols.IncomingPacket
class PacketMessageHandler(private val session: BlokkSession): SimpleChannelInboundHandler<PacketMessage<*>>() { class PacketMessageHandler(private val session: BlokkSession) : SimpleChannelInboundHandler<PacketMessage<*>>() {
override fun channelRead0(ctx: ChannelHandlerContext, msg: PacketMessage<*>) { override fun channelRead0(ctx: ChannelHandlerContext, msg: PacketMessage<*>) {
if (msg.packet !is IncomingPacket) throw Error("Only serverbound packets are allowed. This should never happen.") if (msg.packet !is IncomingPacket) throw Error("Only serverbound packets are allowed. This should never happen.")
session.logger.trace { "Packet received: ${msg.packet}" } session.logger.trace { "Packet received: ${msg.packet}" }

View file

@ -5,8 +5,8 @@ import space.blokk.net.ProtocolPacketReceivedEventHandler
import space.blokk.net.protocols.login.LoginProtocol import space.blokk.net.protocols.login.LoginProtocol
import space.blokk.net.protocols.status.StatusProtocol import space.blokk.net.protocols.status.StatusProtocol
object HandshakingProtocolHandler: ProtocolPacketReceivedEventHandler(mapOf( object HandshakingProtocolHandler : ProtocolPacketReceivedEventHandler(mapOf(
HandshakePacket to PacketReceivedEventHandler.of<HandshakePacket> { session, packet -> HandshakePacket to PacketReceivedEventHandler.of<HandshakePacket> { session, packet ->
session.currentProtocol = if (packet.loginAttempt) LoginProtocol else StatusProtocol session.currentProtocol = if (packet.loginAttempt) LoginProtocol else StatusProtocol
} }
)) ))

View file

@ -9,10 +9,10 @@ import space.blokk.net.events.ServerListInfoRequestEvent
import java.util.* import java.util.*
// NOTE: PacketReceivedEventHandler.of<T> MUST have T specified correctly, otherwise the code breaks at runtime // NOTE: PacketReceivedEventHandler.of<T> MUST have T specified correctly, otherwise the code breaks at runtime
object StatusProtocolHandler : ProtocolPacketReceivedEventHandler(mapOf(
object StatusProtocolHandler: ProtocolPacketReceivedEventHandler(mapOf( RequestPacket to PacketReceivedEventHandler.of<RequestPacket> { session, _ ->
RequestPacket to PacketReceivedEventHandler.of<RequestPacket> { session, _ -> session.eventBus.emit(
session.eventBus.emit(ServerListInfoRequestEvent( ServerListInfoRequestEvent(
session, session,
// TODO: Use the real server data // TODO: Use the real server data
ResponsePacket( ResponsePacket(
@ -22,12 +22,18 @@ object StatusProtocolHandler: ProtocolPacketReceivedEventHandler(mapOf(
players = ResponsePacket.Players( players = ResponsePacket.Players(
10, 10,
10, 10,
listOf(ResponsePacket.Players.SampleEntry("${FormattingCode.AQUA}Gronkh", UUID.randomUUID().toString())) listOf(
ResponsePacket.Players.SampleEntry(
"${FormattingCode.AQUA}Gronkh",
UUID.randomUUID().toString()
)
)
) )
) )
)).ifNotCancelled { session.send(it.response) } )
}, ).ifNotCancelled { session.send(it.response) }
PingPacket to PacketReceivedEventHandler.of<PingPacket> { session, packet -> },
session.send(PongPacket(packet.payload)) PingPacket to PacketReceivedEventHandler.of<PingPacket> { session, packet ->
} session.send(PongPacket(packet.payload))
}
)) ))