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
steps:
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Build with Gradle
run: ./gradlew build
- name: Test with Gradle
run: ./gradlew test
- uses: actions/checkout@v2
- name: Set up JDK 1.8
uses: actions/setup-java@v1
with:
java-version: 1.8
- name: Cache Gradle packages
uses: actions/cache@v2
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Build with Gradle
run: ./gradlew build
- name: Test with Gradle
run: ./gradlew test

View file

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

View file

@ -55,17 +55,21 @@ sealed class ChatComponent {
WHITE;
object Adapter {
@ToJson fun toJson(value: Color) = value.name.toLowerCase()
@FromJson fun fromJson(value: String) = valueOf(value.toUpperCase())
@ToJson
fun toJson(value: Color) = value.name.toLowerCase()
@FromJson
fun fromJson(value: String) = valueOf(value.toUpperCase())
}
}
object Adapter {
@FromJson fun fromJson(reader: JsonReader): ChatComponent? {
@FromJson
fun fromJson(reader: JsonReader): ChatComponent? {
throw UnsupportedOperationException("ChatComponent cannot be deserialized.")
}
@ToJson fun toJson(writer: JsonWriter, value: ChatComponent?) {
@ToJson
fun toJson(writer: JsonWriter, value: ChatComponent?) {
@Suppress("UNCHECKED_CAST")
if (value == null) writer.nullValue()
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 color: Color? = null,
override val extra: List<ChatComponent>? = null
): ChatComponent() {
) : ChatComponent() {
companion object {
/**
* 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.
*/
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.
*/
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.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.
*/
@ -19,12 +19,12 @@ class EventBus<EventT: Event>(private val eventClass: KClass<EventT>, private va
*
* @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) }
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.
@ -32,10 +32,10 @@ class EventBus<EventT: Event>(private val eventClass: KClass<EventT>, private va
* @return [listener]
* @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
.mapNotNull { method -> method.findAnnotation<EventHandler>()?.let { method to it } }
.toMap()
.mapNotNull { method -> method.findAnnotation<EventHandler>()?.let { method to it } }
.toMap()
for ((method, data) in handlersOfListener) {
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>
if (!eventClass.isSuperclassOf(klass))
throw InvalidEventHandlerException("${method.name}'s first parameter type is incompatible with the " +
"one required by the EventBus")
throw InvalidEventHandlerException(
"${method.name}'s first parameter type is incompatible with the " +
"one required by the EventBus"
)
@Suppress("UNCHECKED_CAST")
val handler = Handler(
@ -71,9 +73,9 @@ class EventBus<EventT: Event>(private val eventClass: KClass<EventT>, private va
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 listener: Listener,
val fn: KFunction<T>,

View file

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

View file

@ -1,13 +1,13 @@
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.
* You should never reuse [listener] for other groups or directly on event targets
* 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.

View file

@ -14,9 +14,23 @@ class Logger(name: String) {
infix fun debug(msg: String) = logger.debug(msg)
infix fun trace(msg: String) = logger.trace(msg)
infix fun error(fn: () -> String) { if (logger.isErrorEnabled) logger.error(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()) }
infix fun error(fn: () -> String) {
if (logger.isErrorEnabled) logger.error(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 java.net.InetAddress
interface Session: EventTarget<SessionEvent> {
interface Session : EventTarget<SessionEvent> {
/**
* 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.Listener
class SessionGroup: EventTargetGroup<Session> {
class SessionGroup : EventTargetGroup<Session> {
private val sessions = mutableSetOf<Session>()
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.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
}

View file

@ -4,6 +4,6 @@ import space.blokk.events.Cancellable
import space.blokk.net.Session
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
}

View file

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

View file

@ -3,4 +3,4 @@ package space.blokk.net.events
import space.blokk.events.Event
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)"
}
abstract class IncomingPacket: Packet()
abstract class IncomingPacket : Packet()
abstract class OutgoingPacket: Packet() {
abstract class OutgoingPacket : Packet() {
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,
packetType: KClass<T>
): PacketCompanion<T>(id, packetType) {
) : PacketCompanion<T>(id, packetType) {
abstract fun decode(msg: ByteBuf): T
}
abstract class OutgoingPacketCompanion<T: OutgoingPacket>(
abstract class OutgoingPacketCompanion<T : OutgoingPacket>(
id: Int,
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 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() {
ensureDistinctIDs(incomingPackets, "serverbound")

View file

@ -22,15 +22,15 @@ data class HandshakePacket(
val serverAddress: String,
val serverPort: Int,
val loginAttempt: Boolean
): IncomingPacket() {
companion object: IncomingPacketCompanion<HandshakePacket>(0x00, HandshakePacket::class) {
) : IncomingPacket() {
companion object : IncomingPacketCompanion<HandshakePacket>(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
protocolVersion = msg.readVarInt(),
serverAddress = msg.readString(),
serverPort = msg.readUnsignedShort(),
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.
*/
data class DisconnectPacket(val reason: ChatComponent): OutgoingPacket() {
companion object: OutgoingPacketCompanion<DisconnectPacket>(0x00, DisconnectPacket::class)
data class DisconnectPacket(val reason: ChatComponent) : OutgoingPacket() {
companion object : OutgoingPacketCompanion<DisconnectPacket>(0x00, DisconnectPacket::class)
override fun encode(dst: ByteBuf) {
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>
*/
data class EncryptionRequestPacket(
val serverID: String,
val publicKey: ByteArray,
val verifyToken: ByteArray
): OutgoingPacket() {
companion object: OutgoingPacketCompanion<EncryptionRequestPacket>(0x01, EncryptionRequestPacket::class)
val serverID: String,
val publicKey: ByteArray,
val verifyToken: ByteArray
) : OutgoingPacket() {
companion object : OutgoingPacketCompanion<EncryptionRequestPacket>(0x01, EncryptionRequestPacket::class)
init {
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>
*/
data class EncryptionResponsePacket(
val sharedSecret: ByteArray,
val verifyToken: ByteArray
): IncomingPacket() {
companion object: IncomingPacketCompanion<EncryptionResponsePacket>(0x01, EncryptionResponsePacket::class) {
val sharedSecret: ByteArray,
val verifyToken: ByteArray
) : IncomingPacket() {
companion object : IncomingPacketCompanion<EncryptionResponsePacket>(0x01, EncryptionResponsePacket::class) {
override fun decode(msg: ByteBuf): EncryptionResponsePacket {
return with(MinecraftDataTypes) {
val sharedSecretLength = msg.readVarInt()

View file

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

View file

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

View file

@ -2,7 +2,8 @@ package space.blokk.net.protocols.login
import space.blokk.net.protocols.Protocol
object LoginProtocol: Protocol("LOGIN", setOf(
object LoginProtocol : Protocol(
"LOGIN", setOf(
DisconnectPacket,
LoginStartPacket,
EncryptionRequestPacket,
@ -11,4 +12,5 @@ object LoginProtocol: Protocol("LOGIN", setOf(
LoginSuccessPacket,
LoginPluginRequestPacket,
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.
*/
data class LoginStartPacket(val username: String): IncomingPacket() {
companion object: IncomingPacketCompanion<LoginStartPacket>(0x00, LoginStartPacket::class) {
data class LoginStartPacket(val username: String) : IncomingPacket() {
companion object : IncomingPacketCompanion<LoginStartPacket>(0x00, LoginStartPacket::class) {
override fun decode(msg: ByteBuf): LoginStartPacket {
return with(MinecraftDataTypes) { LoginStartPacket(msg.readString()) }
}

View file

@ -14,8 +14,8 @@ import java.util.*
* @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<LoginSuccessPacket>(0x02, LoginSuccessPacket::class)
data class LoginSuccessPacket(val uuid: UUID, val username: String) : OutgoingPacket() {
companion object : OutgoingPacketCompanion<LoginSuccessPacket>(0x02, LoginSuccessPacket::class)
init {
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.
*/
data class SetCompressionPacket(val threshold: Int): OutgoingPacket() {
companion object: OutgoingPacketCompanion<SetCompressionPacket>(0x03, SetCompressionPacket::class)
data class SetCompressionPacket(val threshold: Int) : OutgoingPacket() {
companion object : OutgoingPacketCompanion<SetCompressionPacket>(0x03, SetCompressionPacket::class)
override fun encode(dst: ByteBuf) {
dst.writeVarInt(threshold)

View file

@ -11,7 +11,7 @@ import space.blokk.net.protocols.IncomingPacketCompanion
*
* @see [space.blokk.net.events.ServerListInfoRequestEvent]
*/
class RequestPacket: IncomingPacket() {
class RequestPacket : IncomingPacket() {
companion object : IncomingPacketCompanion<RequestPacket>(0x00, RequestPacket::class) {
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
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.server.events.ServerEvent
interface Server: EventTarget<ServerEvent> {
interface Server : EventTarget<ServerEvent> {
override val eventBus: EventBus<ServerEvent>
val scope: CoroutineScope
}

View file

@ -2,4 +2,4 @@ package space.blokk.server.events
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.net.Session
class SessionInitializedEvent(val session: Session): ServerEvent(), Cancellable {
class SessionInitializedEvent(val session: Session) : ServerEvent(), Cancellable {
override var isCancelled: Boolean = false
}

View file

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

View file

@ -1,4 +1,5 @@
package space.blokk.events
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
@ -10,11 +11,11 @@ import strikt.api.expectThrows
import strikt.assertions.*
import kotlin.system.measureTimeMillis
private abstract class TestEvent: Event()
private class FirstEvent: TestEvent()
private class SecondEvent: TestEvent()
private abstract class TestEvent : Event()
private class FirstEvent : TestEvent()
private class SecondEvent : TestEvent()
object EventBusTest: Spek({
object EventBusTest : Spek({
describe("EventBus") {
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.style.specification.describe
object ProtocolsTest: Spek({
object ProtocolsTest : Spek({
describe("Protocols") {
it("are valid") {
Protocols.validate()

View file

@ -1,5 +1,3 @@
plugins {
kotlin("jvm")
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.events.ServerEvent
class BlokkServer internal constructor(): Server {
init { i = this }
class BlokkServer internal constructor() : Server {
init {
i = this
}
override val scope = CoroutineScope(CoroutineName("BlokkServer"))
override val eventBus = EventBus(ServerEvent::class, scope)
@ -52,7 +54,14 @@ class BlokkServer internal constructor(): Server {
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))
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.util.*
class ConsoleAppender: AppenderBase<ILoggingEvent>() {
class ConsoleAppender : AppenderBase<ILoggingEvent>() {
private val dateFormat = SimpleDateFormat("HH:mm:ss.SSS")
override fun append(event: ILoggingEvent) {
@ -23,13 +23,15 @@ class ConsoleAppender: AppenderBase<ILoggingEvent>() {
else -> khalk
}
stream.println(listOf(
khalk.gray { dateFormat.format(Date(event.timeStamp)) },
color { event.level.toString().padEnd(5) },
khalk.bold { event.threadName },
color.inverse { " ${event.loggerName} " },
color { "" },
event.message
).joinToString(" "))
stream.println(
listOf(
khalk.gray { dateFormat.format(Date(event.timeStamp)) },
color { event.level.toString().padEnd(5) },
khalk.bold { event.threadName },
color.inverse { " ${event.loggerName} " },
color { "" },
event.message
).joinToString(" ")
)
}
}

View file

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

View file

@ -4,6 +4,7 @@ import io.netty.channel.Channel
import kotlinx.coroutines.*
import space.blokk.BlokkServer
import space.blokk.events.*
import space.blokk.logging.Logger
import space.blokk.net.events.PacketReceivedEvent
import space.blokk.net.events.PacketSendEvent
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.handshaking.HandshakingProtocol
import space.blokk.server.events.SessionInitializedEvent
import space.blokk.logging.Logger
import space.blokk.utils.awaitSuspending
import java.net.InetAddress
import java.net.InetSocketAddress

View file

@ -19,14 +19,16 @@ class BlokkSocketServer(private val blokkServer: BlokkServer) {
private val bossGroup = createEventLoopGroup()
private val workerGroup = createEventLoopGroup()
private val bootstrap: ServerBootstrap = ServerBootstrap()
.group(bossGroup, workerGroup)
.channel(when {
.group(bossGroup, workerGroup)
.channel(
when {
EPOLL_AVAILABLE -> EpollServerSocketChannel::class.java
KQUEUE_AVAILABLE -> KQueueServerSocketChannel::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))
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)
companion object {
fun <T: IncomingPacket> of(fn: suspend (session: BlokkSession, packet: T) -> Unit) =
object : PacketReceivedEventHandler<T>() {
override suspend fun handle(session: BlokkSession, packet: T) = fn(session, packet)
}
fun <T : IncomingPacket> of(fn: suspend (session: BlokkSession, packet: T) -> Unit) =
object : PacketReceivedEventHandler<T>() {
override suspend fun handle(session: BlokkSession, packet: T) = fn(session, packet)
}
}
}
object SessionPacketReceivedEventHandler {
suspend fun handle(session: BlokkSession, packet: IncomingPacket) {
val handler = when(session.currentProtocol) {
val handler = when (session.currentProtocol) {
HandshakingProtocol -> HandshakingProtocolHandler
StatusProtocol -> StatusProtocolHandler
else -> return

View file

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

View file

@ -7,9 +7,14 @@ import space.blokk.BlokkServer
import space.blokk.net.protocols.OutgoingPacket
import java.io.IOException
class PacketCodec(private val session: BlokkSession): MessageToMessageCodec<ByteBuf, PacketMessage<*>>() {
override fun channelActive(ctx: ChannelHandlerContext) { session.onConnect() }
override fun channelInactive(ctx: ChannelHandlerContext) { session.onDisconnect() }
class PacketCodec(private val session: BlokkSession) : MessageToMessageCodec<ByteBuf, PacketMessage<*>>() {
override fun channelActive(ctx: ChannelHandlerContext) {
session.onConnect()
}
override fun channelInactive(ctx: ChannelHandlerContext) {
session.onDisconnect()
}
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.")

View file

@ -3,11 +3,13 @@ package space.blokk.net
import space.blokk.net.protocols.Packet
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 {
@Suppress("UNCHECKED_CAST")
session.currentProtocol.packetCompanionsByPacketType[packet::class] as PacketCompanion<T>?
?: throw Exception("No packet companion found for this packet type. " +
"This can happen if the packet is not part of the current protocol.")
?: throw Exception(
"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.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<*>) {
if (msg.packet !is IncomingPacket) throw Error("Only serverbound packets are allowed. This should never happen.")
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.status.StatusProtocol
object HandshakingProtocolHandler: ProtocolPacketReceivedEventHandler(mapOf(
HandshakePacket to PacketReceivedEventHandler.of<HandshakePacket> { session, packet ->
session.currentProtocol = if (packet.loginAttempt) LoginProtocol else StatusProtocol
}
object HandshakingProtocolHandler : ProtocolPacketReceivedEventHandler(mapOf(
HandshakePacket to PacketReceivedEventHandler.of<HandshakePacket> { session, packet ->
session.currentProtocol = if (packet.loginAttempt) LoginProtocol else StatusProtocol
}
))

View file

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