package ru.dbotthepony.kstarbound.client import io.netty.bootstrap.Bootstrap import io.netty.channel.Channel import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelInitializer import io.netty.channel.local.LocalAddress import io.netty.channel.local.LocalChannel import io.netty.channel.socket.nio.NioSocketChannel import org.apache.logging.log4j.LogManager import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.network.Connection import ru.dbotthepony.kstarbound.network.ConnectionSide import ru.dbotthepony.kstarbound.network.ConnectionType import ru.dbotthepony.kstarbound.network.IClientPacket import ru.dbotthepony.kstarbound.network.packets.ProtocolRequestPacket import java.net.SocketAddress import java.util.* // client -> server class ClientConnection(val client: StarboundClient, type: ConnectionType, uuid: UUID) : Connection(ConnectionSide.CLIENT, type, uuid) { private fun sendHello() { isLegacy = true sendAndFlush(ProtocolRequestPacket(Starbound.LEGACY_PROTOCOL_VERSION)) } var connectionID: Int = -1 override fun inGame() { } override fun channelRead(ctx: ChannelHandlerContext, msg: Any) { if (msg is IClientPacket) { try { msg.play(this) } catch (err: Throwable) { LOGGER.error("Failed to read incoming packet $msg", err) disconnect(err.toString()) } } else { LOGGER.error("Unknown incoming packet type $msg") disconnect("Unknown incoming packet type $msg") } } companion object { private val LOGGER = LogManager.getLogger() fun connectToLocalServer(client: StarboundClient, address: LocalAddress, uuid: UUID): ClientConnection { LOGGER.info("Trying to connect to local server at $address with Client UUID $uuid") val connection = ClientConnection(client, ConnectionType.MEMORY, uuid) Bootstrap() .group(NIO_POOL) .channel(LocalChannel::class.java) .handler(object : ChannelInitializer() { override fun initChannel(ch: Channel) { connection.bind(ch) } }) .connect(address) .syncUninterruptibly() connection.sendHello() return connection } fun connectToLocalServer(client: StarboundClient, address: Channel, uuid: UUID): ClientConnection { return connectToLocalServer(client, address.localAddress() as LocalAddress, uuid) } fun connectToRemoteServer(client: StarboundClient, address: SocketAddress, uuid: UUID): ClientConnection { LOGGER.info("Trying to connect to remote server at $address with Client UUID $uuid") val connection = ClientConnection(client, ConnectionType.NETWORK, uuid) Bootstrap() .group(NIO_POOL) .channel(NioSocketChannel::class.java) .handler(object : ChannelInitializer() { override fun initChannel(ch: Channel) { connection.bind(ch) } }) .connect(address) .syncUninterruptibly() connection.sendHello() return connection } } }