diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/network/Connection.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/network/Connection.kt index 20d3f587..902a54d5 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/network/Connection.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/network/Connection.kt @@ -46,7 +46,7 @@ abstract class Connection(val side: ConnectionSide, val type: ConnectionType, va protected abstract fun inGame() fun helloReceived(helloPacket: HelloPacket) { - LOGGER.info("${side.opposite} HELLO Received from ${channel?.remoteAddress()}: $helloPacket") + LOGGER.info("Handshake received on $side from ${channel?.remoteAddress()}: $helloPacket") otherSide = helloPacket if (side == ConnectionSide.SERVER) { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerWorld.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerWorld.kt index ad07e647..c0896629 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerWorld.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerWorld.kt @@ -23,7 +23,7 @@ class ServerWorld( val server: StarboundServer, seed: Long, geometry: WorldGeometry, -) : World(seed, geometry), Closeable { +) : World(seed, geometry) { init { server.worlds.add(this) } @@ -49,10 +49,8 @@ class ServerWorld( private var nextThink = 0L override fun close() { - if (!isStopped) { - isStopped = true - lock.withLock { onUnload() } - } + super.close() + isStopped = true } fun startThread() { @@ -60,10 +58,6 @@ class ServerWorld( thread.start() } - private fun onUnload() { - - } - private fun runThread() { while (!isStopped) { var diff = System.nanoTime() - nextThink @@ -80,8 +74,7 @@ class ServerWorld( try { think() } catch (err: Throwable) { - isStopped = true - onUnload() + close() throw err } } @@ -127,7 +120,7 @@ class ServerWorld( fun permanentChunkTicket(pos: ChunkPos): ITicket { lock.withLock { - return getTicketList(pos).Ticket().init() + return getTicketList(pos).Ticket() } } @@ -135,7 +128,7 @@ class ServerWorld( require(time > 0) { "Invalid ticket time: $time" } lock.withLock { - return getTicketList(pos).TimedTicket(time).init() + return getTicketList(pos).TimedTicket(time) } } @@ -181,13 +174,14 @@ class ServerWorld( return temporary.isNotEmpty() || permanent.isNotEmpty() } - open inner class Ticket : ITicket { - open fun init(): Ticket { - if (this is TimedTicket) - temporary.add(this) - else - permanent.add(this) + abstract inner class AbstractTicket : ITicket { + final override val id: Int = nextTicketID.getAndIncrement() + final override val pos: ChunkPos + get() = this@TicketList.pos + final override var isCanceled: Boolean = false + + fun init() { if (first) { first = false @@ -196,12 +190,12 @@ class ServerWorld( if (chunkProviders.isNotEmpty()) { composeFutures(chunkProviders) - { if (!isValid) CompletableFuture.completedFuture(KOptional.empty()) else it.getTiles(pos) } + { if (!isValid) CompletableFuture.completedFuture(KOptional.empty()) else it.getTiles(pos) } .thenAccept(Consumer { tiles -> if (!isValid || !tiles.isPresent) return@Consumer composeFutures(chunkProviders) - { if (!isValid) CompletableFuture.completedFuture(KOptional.empty()) else it.getEntities(pos) } + { if (!isValid) CompletableFuture.completedFuture(KOptional.empty()) else it.getEntities(pos) } .thenAcceptAsync(Consumer { ents -> if (!isValid) return@Consumer val chunk = chunkMap.compute(pos) ?: return@Consumer @@ -213,44 +207,49 @@ class ServerWorld( } } }, mailbox) - }) + }) } } } - - return this } - final override val id: Int = nextTicketID.getAndIncrement() - final override val pos: ChunkPos - get() = this@TicketList.pos - final override fun cancel() { if (isCanceled) return lock.withLock { if (isCanceled) return isCanceled = true - - if (this is TimedTicket) - temporary.remove(this) - else - permanent.remove(this) + onCancel() } } - final override var isCanceled: Boolean = false + protected abstract fun onCancel() } - inner class TimedTicket(expiresAt: Int) : Ticket(), ITimedTicket { + inner class Ticket : AbstractTicket() { + init { + permanent.add(this) + init() + } + + override fun onCancel() { + permanent.remove(this) + } + } + + inner class TimedTicket(expiresAt: Int) : AbstractTicket(), ITimedTicket { var expiresAt = expiresAt + ticks override val timeRemaining: Int get() = (expiresAt - ticks).coerceAtLeast(0) - override fun init(): TimedTicket { - super.init() - return this + init { + temporary.add(this) + init() + } + + override fun onCancel() { + temporary.remove(this) } override fun prolong(ticks: Int) { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt index af6ccb29..5d92128c 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt @@ -46,7 +46,7 @@ abstract class Chunk, This : Chunk() val objects = ReferenceOpenHashSet() - protected val subscribers = ObjectArraySet() + protected val subscribers = ObjectArraySet() // local cells' tile access val localBackgroundView = TileView.Background(this) @@ -135,6 +135,8 @@ abstract class Chunk, This : Chunk Unit) { @@ -152,11 +154,11 @@ abstract class Chunk, This : Chunk, ChunkType : Chunk>( val seed: Long, val geometry: WorldGeometry, -) : ICellAccess { +) : ICellAccess, Closeable { // whenever provided cell position is within actual world borders, ignoring wrapping fun inBounds(x: Int, y: Int) = geometry.x.inBoundsCell(x) && geometry.y.inBoundsCell(y) fun inBounds(value: IStruct2i) = geometry.x.inBoundsCell(value.component1()) && geometry.y.inBoundsCell(value.component2()) @@ -279,6 +280,10 @@ abstract class World, ChunkType : Chunk { val result = ArrayList() val tiles = aabb.encasingIntAABB()