Merge Player and Connection

This commit is contained in:
DBotThePony 2024-02-02 17:00:02 +07:00
parent bd8d0e58df
commit 0b961b72ae
Signed by: DBot
GPG Key ID: DCC23B5715498507
13 changed files with 140 additions and 180 deletions

View File

@ -68,8 +68,6 @@ fun main() {
Starbound.initializeGame()
var ply: PlayerEntity? = null
Starbound.mailboxInitialized.submit {
//ply = PlayerEntity(client.world!!)
@ -139,7 +137,7 @@ fun main() {
//item.movement.applyVelocity(Vector2d(rand.nextDouble() * 1000.0 - 500.0, rand.nextDouble() * 1000.0 - 500.0))
}
client.connectToLocalServer(client, server.channels.createLocalChannel(), UUID(0L, 0L))
client.connectToLocalServer(client, server.channels.createLocalChannel(), UUID.randomUUID())
}
//ent.position += Vector2d(y = 14.0, x = -10.0)
@ -163,12 +161,14 @@ fun main() {
}
while (client.renderFrame()) {
if (ply != null) {
client.camera.pos = ply!!.position
val ply = client.activeConnection?.character
ply!!.movement.controlMove = if (client.input.KEY_A_DOWN) Direction.LEFT else if (client.input.KEY_D_DOWN) Direction.RIGHT else null
ply!!.movement.controlJump = client.input.KEY_SPACE_DOWN
ply!!.movement.controlRun = !client.input.KEY_LEFT_SHIFT_DOWN
if (ply != null) {
client.camera.pos = ply.position
ply.movement.controlMove = if (client.input.KEY_A_DOWN) Direction.LEFT else if (client.input.KEY_D_DOWN) Direction.RIGHT else null
ply.movement.controlJump = client.input.KEY_SPACE_DOWN
ply.movement.controlRun = !client.input.KEY_LEFT_SHIFT_DOWN
} else {
client.camera.pos += Vector2d(
(if (client.input.KEY_A_DOWN) -Starbound.TICK_TIME_ADVANCE * 32f / client.settings.zoom else 0.0) + (if (client.input.KEY_D_DOWN) Starbound.TICK_TIME_ADVANCE * 32f / client.settings.zoom else 0.0),

View File

@ -1001,7 +1001,6 @@ class StarboundClient : Closeable {
if (activeConnection != null) {
activeConnection.send(TrackedPositionPacket(camera.pos))
activeConnection.send(TrackedSizePacket(2, 2))
}
uberShaderPrograms.forEachValid { it.viewMatrix = viewportMatrixScreen }

View File

@ -25,15 +25,10 @@ class ClientConnection(val client: StarboundClient, type: ConnectionType, uuid:
helloListener = HelloListener(this, channel!!).sendHello(localUUID)
}
override var player: LocalPlayer by Delegates.notNull()
private set
override fun onHelloReceived(helloPacket: HelloPacket) {
player = LocalPlayer(this)
}
override fun inGame() {
}
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {

View File

@ -1,6 +0,0 @@
package ru.dbotthepony.kstarbound.client.network
import ru.dbotthepony.kstarbound.network.Player
class LocalPlayer(connection: ClientConnection) : Player<ClientConnection>(connection, connection.localUUID) {
}

View File

@ -9,17 +9,20 @@ 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
abstract val player: Player<*>
override val protocolVersion: Int
get() = otherSide?.protocolVersion ?: 0
override val engineVersion: String

View File

@ -29,7 +29,7 @@ object PacketRegistry {
val size: Int
get() = packets.size
fun <T : IPacket> add(type: KClass<T>, reader: IPacketReader<T>, direction: PacketDirection = PacketDirection.get(type)): PacketRegistry {
private fun <T : IPacket> add(type: KClass<T>, reader: IPacketReader<T>, direction: PacketDirection = PacketDirection.get(type)): PacketRegistry {
if (packets.size >= 255)
throw IndexOutOfBoundsException("Unable to add any more packet types! 255 is the max")
@ -42,7 +42,7 @@ object PacketRegistry {
return this
}
inline fun <reified T : IPacket> add(reader: IPacketReader<T>, direction: PacketDirection = PacketDirection.get(T::class)): PacketRegistry {
private inline fun <reified T : IPacket> add(reader: IPacketReader<T>, direction: PacketDirection = PacketDirection.get(T::class)): PacketRegistry {
return add(T::class, reader, direction)
}

View File

@ -1,10 +0,0 @@
package ru.dbotthepony.kstarbound.network
import ru.dbotthepony.kstarbound.player.Avatar
import ru.dbotthepony.kstarbound.world.entities.PlayerEntity
import java.util.UUID
abstract class Player<T : Connection>(val connection: T, val uuid: UUID) {
var avatar: Avatar? = null
var character: PlayerEntity? = null
}

View File

@ -1,9 +1,8 @@
package ru.dbotthepony.kstarbound.server
import ru.dbotthepony.kstarbound.client.network.packets.InitialChunkDataPacket
import ru.dbotthepony.kstarbound.client.network.packets.JoinWorldPacket
import ru.dbotthepony.kstarbound.server.network.ServerChannels
import ru.dbotthepony.kstarbound.server.network.ServerPlayer
import ru.dbotthepony.kstarbound.server.network.ServerConnection
import ru.dbotthepony.kstarbound.server.world.ServerWorld
import ru.dbotthepony.kstarbound.util.MailboxExecutorService
import java.io.Closeable
@ -41,11 +40,11 @@ abstract class StarboundServer(val root: File) : Closeable {
thread.start()
}
fun playerInGame(player: ServerPlayer) {
fun playerInGame(player: ServerConnection) {
val world = worlds.first()
player.world = world
world.players.add(player)
player.connection.send(JoinWorldPacket(world))
player.send(JoinWorldPacket(world))
}
protected abstract fun close0()

View File

@ -1,18 +1,132 @@
package ru.dbotthepony.kstarbound.server.network
import io.netty.channel.ChannelHandlerContext
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.kstarbound.client.network.packets.ForgetChunkPacket
import ru.dbotthepony.kstarbound.client.network.packets.InitialChunkDataPacket
import ru.dbotthepony.kstarbound.client.network.packets.SpawnWorldObjectPacket
import ru.dbotthepony.kstarbound.network.Connection
import ru.dbotthepony.kstarbound.network.ConnectionSide
import ru.dbotthepony.kstarbound.network.ConnectionType
import ru.dbotthepony.kstarbound.network.IServerPacket
import ru.dbotthepony.kstarbound.network.packets.HelloPacket
import ru.dbotthepony.kstarbound.server.StarboundServer
import ru.dbotthepony.kstarbound.server.world.ServerWorld
import ru.dbotthepony.kstarbound.world.ChunkPos
import ru.dbotthepony.kvector.vector.Vector2d
import java.util.*
import kotlin.properties.Delegates
// server -> client
class ServerConnection(val server: StarboundServer, type: ConnectionType) : Connection(ConnectionSide.SERVER, type, UUID(0L, 0L)) {
var world: ServerWorld? = null
set(value) {
field = value
needsToRecomputeTrackedChunks = true
}
var trackedPosition: Vector2d = Vector2d(238.0, 685.0)
set(value) {
if (field != value) {
field = value
needsToRecomputeTrackedChunks = true
}
}
var trackedPositionChunk: ChunkPos = ChunkPos.ZERO
private set
var trackedChunksWidth = 4
set(value) {
if (field != value) {
field = value
needsToRecomputeTrackedChunks = true
}
}
var trackedChunksHeight = 4
set(value) {
if (field != value) {
field = value
needsToRecomputeTrackedChunks = true
}
}
private val tickets = Object2ObjectOpenHashMap<ChunkPos, ServerWorld.ITicket>()
private val sentChunks = ObjectOpenHashSet<ChunkPos>()
private var needsToRecomputeTrackedChunks = true
private fun recomputeTrackedChunks() {
val world = world ?: return
val trackedPositionChunk = world.geometry.chunkFromCell(trackedPosition)
needsToRecomputeTrackedChunks = false
if (trackedPositionChunk == this.trackedPositionChunk) return
val tracked = ObjectOpenHashSet<ChunkPos>()
for (x in -trackedChunksWidth .. trackedChunksWidth) {
for (y in -trackedChunksHeight .. trackedChunksHeight) {
tracked.add(world.geometry.wrap(trackedPositionChunk + ChunkPos(x, y)))
}
}
val itr = tickets.entries.iterator()
for ((pos, ticket) in itr) {
if (pos !in tracked) {
ticket.cancel()
itr.remove()
}
}
for (pos in tracked) {
if (pos !in tickets) {
tickets[pos] = world.permanentChunkTicket(pos)
}
}
}
fun tick() {
val world = world
if (world == null) {
tickets.values.forEach { it.cancel() }
tickets.clear()
sentChunks.clear()
return
}
if (needsToRecomputeTrackedChunks) {
recomputeTrackedChunks()
}
for (pos in tickets.keys) {
if (pos !in sentChunks) {
val chunk = world.chunkMap[pos]
if (chunk != null) {
send(InitialChunkDataPacket(chunk))
chunk.objects.forEach {
send(SpawnWorldObjectPacket(it.serialize()))
}
sentChunks.add(pos)
}
}
}
val itr = sentChunks.iterator()
for (pos in itr) {
if (pos !in tickets) {
send(ForgetChunkPacket(pos))
itr.remove()
}
}
}
override fun channelRead(ctx: ChannelHandlerContext, msg: Any) {
if (msg is IServerPacket) {
try {
@ -27,15 +141,11 @@ class ServerConnection(val server: StarboundServer, type: ConnectionType) : Conn
}
}
override var player: ServerPlayer by Delegates.notNull()
private set
override fun inGame() {
server.playerInGame(player)
server.playerInGame(this)
}
override fun onHelloReceived(helloPacket: HelloPacket) {
player = ServerPlayer(this)
}
companion object {

View File

@ -1,127 +0,0 @@
package ru.dbotthepony.kstarbound.server.network
import it.unimi.dsi.fastutil.longs.LongOpenHashSet
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap
import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet
import ru.dbotthepony.kstarbound.client.network.packets.ForgetChunkPacket
import ru.dbotthepony.kstarbound.client.network.packets.InitialChunkDataPacket
import ru.dbotthepony.kstarbound.client.network.packets.SpawnWorldObjectPacket
import ru.dbotthepony.kstarbound.network.Player
import ru.dbotthepony.kstarbound.server.StarboundServer
import ru.dbotthepony.kstarbound.server.world.ServerWorld
import ru.dbotthepony.kstarbound.world.ChunkPos
import ru.dbotthepony.kvector.vector.Vector2d
import kotlin.concurrent.withLock
class ServerPlayer(connection: ServerConnection) : Player<ServerConnection>(connection, connection.uuid) {
inline val server: StarboundServer
get() = connection.server
var world: ServerWorld? = null
set(value) {
field = value
needsToRecomputeTrackedChunks = true
}
var trackedPosition: Vector2d = Vector2d(238.0, 685.0)
set(value) {
if (field != value) {
field = value
needsToRecomputeTrackedChunks = true
}
}
var trackedPositionChunk: ChunkPos = ChunkPos.ZERO
private set
var trackedChunksWidth = 1
set(value) {
if (field != value) {
field = value
needsToRecomputeTrackedChunks = true
}
}
var trackedChunksHeight = 1
set(value) {
if (field != value) {
field = value
needsToRecomputeTrackedChunks = true
}
}
private val tickets = Object2ObjectOpenHashMap<ChunkPos, ServerWorld.ITicket>()
private val sentChunks = ObjectOpenHashSet<ChunkPos>()
private var needsToRecomputeTrackedChunks = true
private fun recomputeTrackedChunks() {
val world = world ?: return
val trackedPositionChunk = world.geometry.chunkFromCell(trackedPosition)
needsToRecomputeTrackedChunks = false
if (trackedPositionChunk == this.trackedPositionChunk) return
val tracked = ObjectOpenHashSet<ChunkPos>()
for (x in -trackedChunksWidth .. trackedChunksWidth) {
for (y in -trackedChunksHeight .. trackedChunksHeight) {
tracked.add(world.geometry.wrap(trackedPositionChunk + ChunkPos(x, y)))
}
}
val itr = tickets.entries.iterator()
for ((pos, ticket) in itr) {
if (pos !in tracked) {
ticket.cancel()
itr.remove()
}
}
for (pos in tracked) {
if (pos !in tickets) {
tickets[pos] = world.permanentChunkTicket(pos)
}
}
}
fun tick() {
val world = world
if (world == null) {
tickets.values.forEach { it.cancel() }
tickets.clear()
sentChunks.clear()
return
}
if (needsToRecomputeTrackedChunks) {
recomputeTrackedChunks()
}
for (pos in tickets.keys) {
if (pos !in sentChunks) {
val chunk = world.chunkMap[pos]
if (chunk != null) {
connection.send(InitialChunkDataPacket(chunk))
chunk.objects.forEach {
connection.send(SpawnWorldObjectPacket(it.serialize()))
}
sentChunks.add(pos)
}
}
}
val itr = sentChunks.iterator()
for (pos in itr) {
if (pos !in tickets) {
connection.send(ForgetChunkPacket(pos))
itr.remove()
}
}
}
}

View File

@ -16,6 +16,6 @@ data class TrackedPositionPacket(val pos: Vector2d) : IServerPacket {
}
override fun play(connection: ServerConnection) {
connection.player.trackedPosition = pos
connection.trackedPosition = pos
}
}

View File

@ -19,7 +19,7 @@ data class TrackedSizePacket(val width: Int, val height: Int) : IServerPacket {
}
override fun play(connection: ServerConnection) {
connection.player.trackedChunksWidth = width
connection.player.trackedChunksHeight = height
connection.trackedChunksWidth = width
connection.trackedChunksHeight = height
}
}

View File

@ -6,15 +6,12 @@ import it.unimi.dsi.fastutil.objects.ObjectAVLTreeSet
import it.unimi.dsi.fastutil.objects.ObjectArraySet
import ru.dbotthepony.kstarbound.Starbound
import ru.dbotthepony.kstarbound.server.StarboundServer
import ru.dbotthepony.kstarbound.server.network.ServerPlayer
import ru.dbotthepony.kstarbound.server.network.ServerConnection
import ru.dbotthepony.kstarbound.util.KOptional
import ru.dbotthepony.kstarbound.util.composeFutures
import ru.dbotthepony.kstarbound.world.ChunkPos
import ru.dbotthepony.kstarbound.world.IChunkSubscriber
import ru.dbotthepony.kstarbound.world.World
import ru.dbotthepony.kstarbound.world.WorldGeometry
import ru.dbotthepony.kstarbound.world.entities.Entity
import ru.dbotthepony.kstarbound.world.entities.WorldObject
import java.io.Closeable
import java.util.concurrent.CompletableFuture
import java.util.concurrent.atomic.AtomicInteger
@ -31,7 +28,7 @@ class ServerWorld(
server.worlds.add(this)
}
val players = ObjectArraySet<ServerPlayer>()
val players = ObjectArraySet<ServerConnection>()
val thread = Thread(::runThread, "Starbound Server World $seed")
var isStopped: Boolean = false