From a46269aa15357908445e5693bb2da6aa0460531d Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 12 Apr 2024 10:24:47 +0700 Subject: [PATCH] Performance improvement bits --- .../kstarbound/defs/world/WorldTemplate.kt | 11 +++-- .../kstarbound/server/world/ServerChunk.kt | 44 +++++++------------ .../world/{SpatialIndex.kt => EntityIndex.kt} | 30 +++++++++---- .../ru/dbotthepony/kstarbound/world/World.kt | 42 ++++++++++-------- .../world/entities/AbstractEntity.kt | 5 +-- .../world/entities/DynamicEntity.kt | 5 +-- .../world/entities/MovementController.kt | 8 ++-- .../world/entities/player/PlayerEntity.kt | 3 -- .../world/entities/tile/WorldObject.kt | 12 +++-- .../world/entities/wire/WireConnection.kt | 16 ++++--- .../world/terrain/KarstCaveTerrainSelector.kt | 8 ++-- .../world/terrain/WormCaveTerrainSelector.kt | 4 +- .../dbotthepony/kstarbound/test/WorldTests.kt | 31 +++++++++++-- 13 files changed, 128 insertions(+), 91 deletions(-) rename src/main/kotlin/ru/dbotthepony/kstarbound/world/{SpatialIndex.kt => EntityIndex.kt} (84%) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/world/WorldTemplate.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/world/WorldTemplate.kt index 078ee84d..e4c969dd 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/world/WorldTemplate.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/world/WorldTemplate.kt @@ -25,6 +25,7 @@ import ru.dbotthepony.kstarbound.world.Universe import ru.dbotthepony.kstarbound.world.UniversePos import ru.dbotthepony.kstarbound.world.WorldGeometry import ru.dbotthepony.kstarbound.world.physics.Poly +import java.time.Duration import java.util.concurrent.CopyOnWriteArrayList import java.util.random.RandomGenerator @@ -299,17 +300,19 @@ class WorldTemplate(val geometry: WorldGeometry) { } private val cellCache = Caffeine.newBuilder() - .maximumSize(50_000L) - //.expireAfterAccess(Duration.ofMinutes(1)) - //.executor(Starbound.EXECUTOR) - //.scheduler(Starbound) // don't specify scheduler since this cache is accessed very frequently + .maximumSize(150_000L) + .expireAfterAccess(Duration.ofMinutes(1)) + .executor(Starbound.EXECUTOR) + .scheduler(Starbound) .build { (x, y) -> cellInfo0(x, y) } fun cellInfo(x: Int, y: Int): CellInfo { + worldLayout ?: return CellInfo(x, y) return cellCache.get(Vector2i(x, y)) } fun cellInfo(pos: Vector2i): CellInfo { + worldLayout ?: return CellInfo(pos.x, pos.y) return cellCache.get(pos) } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerChunk.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerChunk.kt index 6881a2ef..9e5f8aec 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerChunk.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/server/world/ServerChunk.kt @@ -51,6 +51,7 @@ import ru.dbotthepony.kstarbound.world.api.TileColor import ru.dbotthepony.kstarbound.world.entities.AbstractEntity import ru.dbotthepony.kstarbound.world.entities.ItemDropEntity import java.util.concurrent.CompletableFuture +import java.util.concurrent.CopyOnWriteArrayList import java.util.concurrent.TimeUnit import java.util.concurrent.locks.ReentrantLock import java.util.function.Predicate @@ -68,8 +69,9 @@ class ServerChunk(world: ServerWorld, pos: ChunkPos) : Chunk(Int.MAX_VALUE) - private val permanent = ArrayList() + private val permanent = CopyOnWriteArrayList() private val temporary = ObjectAVLTreeSet() + private val temporaryList = CopyOnWriteArrayList() private var nextTicketID = 0 // ticket lock because tickets *could* be canceled (or created) concurrently // BUT, front-end ticket creation in ServerWorld is expected to be called only on ServerWorld's thread @@ -285,29 +287,13 @@ class ServerChunk(world: ServerWorld, pos: ChunkPos) : Chunk - val temporary: List - - ticketsLock.withLock { - permanent = ObjectArrayList(this.permanent) - temporary = ObjectArrayList(this.temporary) - } - permanent.forEach { if (it.targetState <= state) it.listener?.onCellChanges(x, y, cell) } - temporary.forEach { if (it.targetState <= state) it.listener?.onCellChanges(x, y, cell) } + temporaryList.forEach { if (it.targetState <= state) it.listener?.onCellChanges(x, y, cell) } } private fun onTileHealthUpdate(x: Int, y: Int, isBackground: Boolean, health: TileHealth) { - val permanent: List - val temporary: List - - ticketsLock.withLock { - permanent = ObjectArrayList(this.permanent) - temporary = ObjectArrayList(this.temporary) - } - permanent.forEach { if (it.targetState <= state) it.listener?.onTileHealthUpdate(x, y, isBackground, health) } - temporary.forEach { if (it.targetState <= state) it.listener?.onTileHealthUpdate(x, y, isBackground, health) } + temporaryList.forEach { if (it.targetState <= state) it.listener?.onTileHealthUpdate(x, y, isBackground, health) } } private abstract inner class AbstractTicket(val targetState: ChunkState) : ITicket { @@ -360,11 +346,13 @@ class ServerChunk(world: ServerWorld, pos: ChunkPos) : Chunk 0) temporary.add(this) + + if (timeRemaining > 0) { + temporary.add(this) + } else { + temporaryList.remove(this) + } } } } @@ -385,16 +378,8 @@ class ServerChunk(world: ServerWorld, pos: ChunkPos) : Chunk= state) { "Tried to downgrade $this state from $state to $newState" } this.state = newState - val permanent: List - val temporary: List - - ticketsLock.withLock { - permanent = ObjectArrayList(this.permanent) - temporary = ObjectArrayList(this.temporary) - } - permanent.forEach { if (it.targetState <= state) it.chunk.complete(this) } - temporary.forEach { if (it.targetState <= state) it.chunk.complete(this) } + temporaryList.forEach { if (it.targetState <= state) it.chunk.complete(this) } } data class DamageResult(val result: TileDamageResult, val health: TileHealth? = null, val stateBefore: AbstractCell? = null) @@ -498,6 +483,7 @@ class ServerChunk(world: ServerWorld, pos: ChunkPos) : Chunk(val geometry: WorldGeometry) { +class EntityIndex(val geometry: WorldGeometry) { private val lock = Any() private val map = Long2ObjectOpenHashMap() private val factory = Long2ObjectFunction { Sector(it) } @@ -55,7 +59,7 @@ class SpatialIndex(val geometry: WorldGeometry) { } } - inner class Entry(val value: T) : Comparable { + inner class Entry(val value: AbstractEntity) : Comparable { private val sectors = Object2IntAVLTreeMap() val id = counter.getAndIncrement() private val fixtures = ArrayList(1) @@ -246,8 +250,8 @@ class SpatialIndex(val geometry: WorldGeometry) { } } - fun query(rect: AABB, filter: Predicate = Predicate { true }, withEdges: Boolean = true): List { - val entriesDirect = ArrayList() + fun query(rect: AABB, filter: Predicate = Predicate { true }, withEdges: Boolean = true): List { + val entriesDirect = ArrayList() iterate(rect, withEdges = withEdges, visitor = { if (filter.test(it)) entriesDirect.add(it) @@ -256,23 +260,33 @@ class SpatialIndex(val geometry: WorldGeometry) { return entriesDirect } - fun any(rect: AABB, filter: Predicate = Predicate { true }, withEdges: Boolean = true): Boolean { + fun any(rect: AABB, filter: Predicate = Predicate { true }, withEdges: Boolean = true): Boolean { return walk(rect, withEdges = withEdges, visitor = { if (filter.test(it)) KOptional(true) else KOptional() }).orElse(false) } - fun all(rect: AABB, filter: Predicate = Predicate { true }, withEdges: Boolean = true): Boolean { + fun all(rect: AABB, filter: Predicate = Predicate { true }, withEdges: Boolean = true): Boolean { return walk(rect, withEdges = withEdges, visitor = { if (!filter.test(it)) KOptional(false) else KOptional() }).orElse(true) } - fun iterate(rect: AABB, visitor: (T) -> Unit, withEdges: Boolean = true) { + fun first(rect: AABB, filter: Predicate = Predicate { true }, withEdges: Boolean = true): AbstractEntity? { + return walk(rect, withEdges = withEdges, visitor = { + if (filter.test(it)) KOptional(it) else KOptional() + }).orNull() + } + + fun tileEntityAt(pos: Vector2i): TileEntity? { + return first(AABB(pos.toDoubleVector(), pos.toDoubleVector() + Vector2d.POSITIVE_XY), Predicate { it is TileEntity && pos in it.occupySpaces }) as TileEntity? + } + + fun iterate(rect: AABB, visitor: (AbstractEntity) -> Unit, withEdges: Boolean = true) { walk(rect, { visitor(it); KOptional() }, withEdges) } - fun walk(rect: AABB, visitor: (T) -> KOptional, withEdges: Boolean = true): KOptional { + fun walk(rect: AABB, visitor: (AbstractEntity) -> KOptional, withEdges: Boolean = true): KOptional { val seen = IntAVLTreeSet() for (actualRegion in geometry.split(rect).first) { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt index b9b77cc2..eeb0c033 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt @@ -17,10 +17,7 @@ import ru.dbotthepony.kommons.util.AABB import ru.dbotthepony.kommons.util.AABBi import ru.dbotthepony.kommons.vector.Vector2d import ru.dbotthepony.kommons.vector.Vector2i -import ru.dbotthepony.kstarbound.Registry import ru.dbotthepony.kstarbound.Starbound -import ru.dbotthepony.kstarbound.defs.tile.TileDefinition -import ru.dbotthepony.kstarbound.defs.tile.isNotEmptyTile import ru.dbotthepony.kstarbound.defs.world.WorldStructure import ru.dbotthepony.kstarbound.defs.world.WorldTemplate import ru.dbotthepony.kstarbound.json.mergeJson @@ -111,6 +108,7 @@ abstract class World, ChunkType : Chunk() // see CONCURRENT_SPARSE_CHUNK_MAP private val lock = Any() + private val list = CopyOnWriteArrayList() override fun get(x: Int, y: Int): ChunkType? { if (!geometry.x.inBoundsChunk(x) || !geometry.y.inBoundsChunk(y)) return null @@ -130,10 +128,18 @@ abstract class World, ChunkType : Chunk, ChunkType : Chunk, ChunkType : Chunk { - if (CONCURRENT_SPARSE_CHUNK_MAP) { - synchronized(lock) { - return ObjectArrayList(map.values) - } - } else { - return ObjectArrayList(map.values) - } + return list } override val size: Int @@ -177,11 +179,15 @@ abstract class World, ChunkType : Chunk(divideUp(geometry.size.x, CHUNK_SIZE), divideUp(geometry.size.y, CHUNK_SIZE)) - private val existing = ObjectAVLTreeSet() + private val list = CopyOnWriteArrayList() override fun compute(x: Int, y: Int): ChunkType? { if (!geometry.x.inBoundsChunk(x) || !geometry.y.inBoundsChunk(y)) return null - return map[x, y] ?: chunkFactory(ChunkPos(x, y)).also { existing.add(ChunkPos(x, y)); map[x, y] = it; onChunkCreated(it) } + return map[x, y] ?: chunkFactory(ChunkPos(x, y)).also { + list.add(it) + map[x, y] = it + onChunkCreated(it) + } } override fun get(x: Int, y: Int): ChunkType? { @@ -198,17 +204,17 @@ abstract class World, ChunkType : Chunk { - return existing.map { (x, y) -> map[x, y] ?: throw ConcurrentModificationException() } + return list } override val size: Int - get() = existing.size + get() = list.size } val chunkMap: ChunkMap = if (geometry.size.x <= 32000 && geometry.size.y <= 32000) ArrayChunkMap() else SparseChunkMap() @@ -227,7 +233,7 @@ abstract class World, ChunkType : Chunk() val entityList = CopyOnWriteArrayList() - val entityIndex = SpatialIndex(geometry) + val entityIndex = EntityIndex(geometry) val dynamicEntities = ArrayList() var playerSpawnPosition = Vector2d.ZERO diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/AbstractEntity.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/AbstractEntity.kt index 0aa74bff..c1467d78 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/AbstractEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/AbstractEntity.kt @@ -7,7 +7,6 @@ import ru.dbotthepony.kommons.io.koptional import ru.dbotthepony.kommons.util.AABB import ru.dbotthepony.kommons.util.KOptional import ru.dbotthepony.kommons.vector.Vector2d -import ru.dbotthepony.kstarbound.Starbound import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.render.LayeredRenderer import ru.dbotthepony.kstarbound.client.world.ClientWorld @@ -22,7 +21,7 @@ import ru.dbotthepony.kstarbound.network.syncher.networkedData import ru.dbotthepony.kstarbound.server.world.ServerWorld import ru.dbotthepony.kstarbound.util.MailboxExecutorService import ru.dbotthepony.kstarbound.world.LightCalculator -import ru.dbotthepony.kstarbound.world.SpatialIndex +import ru.dbotthepony.kstarbound.world.EntityIndex import ru.dbotthepony.kstarbound.world.World import java.io.DataOutputStream import java.util.function.Consumer @@ -104,7 +103,7 @@ abstract class AbstractEntity(path: String) : JsonDriven(path), Comparable.Entry? = null + protected var spatialEntry: EntityIndex.Entry? = null private set /** diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/DynamicEntity.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/DynamicEntity.kt index e6426317..667c2f88 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/DynamicEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/DynamicEntity.kt @@ -2,11 +2,10 @@ package ru.dbotthepony.kstarbound.world.entities import ru.dbotthepony.kommons.math.RGBAColor import ru.dbotthepony.kommons.util.AABB -import ru.dbotthepony.kstarbound.Globals import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.render.LayeredRenderer import ru.dbotthepony.kstarbound.client.render.RenderLayer -import ru.dbotthepony.kstarbound.world.SpatialIndex +import ru.dbotthepony.kstarbound.world.EntityIndex import ru.dbotthepony.kstarbound.world.World /** @@ -43,7 +42,7 @@ abstract class DynamicEntity(path: String) : AbstractEntity(path) { } } - protected var metaFixture: SpatialIndex.Entry.Fixture? = null + protected var metaFixture: EntityIndex.Entry.Fixture? = null private set override fun onJoinWorld(world: World<*, *>) { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/MovementController.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/MovementController.kt index eaa00d86..af071b18 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/MovementController.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/MovementController.kt @@ -23,7 +23,7 @@ import ru.dbotthepony.kstarbound.network.syncher.networkedData import ru.dbotthepony.kstarbound.network.syncher.networkedFixedPoint import ru.dbotthepony.kstarbound.network.syncher.networkedFloat import ru.dbotthepony.kstarbound.network.syncher.networkedPoly -import ru.dbotthepony.kstarbound.world.SpatialIndex +import ru.dbotthepony.kstarbound.world.EntityIndex import ru.dbotthepony.kstarbound.world.World import ru.dbotthepony.kstarbound.world.physics.CollisionPoly import ru.dbotthepony.kstarbound.world.physics.CollisionType @@ -37,9 +37,9 @@ import kotlin.math.sin open class MovementController() { private var world0: World<*, *>? = null val world: World<*, *> get() = world0!! - private var spatialEntry: SpatialIndex<*>.Entry? = null + private var spatialEntry: EntityIndex.Entry? = null - fun initialize(world: World<*, *>, entry: SpatialIndex<*>.Entry?) { + fun initialize(world: World<*, *>, entry: EntityIndex.Entry?) { fixtures.clear() spatialEntry?.remove() this.world0 = world @@ -135,7 +135,7 @@ open class MovementController() { private val relativeXSurfaceVelocity = networkGroup.add(networkedFixedPoint(0.0125).also { it.interpolator = Interpolator.Linear }) private val relativeYSurfaceVelocity = networkGroup.add(networkedFixedPoint(0.0125).also { it.interpolator = Interpolator.Linear }) - private val fixtures = ArrayList.Entry.Fixture>() + private val fixtures = ArrayList() var fixturesChangeset: Int = 0 private set diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/player/PlayerEntity.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/player/PlayerEntity.kt index 0140f65b..a1c00907 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/player/PlayerEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/player/PlayerEntity.kt @@ -24,9 +24,6 @@ import ru.dbotthepony.kstarbound.network.syncher.networkedEnumExtraStupid import ru.dbotthepony.kstarbound.network.syncher.networkedEventCounter import ru.dbotthepony.kstarbound.network.syncher.networkedFixedPoint import ru.dbotthepony.kstarbound.network.syncher.networkedString -import ru.dbotthepony.kstarbound.world.SpatialIndex -import ru.dbotthepony.kstarbound.world.World -import ru.dbotthepony.kstarbound.world.entities.AbstractEntity import ru.dbotthepony.kstarbound.world.entities.Animator import ru.dbotthepony.kstarbound.world.entities.HumanoidActorEntity import ru.dbotthepony.kstarbound.world.entities.StatusController diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/WorldObject.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/WorldObject.kt index 950e0b62..063e2eb3 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/WorldObject.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/tile/WorldObject.kt @@ -195,21 +195,27 @@ open class WorldObject(val config: Registry.Entry) : TileEntit val chatPortrait by networkedString().also { networkGroup.upstream.add(it) } val chatConfig by networkedJsonElement().also { networkGroup.upstream.add(it) } - inner class WireNode(val position: Vector2i) { + inner class WireNode(val position: Vector2i, val isInput: Boolean) { var state by networkedBoolean().also { networkGroup.upstream.add(it) } val connections = NetworkedList(WireConnection.CODEC).also { networkGroup.upstream.add(it) } + + fun addConnection(connection: WireConnection) { + if (connection !in connections) { + connections.add(connection) + } + } } val inputNodes: ImmutableList = lookupProperty(JsonPath("inputNodes")) { JsonArray() } .asJsonArray .stream() - .map { WireNode(vectors.fromJsonTree(it)) } + .map { WireNode(vectors.fromJsonTree(it), true) } .collect(ImmutableList.toImmutableList()) val outputNodes: ImmutableList = lookupProperty(JsonPath("outputNodes")) { JsonArray() } .asJsonArray .stream() - .map { WireNode(vectors.fromJsonTree(it)) } + .map { WireNode(vectors.fromJsonTree(it), false) } .collect(ImmutableList.toImmutableList()) val offeredQuests = NetworkedList(QuestArcDescriptor.CODEC, QuestArcDescriptor.LEGACY_CODEC).also { networkGroup.upstream.add(it) } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/wire/WireConnection.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/wire/WireConnection.kt index 06aa0755..316780b1 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/wire/WireConnection.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/wire/WireConnection.kt @@ -1,20 +1,22 @@ package ru.dbotthepony.kstarbound.world.entities.wire import ru.dbotthepony.kommons.io.StreamCodec -import ru.dbotthepony.kommons.io.readVector2i -import ru.dbotthepony.kommons.io.writeStruct2i -import ru.dbotthepony.kommons.io.writeVarLong +import ru.dbotthepony.kommons.io.readSignedVarInt +import ru.dbotthepony.kommons.io.readVarInt +import ru.dbotthepony.kommons.io.writeSignedVarInt +import ru.dbotthepony.kommons.io.writeVarInt import ru.dbotthepony.kommons.vector.Vector2i import ru.dbotthepony.kstarbound.network.syncher.SizeTCodec import java.io.DataInputStream import java.io.DataOutputStream -data class WireConnection(val entityLocation: Vector2i, val index: Int = -1) { - constructor(stream: DataInputStream) : this(stream.readVector2i(), SizeTCodec.read(stream).toInt()) +data class WireConnection(val entityLocation: Vector2i, val index: Int = 0) { + constructor(stream: DataInputStream) : this(Vector2i(stream.readSignedVarInt(), stream.readSignedVarInt()), stream.readVarInt()) fun write(stream: DataOutputStream) { - stream.writeStruct2i((entityLocation)) - SizeTCodec.write(stream, index.toLong()) + stream.writeSignedVarInt(entityLocation.x) + stream.writeSignedVarInt(entityLocation.y) + stream.writeVarInt(index) } companion object { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/terrain/KarstCaveTerrainSelector.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/terrain/KarstCaveTerrainSelector.kt index e8446dbc..a8737cc5 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/terrain/KarstCaveTerrainSelector.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/terrain/KarstCaveTerrainSelector.kt @@ -58,9 +58,9 @@ class KarstCaveTerrainSelector(data: Data, parameters: TerrainSelectorParameters } private val layers = Caffeine.newBuilder() - .maximumSize(512L) + .maximumSize(2048L) .softValues() - .expireAfterAccess(Duration.ofSeconds(10)) + .expireAfterAccess(Duration.ofMinutes(1)) .scheduler(Starbound) .executor(Starbound.EXECUTOR) .build(::Layer) @@ -127,9 +127,9 @@ class KarstCaveTerrainSelector(data: Data, parameters: TerrainSelectorParameters } private val sectors = Caffeine.newBuilder() - .maximumSize(256L) + .maximumSize(512L) .softValues() - .expireAfterAccess(Duration.ofSeconds(10)) + .expireAfterAccess(Duration.ofMinutes(1)) .scheduler(Starbound) .executor(Starbound.EXECUTOR) .build(::Sector) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/terrain/WormCaveTerrainSelector.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/terrain/WormCaveTerrainSelector.kt index bfba2f79..dcd63ebc 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/terrain/WormCaveTerrainSelector.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/terrain/WormCaveTerrainSelector.kt @@ -178,9 +178,9 @@ class WormCaveTerrainSelector(data: Data, parameters: TerrainSelectorParameters) } private val sectors = Caffeine.newBuilder() - .maximumSize(256L) + .maximumSize(512L) .softValues() - .expireAfterAccess(Duration.ofSeconds(10)) + .expireAfterAccess(Duration.ofMinutes(1)) .scheduler(Starbound) .executor(Starbound.EXECUTOR) .build(::Sector) diff --git a/src/test/kotlin/ru/dbotthepony/kstarbound/test/WorldTests.kt b/src/test/kotlin/ru/dbotthepony/kstarbound/test/WorldTests.kt index 51fd4917..29156827 100644 --- a/src/test/kotlin/ru/dbotthepony/kstarbound/test/WorldTests.kt +++ b/src/test/kotlin/ru/dbotthepony/kstarbound/test/WorldTests.kt @@ -1,5 +1,6 @@ package ru.dbotthepony.kstarbound.test +import com.google.gson.JsonElement import org.junit.jupiter.api.Assertions.assertFalse import org.junit.jupiter.api.Assertions.assertTrue import org.junit.jupiter.api.DisplayName @@ -8,8 +9,12 @@ import ru.dbotthepony.kommons.util.AABB import ru.dbotthepony.kommons.util.AABBi import ru.dbotthepony.kommons.vector.Vector2d import ru.dbotthepony.kommons.vector.Vector2i -import ru.dbotthepony.kstarbound.world.SpatialIndex +import ru.dbotthepony.kstarbound.defs.EntityType +import ru.dbotthepony.kstarbound.json.JsonPath +import ru.dbotthepony.kstarbound.world.EntityIndex import ru.dbotthepony.kstarbound.world.WorldGeometry +import ru.dbotthepony.kstarbound.world.entities.AbstractEntity +import java.io.DataOutputStream object WorldTests { @Test @@ -42,9 +47,29 @@ object WorldTests { @DisplayName("Spatial index test") fun spatialIndex() { val geometry = WorldGeometry(Vector2i(3000, 2000), true, false) - val index = SpatialIndex(geometry) + val index = EntityIndex(geometry) - val entry = index.Entry(0) + val entry = index.Entry(object : AbstractEntity("/") { + override fun lookupProperty(path: JsonPath, orElse: () -> JsonElement): JsonElement { + TODO("Not yet implemented") + } + + override fun setProperty0(key: JsonPath, value: JsonElement) { + TODO("Not yet implemented") + } + + override val position: Vector2d + get() = TODO("Not yet implemented") + override val type: EntityType + get() = TODO("Not yet implemented") + + override fun writeNetwork(stream: DataOutputStream, isLegacy: Boolean) { + TODO("Not yet implemented") + } + + override val metaBoundingBox: AABB + get() = TODO("Not yet implemented") + }) // simple entry.fixture.move(AABB(