Now original game client can properly connect and be on server, and also can request a disconnect

This commit is contained in:
DBotThePony 2024-03-19 16:59:01 +07:00
parent 66aa99acc2
commit 21f3a66283
Signed by: DBot
GPG Key ID: DCC23B5715498507
7 changed files with 101 additions and 13 deletions

View File

@ -16,6 +16,7 @@ import ru.dbotthepony.kstarbound.network.ConnectionType
import ru.dbotthepony.kstarbound.network.IClientPacket
import ru.dbotthepony.kstarbound.network.packets.ClientContextUpdatePacket
import ru.dbotthepony.kstarbound.network.packets.ProtocolRequestPacket
import ru.dbotthepony.kstarbound.network.packets.serverbound.ClientDisconnectRequestPacket
import java.net.SocketAddress
import java.util.*
@ -50,15 +51,47 @@ class ClientConnection(val client: StarboundClient, type: ConnectionType) : Conn
}
override fun flush() {
val entries = rpc.write()
if (!pendingDisconnect) {
val entries = rpc.write()
if (entries != null) {
channel.write(ClientContextUpdatePacket(entries, KOptional(), KOptional()))
if (entries != null) {
channel.write(ClientContextUpdatePacket(entries, KOptional(), KOptional()))
}
}
super.flush()
}
private var pendingDisconnect = false
fun disconnectNow() {
pendingDisconnect = false
if (channel.isOpen) {
channel.close()
}
}
override fun disconnect(reason: String) {
if (pendingDisconnect)
return
if (channel.isOpen) {
pendingDisconnect = true
sendAndFlush(ClientDisconnectRequestPacket)
} else {
disconnectNow()
}
}
override fun onChannelClosed() {
super.onChannelClosed()
if (pendingDisconnect) {
disconnectNow()
}
}
companion object {
private val LOGGER = LogManager.getLogger()

View File

@ -26,7 +26,7 @@ abstract class Connection(val side: ConnectionSide, val type: ConnectionType) :
val hasChannel get() = ::channel.isInitialized
lateinit var channel: Channel
protected set
private set
var isLegacy: Boolean = true
protected set
@ -113,10 +113,7 @@ abstract class Connection(val side: ConnectionSide, val type: ConnectionType) :
channel.flush()
}
fun disconnect(reason: String) {
channel.flush()
channel.close()
}
abstract fun disconnect(reason: String = "")
override fun close() {
channel.close()

View File

@ -33,6 +33,7 @@ import ru.dbotthepony.kstarbound.network.packets.clientbound.LegacyTileUpdatePac
import ru.dbotthepony.kstarbound.network.packets.clientbound.ServerDisconnectPacket
import ru.dbotthepony.kstarbound.network.packets.clientbound.WorldStartPacket
import ru.dbotthepony.kstarbound.network.packets.clientbound.WorldStopPacket
import ru.dbotthepony.kstarbound.network.packets.serverbound.ClientDisconnectRequestPacket
import ru.dbotthepony.kstarbound.server.network.packets.TrackedPositionPacket
import ru.dbotthepony.kstarbound.server.network.packets.TrackedSizePacket
import java.io.BufferedInputStream
@ -202,7 +203,7 @@ class PacketRegistry(val isLegacy: Boolean) {
LOGGER.error("Packet ($packetType/${type.type}) of ${dataLength.absoluteValue} bytes is bigger than maximum allowed $MAX_PACKET_SIZE bytes")
discardBytes = dataLength.absoluteValue
} else {
LOGGER.debug("Packet type {} ({}) received on {} (size {} bytes)", packetType, type.type, side, dataLength.absoluteValue)
// LOGGER.debug("Packet type {} ({}) received on {} (size {} bytes)", packetType, type.type, side, dataLength.absoluteValue)
readingType = type
readableBytes = dataLength.absoluteValue
isCompressed = dataLength < 0
@ -252,7 +253,7 @@ class PacketRegistry(val isLegacy: Boolean) {
stream2.writeByte(type.id)
stream2.writeSignedVarInt(-buffers.size)
stream2.write(buffers.elements(), 0, buffers.size)
LOGGER.debug("Packet type {} ({}) sent from {} (size {} bytes / COMPRESSED size {} bytes)", type.id, type.type, side, stream.length, buffers.size)
// LOGGER.debug("Packet type {} ({}) sent from {} (size {} bytes / COMPRESSED size {} bytes)", type.id, type.type, side, stream.length, buffers.size)
ctx.write(buff, promise)
} else {
// send as-is
@ -261,7 +262,7 @@ class PacketRegistry(val isLegacy: Boolean) {
stream2.writeByte(type.id)
stream2.writeSignedVarInt(stream.length)
stream2.write(stream.array, 0, stream.length)
LOGGER.debug("Packet type {} ({}) sent from {} (size {} bytes)", type.id, type.type, side, stream.length)
// LOGGER.debug("Packet type {} ({}) sent from {} (size {} bytes)", type.id, type.type, side, stream.length)
ctx.write(buff, promise)
}
}
@ -349,7 +350,7 @@ class PacketRegistry(val isLegacy: Boolean) {
// Packets sent universe client -> universe server
LEGACY.add(::ClientConnectPacket) // ClientConnect
LEGACY.skip("ClientDisconnectRequest")
LEGACY.add(ClientDisconnectRequestPacket::read)
LEGACY.add(::HandshakeResponsePacket) // HandshakeResponse
LEGACY.skip("PlayerWarp")
LEGACY.skip("FlyShip")

View File

@ -15,6 +15,6 @@ class ServerDisconnectPacket(val reason: String = "") : IClientPacket {
}
override fun play(connection: ClientConnection) {
TODO("Not yet implemented")
connection.disconnectNow()
}
}

View File

@ -0,0 +1,21 @@
package ru.dbotthepony.kstarbound.network.packets.serverbound
import ru.dbotthepony.kstarbound.network.IServerPacket
import ru.dbotthepony.kstarbound.server.ServerConnection
import java.io.DataInputStream
import java.io.DataOutputStream
object ClientDisconnectRequestPacket : IServerPacket {
override fun write(stream: DataOutputStream, isLegacy: Boolean) {
if (isLegacy) stream.writeBoolean(false)
}
override fun play(connection: ServerConnection) {
connection.disconnect("Disconnect by user.")
}
fun read(stream: DataInputStream, isLegacy: Boolean): ClientDisconnectRequestPacket {
if (isLegacy) stream.readBoolean()
return ClientDisconnectRequestPacket
}
}

View File

@ -1,5 +1,6 @@
package ru.dbotthepony.kstarbound.server
import com.google.gson.JsonObject
import io.netty.channel.ChannelHandlerContext
import it.unimi.dsi.fastutil.bytes.ByteArrayList
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
@ -20,6 +21,7 @@ import ru.dbotthepony.kstarbound.network.ConnectionType
import ru.dbotthepony.kstarbound.network.IServerPacket
import ru.dbotthepony.kstarbound.network.packets.ClientContextUpdatePacket
import ru.dbotthepony.kstarbound.network.packets.clientbound.LegacyTileArrayUpdatePacket
import ru.dbotthepony.kstarbound.network.packets.clientbound.ServerDisconnectPacket
import ru.dbotthepony.kstarbound.server.world.IChunkSource
import ru.dbotthepony.kstarbound.server.world.LegacyChunkSource
import ru.dbotthepony.kstarbound.server.world.ServerWorld
@ -41,6 +43,10 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
init {
connectionID = server.nextConnectionID.incrementAndGet()
rpc.add("team.fetchTeamStatus") {
JsonObject()
}
}
override fun toString(): String {
@ -145,6 +151,28 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
}
}
override fun disconnect(reason: String) {
if (channel.isOpen) {
// send pending updates
flush()
}
tickets.values.forEach { it.cancel() }
tickets.clear()
pendingSend.clear()
if (::shipWorld.isInitialized) {
shipWorld.close()
}
if (channel.isOpen) {
// say goodbye
channel.write(ServerDisconnectPacket(reason))
channel.flush()
channel.close()
}
}
private fun recomputeTrackedChunks() {
val world = world ?: return
val trackedPositionChunk = world.geometry.chunkFromCell(trackedPosition)

View File

@ -4,6 +4,7 @@ import com.google.gson.JsonObject
import it.unimi.dsi.fastutil.longs.Long2ObjectFunction
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.collect.chainOptionalFutures
import ru.dbotthepony.kommons.util.KOptional
import ru.dbotthepony.kstarbound.Starbound
@ -126,6 +127,8 @@ class ServerWorld(
override fun close() {
if (isClosed.compareAndSet(false, true)) {
LOGGER.info("Shutting down $this")
super.close()
spinner.unpause()
@ -135,6 +138,7 @@ class ServerWorld(
}
}
server.worlds.remove(this)
LockSupport.unpark(thread)
}
}
@ -394,4 +398,8 @@ class ServerWorld(
}
}
}
companion object {
private val LOGGER = LogManager.getLogger()
}
}