Reformat code to use the official kotlin code style
This commit is contained in:
parent
da7397e7f2
commit
0a4f835327
47 changed files with 199 additions and 153 deletions
30
.github/workflows/build_and_test.yml
vendored
30
.github/workflows/build_and_test.yml
vendored
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
package space.blokk.events
|
||||
|
||||
interface EventTarget<T: Event> {
|
||||
interface EventTarget<T : Event> {
|
||||
val eventBus: EventBus<T>
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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>()
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
))
|
||||
)
|
||||
)
|
||||
|
|
|
@ -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()) }
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -2,4 +2,4 @@ package space.blokk.server.events
|
|||
|
||||
import space.blokk.events.Event
|
||||
|
||||
abstract class ServerEvent: Event()
|
||||
abstract class ServerEvent : Event()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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)) }
|
||||
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
id("com.github.johnrengelman.shadow") version "6.0.0"
|
||||
|
|
|
@ -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
|
||||
)
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
|
|
|
@ -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(" ")
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.")
|
||||
|
|
|
@ -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."
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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}" }
|
||||
|
|
|
@ -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
|
||||
}
|
||||
))
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
))
|
||||
|
|
Reference in a new issue