217 lines
6.2 KiB
Kotlin
217 lines
6.2 KiB
Kotlin
package ru.dbotthepony.kstarbound.defs
|
|
|
|
import ru.dbotthepony.kommons.io.StreamCodec
|
|
import ru.dbotthepony.kommons.io.readUUID
|
|
import ru.dbotthepony.kommons.io.readVector2d
|
|
import ru.dbotthepony.kommons.io.readVector2f
|
|
import ru.dbotthepony.kommons.io.writeBinaryString
|
|
import ru.dbotthepony.kommons.io.writeStruct2d
|
|
import ru.dbotthepony.kommons.io.writeStruct2f
|
|
import ru.dbotthepony.kommons.io.writeUUID
|
|
import ru.dbotthepony.kommons.vector.Vector2d
|
|
import ru.dbotthepony.kstarbound.io.readInternedString
|
|
import ru.dbotthepony.kstarbound.json.builder.IStringSerializable
|
|
import ru.dbotthepony.kstarbound.network.syncher.legacyCodec
|
|
import ru.dbotthepony.kstarbound.network.syncher.nativeCodec
|
|
import ru.dbotthepony.kstarbound.server.ServerConnection
|
|
import ru.dbotthepony.kstarbound.server.world.ServerWorld
|
|
import java.io.DataInputStream
|
|
import java.io.DataOutputStream
|
|
import java.util.UUID
|
|
|
|
// original game has MVariant here
|
|
// MVariant prepends InvalidValue to Variant<> template
|
|
// Variant<> itself works with LookupTypeIndex<MatchType, 0, FirstType, RestTypes...>
|
|
// 0 is responsible for holding current template comparison check
|
|
// typedef MVariant<WarpToWorld, WarpToPlayer, WarpAlias> WarpAction;
|
|
// -> Variant<InvalidType, WarpToWorld, WarpToPlayer, WarpAlias> WarpAction
|
|
// hence WarpToWorld has index 1, WarpToPlayer 2, WarpAlias 3
|
|
|
|
sealed class SpawnTarget {
|
|
abstract fun write(stream: DataOutputStream, isLegacy: Boolean)
|
|
abstract fun resolve(world: ServerWorld): Vector2d?
|
|
|
|
object Whatever : SpawnTarget() {
|
|
override fun write(stream: DataOutputStream, isLegacy: Boolean) {
|
|
stream.writeByte(0)
|
|
}
|
|
|
|
override fun resolve(world: ServerWorld): Vector2d {
|
|
return world.playerSpawnPosition
|
|
}
|
|
|
|
override fun toString(): String {
|
|
return "SpawnTarget.SpawnTarget"
|
|
}
|
|
}
|
|
|
|
data class Entity(val id: String) : SpawnTarget() {
|
|
override fun write(stream: DataOutputStream, isLegacy: Boolean) {
|
|
stream.writeByte(1)
|
|
stream.writeBinaryString(id)
|
|
}
|
|
|
|
override fun resolve(world: ServerWorld): Vector2d? {
|
|
return world.entities.values.firstOrNull { it.uniqueID == id }?.position
|
|
}
|
|
|
|
override fun toString(): String {
|
|
return "SpawnTarget.Entity[$id]"
|
|
}
|
|
}
|
|
|
|
data class Position(val position: Vector2d) : SpawnTarget() {
|
|
override fun write(stream: DataOutputStream, isLegacy: Boolean) {
|
|
stream.writeByte(2)
|
|
|
|
if (isLegacy) {
|
|
stream.writeStruct2f(position.toFloatVector())
|
|
} else {
|
|
stream.writeStruct2d(position)
|
|
}
|
|
}
|
|
|
|
override fun toString(): String {
|
|
return "SpawnTarget.Position[$position]"
|
|
}
|
|
|
|
override fun resolve(world: ServerWorld): Vector2d {
|
|
return position
|
|
}
|
|
}
|
|
|
|
data class X(val position: Double) : SpawnTarget() {
|
|
override fun write(stream: DataOutputStream, isLegacy: Boolean) {
|
|
stream.writeByte(3)
|
|
|
|
if (isLegacy) {
|
|
stream.writeFloat(position.toFloat())
|
|
} else {
|
|
stream.writeDouble(position)
|
|
}
|
|
}
|
|
|
|
override fun toString(): String {
|
|
return "SpawnTarget.X[$position]"
|
|
}
|
|
|
|
override fun resolve(world: ServerWorld): Vector2d {
|
|
TODO("Not yet implemented")
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
fun read(stream: DataInputStream, isLegacy: Boolean): SpawnTarget {
|
|
return when (val type = stream.readUnsignedByte()) {
|
|
0 -> Whatever
|
|
1 -> Entity(stream.readInternedString())
|
|
2 -> Position(if (isLegacy) stream.readVector2f().toDoubleVector() else stream.readVector2d())
|
|
3 -> X(if (isLegacy) stream.readFloat().toDouble() else stream.readDouble())
|
|
else -> throw IllegalArgumentException("Unknown SpawnTarget type $type!")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sealed class WarpAction {
|
|
abstract fun write(stream: DataOutputStream, isLegacy: Boolean)
|
|
abstract fun resolve(connection: ServerConnection): WorldID
|
|
|
|
data class World(val worldID: WorldID, val target: SpawnTarget) : WarpAction() {
|
|
override fun write(stream: DataOutputStream, isLegacy: Boolean) {
|
|
stream.writeByte(1)
|
|
worldID.write(stream, isLegacy)
|
|
target.write(stream, isLegacy)
|
|
}
|
|
|
|
override fun resolve(connection: ServerConnection): WorldID {
|
|
TODO("Not yet implemented")
|
|
}
|
|
}
|
|
|
|
data class Player(val uuid: UUID) : WarpAction() {
|
|
override fun write(stream: DataOutputStream, isLegacy: Boolean) {
|
|
stream.writeByte(2)
|
|
stream.writeUUID(uuid)
|
|
}
|
|
|
|
override fun resolve(connection: ServerConnection): WorldID {
|
|
if (connection.uuid == uuid)
|
|
return connection.world?.worldID ?: WorldID.Limbo
|
|
|
|
return connection.server.clientByUUID(uuid)?.world?.worldID ?: WorldID.Limbo
|
|
}
|
|
}
|
|
|
|
companion object {
|
|
fun read(stream: DataInputStream, isLegacy: Boolean): WarpAction {
|
|
return when (val type = stream.readUnsignedByte()) {
|
|
1 -> World(WorldID.read(stream, isLegacy), SpawnTarget.read(stream, isLegacy))
|
|
2 -> Player(stream.readUUID())
|
|
3 -> {
|
|
when (val type2 = stream.readInt()) {
|
|
0 -> WarpAlias.Return
|
|
1 -> WarpAlias.OrbitedWorld
|
|
2 -> WarpAlias.OwnShip
|
|
else -> throw IllegalArgumentException("Unknown WarpAlias type $type2!")
|
|
}
|
|
}
|
|
|
|
else -> throw IllegalArgumentException("Unknown WarpAction type $type!")
|
|
}
|
|
}
|
|
|
|
val CODEC = nativeCodec(::read, WarpAction::write)
|
|
val LEGACY_CODEC = legacyCodec(::read, WarpAction::write)
|
|
}
|
|
}
|
|
|
|
sealed class WarpAlias(val index: Int) : WarpAction() {
|
|
override fun write(stream: DataOutputStream, isLegacy: Boolean) {
|
|
stream.write(3)
|
|
// because it is defined as enum class WarpAlias, without specifying uint8_t as type
|
|
stream.writeInt(index)
|
|
}
|
|
|
|
object Return : WarpAlias(0) {
|
|
override fun resolve(connection: ServerConnection): WorldID {
|
|
TODO("Not yet implemented")
|
|
}
|
|
|
|
override fun toString(): String {
|
|
return "WarpAlias.Return"
|
|
}
|
|
}
|
|
|
|
object OrbitedWorld : WarpAlias(1) {
|
|
override fun resolve(connection: ServerConnection): WorldID {
|
|
TODO("Not yet implemented")
|
|
}
|
|
|
|
override fun toString(): String {
|
|
return "WarpAlias.OrbitedWorld"
|
|
}
|
|
}
|
|
|
|
object OwnShip : WarpAlias(2) {
|
|
override fun resolve(connection: ServerConnection): WorldID {
|
|
return connection.shipWorld.worldID
|
|
}
|
|
|
|
override fun toString(): String {
|
|
return "WarpAlias.OwnShip"
|
|
}
|
|
}
|
|
}
|
|
|
|
enum class WarpMode(override val jsonName: String) : IStringSerializable {
|
|
NONE("None"),
|
|
BEAM_ONLY("BeamOnly"),
|
|
DEPLOY_ONLY("DeployOnly"),
|
|
BEAM_OR_DEPLOY("BeamOrDeploy");
|
|
|
|
companion object {
|
|
val CODEC = StreamCodec.Enum(WarpMode::class.java)
|
|
}
|
|
}
|