diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt index bc224339..076e4866 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/Starbound.kt @@ -110,7 +110,7 @@ object Starbound : ISBFileLocator { private val LOGGER = LogManager.getLogger() - val thread = Thread(::universeThread, "Universe") + val thread = Thread(::universeThread, "Universe Thread") val mailbox = MailboxExecutorService(thread).also { it.exceptionHandler = ExceptionLogger(LOGGER) } val mailboxBootstrapped = MailboxExecutorService(thread).also { it.exceptionHandler = ExceptionLogger(LOGGER) } val mailboxInitialized = MailboxExecutorService(thread).also { it.exceptionHandler = ExceptionLogger(LOGGER) } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt index e003a432..4ebbf0ad 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt @@ -308,10 +308,6 @@ class ClientWorld( } } - override fun tick0() { - - } - companion object { val ring = listOf( Vector2i(0, 0), 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 5c0b000f..5437234a 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerWorld.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerWorld.kt @@ -9,7 +9,6 @@ import org.apache.logging.log4j.LogManager import ru.dbotthepony.kommons.util.IStruct2i import ru.dbotthepony.kommons.vector.Vector2d import ru.dbotthepony.kstarbound.Starbound -import ru.dbotthepony.kstarbound.defs.SpawnTarget import ru.dbotthepony.kstarbound.defs.WarpAction import ru.dbotthepony.kstarbound.defs.WorldID import ru.dbotthepony.kstarbound.defs.tile.TileDamage @@ -20,7 +19,6 @@ import ru.dbotthepony.kstarbound.json.builder.JsonFactory import ru.dbotthepony.kstarbound.network.IPacket import ru.dbotthepony.kstarbound.network.packets.StepUpdatePacket import ru.dbotthepony.kstarbound.network.packets.clientbound.PlayerWarpResultPacket -import ru.dbotthepony.kstarbound.network.packets.clientbound.WorldStopPacket import ru.dbotthepony.kstarbound.server.StarboundServer import ru.dbotthepony.kstarbound.server.ServerConnection import ru.dbotthepony.kstarbound.util.AssetPathStack @@ -64,14 +62,14 @@ class ServerWorld private constructor( } } - val players = CopyOnWriteArrayList() + val clients = CopyOnWriteArrayList() private fun doAcceptClient(client: ServerConnection, action: WarpAction?) { - if (players.any { it.client == client }) + if (clients.any { it.client == client }) throw IllegalStateException("$client is already in $this") val start = if (action is WarpAction.Player) - players.firstOrNull { it.client.uuid == action.uuid }?.client?.playerEntity?.position + clients.firstOrNull { it.client.uuid == action.uuid }?.client?.playerEntity?.position else if (action is WarpAction.World) action.target.resolve(this) else @@ -86,7 +84,7 @@ class ServerWorld private constructor( client.send(PlayerWarpResultPacket(true, action, false)) client.tracker?.remove() - players.add(ServerWorldTracker(this, client, start)) + clients.add(ServerWorldTracker(this, client, start)) } fun acceptClient(player: ServerConnection, action: WarpAction? = null): CompletableFuture { @@ -134,7 +132,7 @@ class ServerWorld private constructor( if (isClosed.compareAndSet(false, true)) { super.close() spinner.unpause() - players.forEach { it.remove() } + clients.forEach { it.remove() } if (worldID != WorldID.Limbo) server.worlds.remove(worldID) @@ -180,10 +178,11 @@ class ServerWorld private constructor( return topMost } - override fun tick0() { + override fun tick() { + super.tick() val packet = StepUpdatePacket(ticks) - players.forEach { + clients.forEach { if (!isClosed.get()) { it.send(packet) @@ -210,7 +209,7 @@ class ServerWorld private constructor( val unloadable = entityIndex .query( chunk.aabb, - predicate = Predicate { it.isApplicableForUnloading && chunk.aabb.isInside(it.position) }, + filter = Predicate { it.isApplicableForUnloading && chunk.aabb.isInside(it.position) }, distinct = true, withEdges = false) storage.saveCells(it.pos, chunk.copyCells()) @@ -230,7 +229,7 @@ class ServerWorld private constructor( } override fun broadcast(packet: IPacket) { - players.forEach { + clients.forEach { it.send(packet) } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerWorldTracker.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerWorldTracker.kt index f7b245f9..9510fca9 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerWorldTracker.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerWorldTracker.kt @@ -113,6 +113,18 @@ class ServerWorldTracker(val world: ServerWorld, val client: ServerConnection, p return pos in tickets } + fun isTracking(entity: AbstractEntity): Boolean { + return entityVersions.containsKey(entity.entityID) + } + + fun forget(entity: AbstractEntity, isDeath: Boolean = false) { + val version = entityVersions.remove(entity.entityID) + + if (version != -1L) { + send(EntityDestroyPacket(entity.entityID, entity.networkGroup.write(version, isLegacy = client.isLegacy).first, isDeath)) + } + } + fun tick() { if (!client.worldStartAcknowledged) return @@ -245,7 +257,7 @@ class ServerWorldTracker(val world: ServerWorld, val client: ServerConnection, p if (isActuallyRemoved) return isActuallyRemoved = true - world.players.remove(this) + world.clients.remove(this) tickets.values.forEach { it.ticket.cancel() } val itr = world.entities.int2ObjectEntrySet().iterator() diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/SpatialIndex.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/SpatialIndex.kt index e994522a..41b4c468 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/SpatialIndex.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/SpatialIndex.kt @@ -17,6 +17,7 @@ import kotlin.concurrent.withLock // Advantages of this system include allowing to put entities outside any chunks // into index and getting rid of "orphaned entities" collection, +// and allowing one entity to have multiple bounding boxes, // while also setting up ground for better spatial index strategies, if they // have to be done in the future. class SpatialIndex(val geometry: WorldGeometry) { @@ -242,17 +243,18 @@ class SpatialIndex(val geometry: WorldGeometry) { } /** - * [filter] might be invoked for same entry multiple times, regardless pf [distinct] + * [filter] might be invoked for same entry multiple times, regardless of [distinct] */ fun query(rect: AABBi, filter: Predicate = Predicate { true }, distinct: Boolean = true, withEdges: Boolean = true): List { return query(rect.toDoubleAABB(), filter, distinct, withEdges) } /** - * [predicate] might be invoked for same entry multiple times, regardless pf [distinct] + * [filter] might be invoked for same entry multiple times, regardless of [distinct] */ - fun query(rect: AABB, predicate: Predicate = Predicate { true }, distinct: Boolean = true, withEdges: Boolean = true): List { + fun query(rect: AABB, filter: Predicate = Predicate { true }, distinct: Boolean = true, withEdges: Boolean = true): List { val entries = ArrayList() + val entriesDirect = ArrayList() for (actualRegion in geometry.split(rect).first) { val xMin = geometry.x.chunkFromCell(actualRegion.mins.x) @@ -265,9 +267,17 @@ class SpatialIndex(val geometry: WorldGeometry) { for (y in yMin .. yMax) { val sector = map[index(x, y)] ?: continue - for (entry in sector.entries) { - if (predicate.test(entry.value) && entry.intersects(actualRegion, withEdges)) { - entries.add(entry) + if (distinct) { + for (entry in sector.entries) { + if (filter.test(entry.value) && entry.intersects(actualRegion, withEdges)) { + entries.add(entry) + } + } + } else { + for (entry in sector.entries) { + if (filter.test(entry.value) && entry.intersects(actualRegion, withEdges)) { + entriesDirect.add(entry.value) + } } } } @@ -292,10 +302,7 @@ class SpatialIndex(val geometry: WorldGeometry) { return entries0 } else { - if (entries.isEmpty()) - return listOf() - - return entries.map { it.value } + return entriesDirect } } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt index 0c39ae87..b6b49bfe 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt @@ -218,7 +218,6 @@ abstract class World, ChunkType : Chunk() val entityIndex = SpatialIndex(geometry) val dynamicEntities = ArrayList() - val tileEntities = ArrayList() var playerSpawnPosition = Vector2d.ZERO protected set @@ -252,34 +251,28 @@ abstract class World, ChunkType : Chunk) { - world.tileEntities.add(this) tilePosition = tilePosition } override fun onRemove(world: World<*, *>) { - world.tileEntities.remove(this) } }