More work on legacy protocol

This commit is contained in:
DBotThePony 2024-02-12 16:06:51 +07:00
parent c2dc7c2e11
commit fd233b9ab5
Signed by: DBot
GPG Key ID: DCC23B5715498507
17 changed files with 209 additions and 122 deletions

View File

@ -2,7 +2,7 @@ kotlin.code.style=official
org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m org.gradle.jvmargs=-Xmx2g -XX:MaxMetaspaceSize=512m
kotlinVersion=1.9.0 kotlinVersion=1.9.0
kommonsVersion=2.1.5 kommonsVersion=2.1.8
ffiVersion=2.2.13 ffiVersion=2.2.13
lwjglVersion=3.3.0 lwjglVersion=3.3.0

View File

@ -83,7 +83,8 @@ fun main() {
//item.movement.applyVelocity(Vector2d(rand.nextDouble() * 1000.0 - 500.0, rand.nextDouble() * 1000.0 - 500.0)) //item.movement.applyVelocity(Vector2d(rand.nextDouble() * 1000.0 - 500.0, rand.nextDouble() * 1000.0 - 500.0))
} }
client.connectToLocalServer(server.channels.createLocalChannel(), UUID.randomUUID()) //client.connectToLocalServer(server.channels.createLocalChannel(), UUID.randomUUID())
client.connectToRemoteServer(InetSocketAddress("127.0.0.1", 21025), UUID.randomUUID())
//client2.connectToLocalServer(server.channels.createLocalChannel(), UUID.randomUUID()) //client2.connectToLocalServer(server.channels.createLocalChannel(), UUID.randomUUID())
server.channels.createChannel(InetSocketAddress(21060)) server.channels.createChannel(InetSocketAddress(21060))
} }

View File

@ -24,6 +24,8 @@ class ClientConnection(val client: StarboundClient, type: ConnectionType, uuid:
sendAndFlush(ProtocolRequestPacket(Starbound.LEGACY_PROTOCOL_VERSION)) sendAndFlush(ProtocolRequestPacket(Starbound.LEGACY_PROTOCOL_VERSION))
} }
var connectionID: Int = -1
override fun inGame() { override fun inGame() {
} }

View File

@ -2,10 +2,10 @@ package ru.dbotthepony.kstarbound.client.network.packets
import ru.dbotthepony.kommons.io.readCollection import ru.dbotthepony.kommons.io.readCollection
import ru.dbotthepony.kommons.io.writeCollection import ru.dbotthepony.kommons.io.writeCollection
import ru.dbotthepony.kommons.io.writeStruct2i
import ru.dbotthepony.kstarbound.client.ClientConnection import ru.dbotthepony.kstarbound.client.ClientConnection
import ru.dbotthepony.kstarbound.network.IClientPacket import ru.dbotthepony.kstarbound.network.IClientPacket
import ru.dbotthepony.kstarbound.io.readChunkPos import ru.dbotthepony.kstarbound.io.readChunkPos
import ru.dbotthepony.kstarbound.io.writeVec2i
import ru.dbotthepony.kstarbound.world.CHUNK_SIZE import ru.dbotthepony.kstarbound.world.CHUNK_SIZE
import ru.dbotthepony.kstarbound.world.Chunk import ru.dbotthepony.kstarbound.world.Chunk
import ru.dbotthepony.kstarbound.world.ChunkPos import ru.dbotthepony.kstarbound.world.ChunkPos
@ -25,7 +25,7 @@ class ChunkCellsPacket(val pos: ChunkPos, val data: List<ImmutableCell>) : IClie
}) })
override fun write(stream: DataOutputStream, isLegacy: Boolean) { override fun write(stream: DataOutputStream, isLegacy: Boolean) {
stream.writeVec2i(pos) stream.writeStruct2i(pos)
stream.writeCollection(data) { it.write(stream) } stream.writeCollection(data) { it.write(stream) }
} }

View File

