124 lines
3.7 KiB
Kotlin
124 lines
3.7 KiB
Kotlin
package ru.dbotthepony.kstarbound.network
|
|
|
|
import com.google.common.util.concurrent.ThreadFactoryBuilder
|
|
import io.netty.channel.Channel
|
|
import io.netty.channel.ChannelHandlerContext
|
|
import io.netty.channel.ChannelInboundHandlerAdapter
|
|
import io.netty.channel.ChannelOption
|
|
import io.netty.channel.nio.NioEventLoopGroup
|
|
import org.apache.logging.log4j.LogManager
|
|
import ru.dbotthepony.kstarbound.network.packets.DisconnectPacket
|
|
import ru.dbotthepony.kstarbound.network.packets.HelloListener
|
|
import ru.dbotthepony.kstarbound.network.packets.HelloPacket
|
|
import ru.dbotthepony.kstarbound.player.Avatar
|
|
import ru.dbotthepony.kstarbound.world.entities.PlayerEntity
|
|
import java.util.*
|
|
|
|
abstract class Connection(val side: ConnectionSide, val type: ConnectionType, val localUUID: UUID) : ChannelInboundHandlerAdapter(), IConnectionDetails {
|
|
abstract override fun channelRead(ctx: ChannelHandlerContext, msg: Any)
|
|
|
|
var avatar: Avatar? = null
|
|
var character: PlayerEntity? = null
|
|
|
|
protected var channel: Channel? = null
|
|
protected var otherSide: HelloPacket? = null
|
|
protected var helloListener: HelloListener? = null
|
|
|
|
override val protocolVersion: Int
|
|
get() = otherSide?.protocolVersion ?: 0
|
|
override val engineVersion: String
|
|
get() = otherSide?.engineVersion ?: "0.0.0"
|
|
override val username: String
|
|
get() = otherSide?.username ?: ""
|
|
override val password: String
|
|
get() = otherSide?.password ?: ""
|
|
override val uuid: UUID
|
|
get() = otherSide?.uuid ?: EMPTY_UUID
|
|
|
|
fun bind(channel: Channel) {
|
|
check(this.channel == null) { "Already having channel bound" }
|
|
channel.config().setOption(ChannelOption.TCP_NODELAY, true)
|
|
this.channel = channel
|
|
|
|
if (side == ConnectionSide.SERVER)
|
|
helloListener = HelloListener(this, channel)
|
|
}
|
|
|
|
protected abstract fun onHelloReceived(helloPacket: HelloPacket)
|
|
protected abstract fun inGame()
|
|
|
|
fun helloReceived(helloPacket: HelloPacket) {
|
|
LOGGER.info("Handshake received on $side from ${channel?.remoteAddress()}: $helloPacket")
|
|
otherSide = helloPacket
|
|
|
|
if (side == ConnectionSide.SERVER) {
|
|
helloListener!!.sendHello(localUUID)
|
|
}
|
|
|
|
onHelloReceived(helloPacket)
|
|
initializeHandlers()
|
|
}
|
|
|
|
fun helloFailed() {
|
|
channel!!.close()
|
|
}
|
|
|
|
fun initializeHandlers() {
|
|
val channel = channel ?: throw IllegalStateException("No network channel is bound")
|
|
|
|
if (type == ConnectionType.NETWORK) {
|
|
channel.pipeline().addLast(PacketRegistry.NATIVE.Inbound(side))
|
|
} else {
|
|
channel.pipeline().addLast(PacketRegistry.NATIVE.InboundValidator(side))
|
|
}
|
|
|
|
channel.pipeline().addLast(this)
|
|
|
|
if (type == ConnectionType.NETWORK) {
|
|
channel.pipeline().addLast(PacketRegistry.NATIVE.Outbound(side))
|
|
|
|
channel.pipeline().addFirst(DatagramEncoder)
|
|
channel.pipeline().addFirst(DatagramDecoder())
|
|
} else {
|
|
channel.pipeline().addLast(PacketRegistry.NATIVE.OutboundValidator(side))
|
|
}
|
|
|
|
inGame()
|
|
}
|
|
|
|
fun send(packet: IPacket) {
|
|
val channel = channel ?: throw IllegalStateException("No network channel is bound")
|
|
channel.write(packet)
|
|
}
|
|
|
|
fun sendAndFlush(packet: IPacket) {
|
|
val channel = channel ?: throw IllegalStateException("No network channel is bound")
|
|
channel.write(packet)
|
|
channel.flush()
|
|
}
|
|
|
|
fun flush() {
|
|
val channel = channel ?: throw IllegalStateException("No network channel is bound")
|
|
channel.flush()
|
|
}
|
|
|
|
fun disconnect(reason: String) {
|
|
if (side == ConnectionSide.CLIENT) {
|
|
channel!!.close()
|
|
} else {
|
|
channel!!.write(DisconnectPacket(reason))
|
|
channel!!.flush()
|
|
channel!!.close()
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
private val EMPTY_UUID = UUID(0L, 0L)
|
|
private val LOGGER = LogManager.getLogger()
|
|
|
|
val NIO_POOL by lazy {
|
|
NioEventLoopGroup(ThreadFactoryBuilder().setDaemon(true).setNameFormat("Starbound Network IO %d").build())
|
|
}
|
|
}
|
|
}
|