package ru.dbotthepony.kstarbound.network import io.netty.buffer.ByteBuf import it.unimi.dsi.fastutil.bytes.ByteArrayList import ru.dbotthepony.kstarbound.client.ClientConnection import ru.dbotthepony.kstarbound.server.ServerConnection import java.io.DataInputStream import java.io.DataOutputStream import kotlin.reflect.KClass import kotlin.reflect.full.isSubclassOf fun ByteBuf.writeUTF(value: String) { writeBytes(value.toByteArray().also { check(!it.any { it.toInt() == 0 }) { "Provided UTF string contains NUL" } }) writeByte(0) } fun ByteBuf.readUTF(): String { val bytes = ByteArrayList() var read = readByte() while (read.toInt() != 0) { bytes.add(read) read = readByte() } return String(bytes.toByteArray()) } enum class ConnectionSide { SERVER, CLIENT; val opposite: ConnectionSide get() = if (this == SERVER) CLIENT else SERVER } enum class ConnectionState { FRESH, WORKING, CLOSED; } enum class PacketDirection(val acceptOnClient: Boolean, val acceptOnServer: Boolean) { FROM_SERVER(true, false), FROM_CLIENT(false, true), BI_DIRECTIONAL(true, true); fun acceptedOn(side: ConnectionSide): Boolean { if (side == ConnectionSide.SERVER) return acceptOnServer return acceptOnClient } companion object { fun get(type: KClass): PacketDirection { return of(type.isSubclassOf(IClientPacket::class), type.isSubclassOf(IServerPacket::class)) } fun of(allowedOnClient: Boolean, allowedOnServer: Boolean): PacketDirection { if (allowedOnServer && allowedOnClient) return BI_DIRECTIONAL else if (allowedOnServer) return FROM_CLIENT else if (allowedOnClient) return FROM_SERVER else throw IllegalArgumentException("Packet is not allowed on either side") } } } enum class ConnectionType { NETWORK, MEMORY; } fun interface IPacketReader { fun read(stream: DataInputStream, isLegacy: Boolean): T } interface IPacket { fun write(stream: DataOutputStream, isLegacy: Boolean) } interface IServerPacket : IPacket { fun play(connection: ServerConnection) } interface IClientPacket : IPacket { fun play(connection: ClientConnection) }