@ -1,9 +1,9 @@
package ru.dbotthepony.kstarbound.client.network.packets package ru.dbotthepony.kstarbound.client.network.packets
import ru.dbotthepony.kommons.io.writeStruct2i
import ru.dbotthepony.kstarbound.client.ClientConnection import ru.dbotthepony.kstarbound.client.ClientConnection
import ru.dbotthepony.kstarbound.network.IClientPacket import ru.dbotthepony.kstarbound.network.IClientPacket
import ru.dbotthepony.kstarbound.io.readChunkPos import ru.dbotthepony.kstarbound.io.readChunkPos
import ru.dbotthepony.kstarbound.io.writeVec2i
import ru.dbotthepony.kstarbound.world.ChunkPos import ru.dbotthepony.kstarbound.world.ChunkPos
import java.io.DataInputStream import java.io.DataInputStream
import java.io.DataOutputStream import java.io.DataOutputStream
@ -12,7 +12,7 @@ class ForgetChunkPacket(val pos: ChunkPos) : IClientPacket {
constructor(stream: DataInputStream, isLegacy: Boolean) : this(stream.readChunkPos()) constructor(stream: DataInputStream, isLegacy: Boolean) : this(stream.readChunkPos())
override fun write(stream: DataOutputStream, isLegacy: Boolean) { override fun write(stream: DataOutputStream, isLegacy: Boolean) {
stream.writeVec2i(pos) stream.writeStruct2i(pos)
} }
override fun play(connection: ClientConnection) { override fun play(connection: ClientConnection) {

View File

@ -1,8 +1,8 @@
package ru.dbotthepony.kstarbound.defs package ru.dbotthepony.kstarbound.defs
import ru.dbotthepony.kommons.io.readVector2i
import ru.dbotthepony.kommons.io.writeStruct2i import ru.dbotthepony.kommons.io.writeStruct2i
import ru.dbotthepony.kommons.vector.Vector2i import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kstarbound.io.readVec2i
import ru.dbotthepony.kstarbound.json.builder.JsonFactory import ru.dbotthepony.kstarbound.json.builder.JsonFactory
import java.io.DataInputStream import java.io.DataInputStream
import java.io.DataOutputStream import java.io.DataOutputStream
@ -19,8 +19,8 @@ data class CelestialBaseInformation(
stream.readInt(), stream.readInt(),
stream.readInt(), stream.readInt(),
stream.readInt(), stream.readInt(),
stream.readVec2i(), stream.readVector2i(),
stream.readVec2i(), stream.readVector2i(),
) )
fun write(stream: DataOutputStream, isLegacy: Boolean) { fun write(stream: DataOutputStream, isLegacy: Boolean) {

View File

@ -19,6 +19,15 @@ data class ShipUpgrades(
val shipSpeed: Int = 0, val shipSpeed: Int = 0,
val capabilities: ImmutableSet<String> = ImmutableSet.of() val capabilities: ImmutableSet<String> = ImmutableSet.of()
) { ) {
constructor(stream: DataInputStream, isLegacy: Boolean) : this(
stream.readInt(),
stream.readInt(),
stream.readInt(),
if (isLegacy) stream.readFloat().toDouble() else stream.readDouble(),
stream.readInt(),
ImmutableSet.copyOf(stream.readCollection { readBinaryString() })
)
fun apply(upgrades: ShipUpgrades): ShipUpgrades { fun apply(upgrades: ShipUpgrades): ShipUpgrades {
return ShipUpgrades( return ShipUpgrades(
shipLevel = shipLevel.coerceAtLeast(upgrades.shipLevel), shipLevel = shipLevel.coerceAtLeast(upgrades.shipLevel),
@ -43,17 +52,4 @@ data class ShipUpgrades(
stream.writeInt(shipSpeed) stream.writeInt(shipSpeed)
stream.writeCollection(capabilities) { writeBinaryString(it) } stream.writeCollection(capabilities) { writeBinaryString(it) }
} }
companion object {
fun read(stream: DataInputStream, isLegacy: Boolean): ShipUpgrades {
return ShipUpgrades(
stream.readInt(),
stream.readInt(),
stream.readInt(),
if (isLegacy) stream.readFloat().toDouble() else stream.readDouble(),
stream.readInt(),
ImmutableSet.copyOf(stream.readCollection { readBinaryString() })
)
}
}
} }

View File

@ -37,24 +37,6 @@ fun InputStream.readHeader(header: String) {
} }
} }
fun OutputStream.writeVec2i(value: IStruct2i) {
writeSignedVarInt(value.component1())
writeSignedVarInt(value.component2())
}
fun OutputStream.writeVec2d(value: IStruct2d) {
writeDouble(value.component1())
writeDouble(value.component2())
}
fun InputStream.readVec2i(): Vector2i {
return Vector2i(readSignedVarInt(), readSignedVarInt())
}
fun InputStream.readVec2d(): Vector2d {
return Vector2d(readDouble(), readDouble())
}
fun InputStream.readChunkPos(): ChunkPos { fun InputStream.readChunkPos(): ChunkPos {
return ChunkPos(readSignedVarInt(), readSignedVarInt()) return ChunkPos(readSignedVarInt(), readSignedVarInt())
} }

View File

@ -24,7 +24,7 @@ import java.util.LinkedList
*/ */
fun DataInputStream.readJsonElement(): JsonElement { fun DataInputStream.readJsonElement(): JsonElement {
return when (val id = read()) { return when (val id = read()) {
BinaryJsonReader.TYPE_NULL -> JsonNull.INSTANCE BinaryJsonReader.TYPE_INVALID, BinaryJsonReader.TYPE_NULL -> JsonNull.INSTANCE
BinaryJsonReader.TYPE_DOUBLE -> JsonPrimitive(readDouble()) BinaryJsonReader.TYPE_DOUBLE -> JsonPrimitive(readDouble())
BinaryJsonReader.TYPE_BOOLEAN -> InternedJsonElementAdapter.of(readBoolean()) BinaryJsonReader.TYPE_BOOLEAN -> InternedJsonElementAdapter.of(readBoolean())
BinaryJsonReader.TYPE_INT -> JsonPrimitive(readSignedVarLong()) BinaryJsonReader.TYPE_INT -> JsonPrimitive(readSignedVarLong())
@ -388,6 +388,7 @@ class BinaryJsonReader(private val stream: DataInputStream) : JsonReader(unreada
} }
companion object { companion object {
const val TYPE_INVALID = 0x00
const val TYPE_NULL = 0x01 const val TYPE_NULL = 0x01
const val TYPE_DOUBLE = 0x02 const val TYPE_DOUBLE = 0x02
const val TYPE_BOOLEAN = 0x03 const val TYPE_BOOLEAN = 0x03

View File

@ -35,7 +35,7 @@ abstract class Connection(val side: ConnectionSide, val type: ConnectionType, va
private val legacySerializer = PacketRegistry.LEGACY.Serializer(side) private val legacySerializer = PacketRegistry.LEGACY.Serializer(side)
fun setupLegacy() { fun setupLegacy() {
LOGGER.info("Handshake successful from ${channel.remoteAddress()}, channel is using legacy protocol") LOGGER.info("Handshake successful on ${channel.remoteAddress()}, channel is using legacy protocol")
if (type == ConnectionType.MEMORY) { if (type == ConnectionType.MEMORY) {
channel.pipeline().remove(handshakeValidator) channel.pipeline().remove(handshakeValidator)
@ -49,7 +49,7 @@ abstract class Connection(val side: ConnectionSide, val type: ConnectionType, va
} }
fun setupNative() { fun setupNative() {
LOGGER.info("Handshake successful from ${channel.remoteAddress()}, channel is using native protocol") LOGGER.info("Handshake successful on ${channel.remoteAddress()}, channel is using native protocol")
if (type == ConnectionType.MEMORY) { if (type == ConnectionType.MEMORY) {
channel.pipeline().remove(handshakeValidator) channel.pipeline().remove(handshakeValidator)

View File

@ -7,12 +7,15 @@ import io.netty.channel.ChannelDuplexHandler
import io.netty.channel.ChannelHandlerContext import io.netty.channel.ChannelHandlerContext
import io.netty.channel.ChannelPromise import io.netty.channel.ChannelPromise
import it.unimi.dsi.fastutil.bytes.ByteArrayList import it.unimi.dsi.fastutil.bytes.ByteArrayList
import it.unimi.dsi.fastutil.ints.Int2ObjectArrayMap
import it.unimi.dsi.fastutil.io.FastByteArrayInputStream import it.unimi.dsi.fastutil.io.FastByteArrayInputStream
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kommons.io.readSignedVarInt import ru.dbotthepony.kommons.io.readSignedVarInt
import ru.dbotthepony.kommons.io.readVarInt
import ru.dbotthepony.kommons.io.writeSignedVarInt import ru.dbotthepony.kommons.io.writeSignedVarInt
import ru.dbotthepony.kommons.io.writeVarInt
import ru.dbotthepony.kstarbound.client.network.packets.ForgetChunkPacket import ru.dbotthepony.kstarbound.client.network.packets.ForgetChunkPacket
import ru.dbotthepony.kstarbound.client.network.packets.ChunkCellsPacket import ru.dbotthepony.kstarbound.client.network.packets.ChunkCellsPacket
import ru.dbotthepony.kstarbound.client.network.packets.ForgetEntityPacket import ru.dbotthepony.kstarbound.client.network.packets.ForgetEntityPacket
@ -25,6 +28,7 @@ import ru.dbotthepony.kstarbound.network.packets.serverbound.HandshakeResponsePa
import ru.dbotthepony.kstarbound.network.packets.ProtocolRequestPacket import ru.dbotthepony.kstarbound.network.packets.ProtocolRequestPacket
import ru.dbotthepony.kstarbound.network.packets.ProtocolResponsePacket import ru.dbotthepony.kstarbound.network.packets.ProtocolResponsePacket
import ru.dbotthepony.kstarbound.network.packets.clientbound.ServerDisconnectPacket import ru.dbotthepony.kstarbound.network.packets.clientbound.ServerDisconnectPacket
import ru.dbotthepony.kstarbound.network.packets.clientbound.WorldStartPacket
import ru.dbotthepony.kstarbound.server.network.packets.TrackedPositionPacket import ru.dbotthepony.kstarbound.server.network.packets.TrackedPositionPacket
import ru.dbotthepony.kstarbound.server.network.packets.TrackedSizePacket import ru.dbotthepony.kstarbound.server.network.packets.TrackedSizePacket
import java.io.BufferedInputStream import java.io.BufferedInputStream
@ -37,6 +41,7 @@ import kotlin.reflect.KClass
class PacketRegistry(val isLegacy: Boolean) { class PacketRegistry(val isLegacy: Boolean) {
private val packets = ArrayList<Type<*>?>() private val packets = ArrayList<Type<*>?>()
private val missingNames = Int2ObjectArrayMap<String>()
private val clazz2Type = Reference2ObjectOpenHashMap<KClass<*>, Type<*>>() private val clazz2Type = Reference2ObjectOpenHashMap<KClass<*>, Type<*>>()
private data class Type<T : IPacket>(val id: Int, val type: KClass<T>, val factory: IPacketReader<T>, val direction: PacketDirection) private data class Type<T : IPacket>(val id: Int, val type: KClass<T>, val factory: IPacketReader<T>, val direction: PacketDirection)
@ -67,6 +72,11 @@ class PacketRegistry(val isLegacy: Boolean) {
} }
} }
private fun skip(name: String) {
missingNames[packets.size] = name
packets.add(null)
}
inner class Serializer(val side: ConnectionSide) : ChannelDuplexHandler() { inner class Serializer(val side: ConnectionSide) : ChannelDuplexHandler() {
private val backlog = ByteArrayList() private val backlog = ByteArrayList()
private var discardBytes = 0 private var discardBytes = 0
@ -121,12 +131,19 @@ class PacketRegistry(val isLegacy: Boolean) {
val type = packets.getOrNull(packetType) val type = packets.getOrNull(packetType)
if (type == null) { if (type == null) {
LOGGER.error("Unknown packet type $packetType! Discarding ${dataLength.absoluteValue} bytes") val name = missingNames[packetType]
if (name != null)
LOGGER.error("Unknown packet type $packetType ($name)! Discarding ${dataLength.absoluteValue} bytes")
else
LOGGER.error("Unknown packet type $packetType! Discarding ${dataLength.absoluteValue} bytes")
discardBytes = dataLength.absoluteValue discardBytes = dataLength.absoluteValue
} else if (!type.direction.acceptedOn(side)) { } else if (!type.direction.acceptedOn(side)) {
LOGGER.error("Packet type $packetType (${type.type}) can not be accepted on side $side! Discarding ${dataLength.absoluteValue} bytes") LOGGER.error("Packet type $packetType (${type.type}) can not be accepted on side $side! Discarding ${dataLength.absoluteValue} bytes")
discardBytes = dataLength.absoluteValue discardBytes = dataLength.absoluteValue
} else { } else {
LOGGER.debug("Packet type {} ({}) received on {} (size {} bytes)", packetType, type.type, side, dataLength.absoluteValue)
readingType = type readingType = type
readableBytes = dataLength.absoluteValue readableBytes = dataLength.absoluteValue
isCompressed = dataLength < 0 isCompressed = dataLength < 0
@ -159,6 +176,7 @@ class PacketRegistry(val isLegacy: Boolean) {
stream2.writeByte(type.id) stream2.writeByte(type.id)
stream2.writeSignedVarInt(stream.length) stream2.writeSignedVarInt(stream.length)
stream2.write(stream.array, 0, stream.length) stream2.write(stream.array, 0, stream.length)
LOGGER.debug("Packet type {} ({}) sent from {} (size {} bytes)", type.id, type.type, side, stream.length)
ctx.write(buff, promise) ctx.write(buff, promise)
} }
} }
@ -213,92 +231,100 @@ class PacketRegistry(val isLegacy: Boolean) {
HANDSHAKE.add(::ProtocolRequestPacket) HANDSHAKE.add(::ProtocolRequestPacket)
HANDSHAKE.add(::ProtocolResponsePacket) HANDSHAKE.add(::ProtocolResponsePacket)
LEGACY.skip() // ProtocolRequest // legacy protocol handshake looks like this
LEGACY.skip() // ProtocolResponse // --> ProtocolRequest
// <-- ProtocolResponse
// --> ClientConnect
// <-- HandshakeChallenge *
// --> HandshakeResponse *
// <-- ConnectSuccess / ConnectFailure
LEGACY.skip("ProtocolRequest")
LEGACY.skip("ProtocolResponse")
// Packets sent universe server -> universe client // Packets sent universe server -> universe client
LEGACY.add(::ServerDisconnectPacket) // ServerDisconnect LEGACY.add(::ServerDisconnectPacket) // ServerDisconnect
LEGACY.add(::ConnectSuccessPacket) // ConnectSuccess LEGACY.add(::ConnectSuccessPacket) // ConnectSuccess
LEGACY.skip() // ConnectFailure LEGACY.skip("ConnectFailure")
LEGACY.add(::HandshakeChallengePacket) // HandshakeChallenge LEGACY.add(::HandshakeChallengePacket) // HandshakeChallenge
LEGACY.skip() // ChatReceive LEGACY.skip("ChatReceive")
LEGACY.skip() // UniverseTimeUpdate LEGACY.skip("UniverseTimeUpdate")
LEGACY.skip() // CelestialResponse LEGACY.skip("CelestialResponse")
LEGACY.skip() // PlayerWarpResult LEGACY.skip("PlayerWarpResult")
LEGACY.skip() // PlanetTypeUpdate LEGACY.skip("PlanetTypeUpdate")
LEGACY.skip() // Pause LEGACY.skip("Pause")
LEGACY.skip() // ServerInfo LEGACY.skip("ServerInfo")
// Packets sent universe client -> universe server // Packets sent universe client -> universe server
LEGACY.add(::ClientConnectPacket) // ClientConnect LEGACY.add(::ClientConnectPacket) // ClientConnect
LEGACY.skip() // ClientDisconnectRequest LEGACY.skip("ClientDisconnectRequest")
LEGACY.add(::HandshakeResponsePacket) // HandshakeResponse LEGACY.add(::HandshakeResponsePacket) // HandshakeResponse
LEGACY.skip() // PlayerWarp LEGACY.skip("PlayerWarp")
LEGACY.skip() // FlyShip LEGACY.skip("FlyShip")
LEGACY.skip() // ChatSend LEGACY.skip("ChatSend")
LEGACY.skip() // CelestialRequest LEGACY.skip("CelestialRequest")
// Packets sent bidirectionally between the universe client and the universe // Packets sent bidirectionally between the universe client and the universe
// server // server
LEGACY.skip() // ClientContextUpdate LEGACY.skip("ClientContextUpdate")
// Packets sent world server -> world client // Packets sent world server -> world client
LEGACY.skip() // WorldStart LEGACY.add(::WorldStartPacket) // WorldStart
LEGACY.skip() // WorldStop LEGACY.skip("WorldStop")
LEGACY.skip() // WorldLayoutUpdate LEGACY.skip("WorldLayoutUpdate")
LEGACY.skip() // WorldParametersUpdate LEGACY.skip("WorldParametersUpdate")
LEGACY.skip() // CentralStructureUpdate LEGACY.skip("CentralStructureUpdate")
LEGACY.skip() // TileArrayUpdate LEGACY.skip("TileArrayUpdate")
LEGACY.skip() // TileUpdate LEGACY.skip("TileUpdate")
LEGACY.skip() // TileLiquidUpdate LEGACY.skip("TileLiquidUpdate")
LEGACY.skip() // TileDamageUpdate LEGACY.skip("TileDamageUpdate")
LEGACY.skip() // TileModificationFailure LEGACY.skip("TileModificationFailure")
LEGACY.skip() // GiveItem LEGACY.skip("GiveItem")
LEGACY.skip() // EnvironmentUpdate LEGACY.skip("EnvironmentUpdate")
LEGACY.skip() // UpdateTileProtection LEGACY.skip("UpdateTileProtection")
LEGACY.skip() // SetDungeonGravity LEGACY.skip("SetDungeonGravity")
LEGACY.skip() // SetDungeonBreathable LEGACY.skip("SetDungeonBreathable")
LEGACY.skip() // SetPlayerStart LEGACY.skip("SetPlayerStart")
LEGACY.skip() // FindUniqueEntityResponse LEGACY.skip("FindUniqueEntityResponse")
LEGACY.skip() // Pong LEGACY.skip("Pong")
// Packets sent world client -> world server // Packets sent world client -> world server
LEGACY.skip() // ModifyTileList LEGACY.skip("ModifyTileList")
LEGACY.skip() // DamageTileGroup LEGACY.skip("DamageTileGroup")
LEGACY.skip() // CollectLiquid LEGACY.skip("CollectLiquid")
LEGACY.skip() // RequestDrop LEGACY.skip("RequestDrop")
LEGACY.skip() // SpawnEntity LEGACY.skip("SpawnEntity")
LEGACY.skip() // ConnectWire LEGACY.skip("ConnectWire")
LEGACY.skip() // DisconnectAllWires LEGACY.skip("DisconnectAllWires")
LEGACY.skip() // WorldClientStateUpdate LEGACY.skip("WorldClientStateUpdate")
LEGACY.skip() // FindUniqueEntity LEGACY.skip("FindUniqueEntity")
LEGACY.skip() // WorldStartAcknowledge LEGACY.skip("WorldStartAcknowledge")
LEGACY.skip() // Ping LEGACY.skip("Ping")
// Packets sent bidirectionally between world client and world server // Packets sent bidirectionally between world client and world server
LEGACY.skip() // EntityCreate LEGACY.skip("EntityCreate")
LEGACY.skip() // EntityUpdateSet LEGACY.skip("EntityUpdateSet")
LEGACY.skip() // EntityDestroy LEGACY.skip("EntityDestroy")
LEGACY.skip() // EntityInteract LEGACY.skip("EntityInteract")
LEGACY.skip() // EntityInteractResult LEGACY.skip("EntityInteractResult")
LEGACY.skip() // HitRequest LEGACY.skip("HitRequest")
LEGACY.skip() // DamageRequest LEGACY.skip("DamageRequest")
LEGACY.skip() // DamageNotification LEGACY.skip("DamageNotification")
LEGACY.skip() // EntityMessage LEGACY.skip("EntityMessage")
LEGACY.skip() // EntityMessageResponse LEGACY.skip("EntityMessageResponse")
LEGACY.skip() // UpdateWorldProperties LEGACY.skip("UpdateWorldProperties")
LEGACY.skip() // StepUpdate LEGACY.skip("StepUpdate")
// Packets sent system server -> system client // Packets sent system server -> system client
LEGACY.skip() // SystemWorldStart LEGACY.skip("SystemWorldStart")
LEGACY.skip() // SystemWorldUpdate LEGACY.skip("SystemWorldUpdate")
LEGACY.skip() // SystemObjectCreate LEGACY.skip("SystemObjectCreate")
LEGACY.skip() // SystemObjectDestroy LEGACY.skip("SystemObjectDestroy")
LEGACY.skip() // SystemShipCreate LEGACY.skip("SystemShipCreate")
LEGACY.skip() // SystemShipDestroy LEGACY.skip("SystemShipDestroy")
// Packets sent system client -> system server // Packets sent system client -> system server
LEGACY.skip() // SystemObjectSpawn LEGACY.skip("SystemObjectSpawn")
} }
} }
} }

View File

@ -29,9 +29,9 @@ data class ProtocolResponsePacket(val allowed: Boolean) : IClientPacket {
playerSpecies = "hylotl", playerSpecies = "hylotl",
shipChunks = HashMap(), shipChunks = HashMap(),
shipUpgrades = ShipUpgrades(), shipUpgrades = ShipUpgrades(),
introComplete = false, introComplete = true,
account = "" account = ""
) )
) )
} else { } else {
connection.setupNative() connection.setupNative()

View File

@ -1,7 +1,9 @@
package ru.dbotthepony.kstarbound.network.packets.clientbound package ru.dbotthepony.kstarbound.network.packets.clientbound
import ru.dbotthepony.kommons.io.readUUID import ru.dbotthepony.kommons.io.readUUID
import ru.dbotthepony.kommons.io.readVarInt
import ru.dbotthepony.kommons.io.writeUUID import ru.dbotthepony.kommons.io.writeUUID
import ru.dbotthepony.kommons.io.writeVarInt
import ru.dbotthepony.kstarbound.client.ClientConnection import ru.dbotthepony.kstarbound.client.ClientConnection
import ru.dbotthepony.kstarbound.defs.CelestialBaseInformation import ru.dbotthepony.kstarbound.defs.CelestialBaseInformation
import ru.dbotthepony.kstarbound.network.IClientPacket import ru.dbotthepony.kstarbound.network.IClientPacket
@ -11,18 +13,18 @@ import java.util.UUID
class ConnectSuccessPacket(val connectionID: Int, val serverUUID: UUID, val celestialInformation: CelestialBaseInformation) : IClientPacket { class ConnectSuccessPacket(val connectionID: Int, val serverUUID: UUID, val celestialInformation: CelestialBaseInformation) : IClientPacket {
constructor(stream: DataInputStream, isLegacy: Boolean) : this( constructor(stream: DataInputStream, isLegacy: Boolean) : this(
stream.readUnsignedShort(), stream.readVarInt(),
stream.readUUID(), stream.readUUID(),
CelestialBaseInformation(stream, isLegacy) CelestialBaseInformation(stream, isLegacy)
) )
override fun write(stream: DataOutputStream, isLegacy: Boolean) { override fun write(stream: DataOutputStream, isLegacy: Boolean) {
stream.writeShort(connectionID) stream.writeVarInt(connectionID)
stream.writeUUID(serverUUID) stream.writeUUID(serverUUID)
celestialInformation.write(stream, isLegacy) celestialInformation.write(stream, isLegacy)
} }
override fun play(connection: ClientConnection) { override fun play(connection: ClientConnection) {
TODO("Not yet implemented") connection.connectionID = connectionID
} }
} }

View File

@ -0,0 +1,77 @@
package ru.dbotthepony.kstarbound.network.packets.clientbound
import com.google.gson.JsonElement
import it.unimi.dsi.fastutil.ints.Int2BooleanAVLTreeMap
import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
import it.unimi.dsi.fastutil.ints.IntAVLTreeSet
import ru.dbotthepony.kommons.io.readByteArray
import ru.dbotthepony.kommons.io.readCollection
import ru.dbotthepony.kommons.io.readMap
import ru.dbotthepony.kommons.io.readVector2d
import ru.dbotthepony.kommons.io.readVector2f
import ru.dbotthepony.kommons.io.writeByteArray
import ru.dbotthepony.kommons.io.writeCollection
import ru.dbotthepony.kommons.io.writeMap
import ru.dbotthepony.kommons.io.writeStruct2d
import ru.dbotthepony.kommons.io.writeStruct2f
import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kstarbound.client.ClientConnection
import ru.dbotthepony.kstarbound.json.readJsonElement
import ru.dbotthepony.kstarbound.json.writeJsonElement
import ru.dbotthepony.kstarbound.network.IClientPacket
import java.io.DataInputStream
import java.io.DataOutputStream
class WorldStartPacket(
val templateData: JsonElement, val skyData: ByteArray, val weatherData: ByteArray,
val playerStart: Vector2d, val playerRespawn: Vector2d, val respawnInWorld: Boolean,
val dungeonGravity: Map<Int, Vector2d>, val dungeonBreathable: Map<Int, Boolean>,
val protectedDungeonIDs: Set<Int>, val worldProperties: JsonElement, val connectionID: Int,
val localInterpolationMode: Boolean,
) : IClientPacket {
constructor(stream: DataInputStream, isLegacy: Boolean) : this(
stream.readJsonElement(),
stream.readByteArray(),
stream.readByteArray(),
if (isLegacy) stream.readVector2f().toDoubleVector() else stream.readVector2d(),
if (isLegacy) stream.readVector2f().toDoubleVector() else stream.readVector2d(),
stream.readBoolean(),
if (isLegacy) stream.readMap({ readUnsignedShort() }, { Vector2d(0.0, readFloat().toDouble()) }, ::Int2ObjectOpenHashMap) else stream.readMap({ readInt() }, { readVector2d() }, { Int2ObjectAVLTreeMap() }),
if (isLegacy) stream.readMap({ readUnsignedShort() }, { readBoolean() }, ::Int2ObjectOpenHashMap) else stream.readMap({ readInt() }, { readBoolean() }, { Int2BooleanAVLTreeMap() }),
if (isLegacy) stream.readCollection({ readUnsignedShort() }, { IntAVLTreeSet() }) else stream.readCollection({ readInt() }, { IntAVLTreeSet() }),
stream.readJsonElement(),
stream.readUnsignedShort(),
stream.readBoolean()
)
override fun write(stream: DataOutputStream, isLegacy: Boolean) {
stream.writeJsonElement(templateData)
stream.writeByteArray(skyData)
stream.writeByteArray(weatherData)
if (isLegacy) {
stream.writeStruct2f(playerStart.toFloatVector())
stream.writeStruct2f(playerRespawn.toFloatVector())
stream.writeBoolean(respawnInWorld)
stream.writeMap(dungeonGravity, { writeShort(it) }, { writeFloat(it.y.toFloat()) })
stream.writeMap(dungeonBreathable, { writeShort(it) }, { writeBoolean(it) })
stream.writeCollection(protectedDungeonIDs) { writeShort(it) }
} else {
stream.writeStruct2d(playerStart)
stream.writeStruct2d(playerRespawn)
stream.writeBoolean(respawnInWorld)
stream.writeMap(dungeonGravity, { writeInt(it) }, { writeStruct2d(it) })
stream.writeMap(dungeonBreathable, { writeInt(it) }, { writeBoolean(it) })
stream.writeCollection(protectedDungeonIDs) { writeInt(it) }
}
stream.writeJsonElement(worldProperties)
stream.writeShort(connectionID)
stream.writeBoolean(localInterpolationMode)
}
override fun play(connection: ClientConnection) {
TODO("Not yet implemented")
}
}

View File

@ -39,7 +39,7 @@ data class ClientConnectPacket(
stream.readBinaryString(), stream.readBinaryString(),
stream.readBinaryString(), stream.readBinaryString(),
stream.readMap(InputStream::readByteKey, { readKOptional { readByteArray() } }, { HashMap(it) }), stream.readMap(InputStream::readByteKey, { readKOptional { readByteArray() } }, { HashMap(it) }),
ShipUpgrades.read(stream, isLegacy), ShipUpgrades(stream, isLegacy),
stream.readBoolean(), stream.readBoolean(),
stream.readBinaryString() stream.readBinaryString()
) )

View File

@ -1,18 +1,18 @@
package ru.dbotthepony.kstarbound.server.network.packets package ru.dbotthepony.kstarbound.server.network.packets
import ru.dbotthepony.kommons.io.readVector2d
import ru.dbotthepony.kommons.io.writeStruct2d
import ru.dbotthepony.kommons.vector.Vector2d import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kstarbound.network.IServerPacket import ru.dbotthepony.kstarbound.network.IServerPacket
import ru.dbotthepony.kstarbound.server.ServerConnection import ru.dbotthepony.kstarbound.server.ServerConnection
import ru.dbotthepony.kstarbound.io.readVec2d
import ru.dbotthepony.kstarbound.io.writeVec2d
import java.io.DataInputStream import java.io.DataInputStream
import java.io.DataOutputStream import java.io.DataOutputStream
data class TrackedPositionPacket(val pos: Vector2d) : IServerPacket { data class TrackedPositionPacket(val pos: Vector2d) : IServerPacket {
constructor(stream: DataInputStream, isLegacy: Boolean) : this(stream.readVec2d()) constructor(stream: DataInputStream, isLegacy: Boolean) : this(stream.readVector2d())
override fun write(stream: DataOutputStream, isLegacy: Boolean) { override fun write(stream: DataOutputStream, isLegacy: Boolean) {
stream.writeVec2d(pos) stream.writeStruct2d(pos)
} }
override fun play(connection: ServerConnection) { override fun play(connection: ServerConnection) {

View File

@ -1,23 +1,23 @@
package ru.dbotthepony.kstarbound.world package ru.dbotthepony.kstarbound.world
import ru.dbotthepony.kommons.io.readVector2i
import ru.dbotthepony.kommons.io.writeStruct2i
import ru.dbotthepony.kommons.util.IStruct2d import ru.dbotthepony.kommons.util.IStruct2d
import ru.dbotthepony.kommons.util.IStruct2f import ru.dbotthepony.kommons.util.IStruct2f
import ru.dbotthepony.kommons.util.IStruct2i import ru.dbotthepony.kommons.util.IStruct2i
import ru.dbotthepony.kommons.vector.Vector2d import ru.dbotthepony.kommons.vector.Vector2d
import ru.dbotthepony.kommons.vector.Vector2i import ru.dbotthepony.kommons.vector.Vector2i
import ru.dbotthepony.kstarbound.io.readVec2i
import ru.dbotthepony.kstarbound.io.writeVec2i
import java.io.DataInputStream import java.io.DataInputStream
import java.io.DataOutputStream import java.io.DataOutputStream
data class WorldGeometry(val size: Vector2i, val loopX: Boolean, val loopY: Boolean) { data class WorldGeometry(val size: Vector2i, val loopX: Boolean, val loopY: Boolean) {
constructor(buff: DataInputStream) : this(buff.readVec2i(), buff.readBoolean(), buff.readBoolean()) constructor(buff: DataInputStream) : this(buff.readVector2i(), buff.readBoolean(), buff.readBoolean())
val x: CoordinateMapper = if (loopX) CoordinateMapper.Wrapper(size.x) else CoordinateMapper.Clamper(size.x) val x: CoordinateMapper = if (loopX) CoordinateMapper.Wrapper(size.x) else CoordinateMapper.Clamper(size.x)
val y: CoordinateMapper = if (loopY) CoordinateMapper.Wrapper(size.y) else CoordinateMapper.Clamper(size.y) val y: CoordinateMapper = if (loopY) CoordinateMapper.Wrapper(size.y) else CoordinateMapper.Clamper(size.y)
fun write(buff: DataOutputStream) { fun write(buff: DataOutputStream) {
buff.writeVec2i(size) buff.writeStruct2i(size)
buff.writeBoolean(loopX) buff.writeBoolean(loopX)
buff.writeBoolean(loopY) buff.writeBoolean(loopY)
} }