diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt index 310cc70f..f3109d61 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt @@ -125,9 +125,11 @@ fun main() { for (i in 0 .. 128) { val item = ItemEntity(client.world!!, Registries.items.values.random().value) - item.position = Vector2d(225.0 - i, 685.0) + item.position = Vector2d(225.0 - i, 785.0) item.spawn() item.velocity = Vector2d(rand.nextDouble() * 32.0 - 16.0, rand.nextDouble() * 32.0 - 16.0) + + item.mailbox.scheduleAtFixedRate({ item.velocity += Vector2d(rand.nextDouble() * 32.0 - 16.0, rand.nextDouble() * 32.0 - 16.0) }, 1000 + rand.nextLong(-100, 100), 1000 + rand.nextLong(-100, 100), TimeUnit.MILLISECONDS) //item.movement.applyVelocity(Vector2d(rand.nextDouble() * 1000.0 - 500.0, rand.nextDouble() * 1000.0 - 500.0)) } 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 2041609c..e0771b53 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt @@ -46,6 +46,9 @@ class ClientWorld( throw RuntimeException("unreachable code") } + override val isClient: Boolean + get() = true + val renderRegionWidth = if (size == null) 16 else determineChunkSize(size.x) val renderRegionHeight = if (size == null) 16 else determineChunkSize(size.y) val renderRegionsX = if (size == null) 0 else size.x / renderRegionWidth @@ -304,18 +307,7 @@ class ClientWorld( } override fun thinkInner() { - val entities = ObjectArrayList(entities) - for (ent in entities) { - ent.think() - } - - val objects = ObjectArrayList(objects) - - for (ent in objects) { - ent.thinkShared() - ent.thinkClient() - } } companion object { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/BaseMovementParameters.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/BaseMovementParameters.kt index e928707f..dfc28256 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/BaseMovementParameters.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/BaseMovementParameters.kt @@ -22,6 +22,8 @@ interface BaseMovementParameters { // horizontal ground without losing horizontal speed. val enableSurfaceSlopeCorrection: KOptional val slopeSlidingFactor: KOptional + + // ignored val maxMovementPerStep: KOptional val maximumCorrection: KOptional val speedLimit: KOptional diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt index 73678d63..61ef8e3f 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/Chunk.kt @@ -16,9 +16,6 @@ import ru.dbotthepony.kstarbound.world.entities.Entity import ru.dbotthepony.kvector.arrays.Object2DArray import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.vector.Vector2d -import java.util.* -import java.util.concurrent.locks.ReentrantLock -import kotlin.collections.ArrayList import kotlin.concurrent.withLock /** @@ -261,7 +258,7 @@ abstract class Chunk, This : Chunk, This : Chunk) { - world.entityMoveLock.withLock { + world.entityListsLock.withLock { if (otherChunk == this) throw IllegalArgumentException("what?") @@ -295,7 +292,7 @@ abstract class Chunk, This : Chunk, ChunkType : Chunk, ChunkType : Chunk() - - /** - * Сущности, находящиеся в этом мире - */ val entities = ReferenceLinkedOpenHashSet() - val objects = ReferenceLinkedOpenHashSet() protected abstract fun chunkFactory(pos: ChunkPos): ChunkType @@ -285,6 +304,48 @@ abstract class World, ChunkType : Chunk = ImmutableList.of( + Vector2d(0.5, 0.5), + Vector2d(0.5, 1.0), + Vector2d(0.5, 1.5), + Vector2d(1.0, 1.5), + Vector2d(1.5, 1.5), + Vector2d(1.5, 1.0), + Vector2d(1.5, 0.5), + Vector2d(1.0, 0.5), + Vector2d(1.0, 1.0) + ) + + private val POLY_INDICES: ImmutableList = ImmutableList.of( + IntList.of(9, 9, 9, 9, 9, 9), + IntList.of(1, 2, 3, 9, 9, 9), + IntList.of(3, 4, 5, 9, 9, 9), + IntList.of(1, 2, 4, 5, 9, 9), + IntList.of(7, 5, 6, 9, 9, 9), + IntList.of(1, 2, 3, 5, 6, 7), + IntList.of(7, 3, 4, 6, 9, 9), + IntList.of(1, 2, 4, 6, 7, 9), + IntList.of(0, 1, 7, 9, 9, 9), + IntList.of(0, 2, 3, 7, 9, 9), + IntList.of(0, 1, 3, 4, 5, 7), + IntList.of(0, 2, 4, 5, 7, 9), + IntList.of(0, 1, 5, 6, 9, 9), + IntList.of(0, 2, 3, 5, 6, 9), + IntList.of(0, 1, 3, 4, 6, 9), + IntList.of(0, 2, 4, 6, 9, 9), + // special cases for squared off top corners + IntList.of(5, 6, 7, 8, 9, 9), // top left corner + IntList.of(0, 1, 8, 7, 9, 9), // top right corner + // special cases for hollowed out bottom corners + IntList.of(0, 2, 3, 8, 9, 9), // lower left corner part 1 + IntList.of(0, 8, 5, 6, 9, 9), // lower left corner part 2 + IntList.of(0, 1, 8, 6, 9, 9), // lower right corner part 1 + IntList.of(6, 8, 3, 4, 9, 9) // lower right corner part 2 + ) + private val BLOCK_POLY = Poly(listOf(Vector2d.ZERO, Vector2d(0.0, 1.0), Vector2d(1.0, 1.0), Vector2d(1.0, 0.0))) + private val PEAK = Poly(listOf(Vector2d(0.0, 0.0), Vector2d(0.5, 1.0), Vector2d(1.0, 0.0))) + private val PX_NY = Poly(listOf(Vector2d(0.0, 0.0), Vector2d(0.0, 1.0), Vector2d(1.0, 0.0))) + private val NX_NY = Poly(listOf(Vector2d(-1.0, 0.0), Vector2d(0.0, 1.0), Vector2d(0.0, 0.0))) } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt index 677dcdf3..3c082725 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt @@ -12,8 +12,10 @@ import ru.dbotthepony.kstarbound.world.physics.CollisionPoly import ru.dbotthepony.kstarbound.world.physics.CollisionType import ru.dbotthepony.kstarbound.world.physics.Poly import ru.dbotthepony.kvector.util2d.AABB +import ru.dbotthepony.kvector.vector.RGBAColor import ru.dbotthepony.kvector.vector.Vector2d import java.util.EnumSet +import kotlin.concurrent.withLock abstract class Entity(val world: World<*, *>) { var chunk: Chunk<*, *>? = null @@ -35,14 +37,16 @@ abstract class Entity(val world: World<*, *>) { val oldChunk = field field = value - if (oldChunk == null && value != null) { - world.orphanedEntities.remove(this) - value.addEntity(this) - } else if (oldChunk != null && value == null) { - world.orphanedEntities.add(this) - oldChunk.removeEntity(this) - } else if (oldChunk != null && value != null) { - value.transferEntity(this, oldChunk) + world.entityListsLock.withLock { + if (oldChunk == null && value != null) { + world.orphanedEntities.remove(this) + value.addEntity(this) + } else if (oldChunk != null && value == null) { + world.orphanedEntities.add(this) + oldChunk.removeEntity(this) + } else if (oldChunk != null && value != null) { + value.transferEntity(this, oldChunk) + } } } @@ -126,16 +130,17 @@ abstract class Entity(val world: World<*, *>) { /** * this function is executed sequentially */ - fun think() { - if (!isSpawned) { - throw IllegalStateException("Tried to think before spawning in world") - } - + open fun thinkShared() { mailbox.executeQueuedTasks() - thinkInner() } - protected abstract fun thinkInner() + open fun thinkClient() { + + } + + open fun thinkServer() { + + } /** * this function is executed in parallel @@ -146,6 +151,12 @@ abstract class Entity(val world: World<*, *>) { var physicsSleepTicks = physicsSleepTicks velocity += world.gravity * Starbound.TICK_TIME_ADVANCE + movementParameters.speedLimit.ifPresent { + if (velocity.length > it) { + velocity = velocity.unitVector * it + } + } + if (hitboxes.isEmpty()) { position += velocity * Starbound.TICK_TIME_ADVANCE return @@ -161,7 +172,7 @@ abstract class Entity(val world: World<*, *>) { val localHitboxes = hitboxes.map { it + position } val polies = world.queryCollisions( - localHitboxes.stream().map { it.aabb }.reduce(AABB::combine).get().enlarge(1.0, 1.0) + localHitboxes.stream().map { it.aabb }.reduce(AABB::combine).get().enlarge(2.0, 2.0) ).filter { if (collisionFilterMode) it.type in collisionFilter @@ -211,6 +222,15 @@ abstract class Entity(val world: World<*, *>) { open fun render(client: StarboundClient = StarboundClient.current()) { hitboxes.forEach { (it + position).render(client) } + + world.queryCollisions( + hitboxes.stream().map { (it + position).aabb }.reduce(AABB::combine).get().enlarge(2.0, 2.0) + ).filter { + if (collisionFilterMode) + it.type in collisionFilter + else + it.type !in collisionFilter + }.forEach { it.poly.render(client, BLOCK_COLLISION_COLOR) } } open var maxHealth = 0.0 @@ -222,5 +242,6 @@ abstract class Entity(val world: World<*, *>) { companion object { const val PHYSICS_TICKS_UNTIL_SLEEP = 16 + val BLOCK_COLLISION_COLOR = RGBAColor(65, 179, 217) } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/ItemEntity.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/ItemEntity.kt index d6a23e95..1747d2c5 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/ItemEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/ItemEntity.kt @@ -10,9 +10,4 @@ class ItemEntity(world: World<*, *>, val def: IItemDefinition) : Entity(world) { init { hitboxes.add(Poly(AABB.rectangle(Vector2d.ZERO, 0.75, 0.75))) } - - override fun thinkInner() { - // TODO: деспавнинг? - // просто, как бы, предметы не должны уж так сильно нагружать процессор - } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/WorldObject.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/WorldObject.kt index be646146..5eb76346 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/WorldObject.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/WorldObject.kt @@ -14,6 +14,7 @@ import ru.dbotthepony.kstarbound.defs.JsonDriven import ru.dbotthepony.kstarbound.defs.image.SpriteReference import ru.dbotthepony.kstarbound.defs.`object`.ObjectDefinition import ru.dbotthepony.kstarbound.defs.`object`.ObjectOrientation +import ru.dbotthepony.kstarbound.util.MailboxExecutorService import ru.dbotthepony.kstarbound.util.get import ru.dbotthepony.kstarbound.util.set import ru.dbotthepony.kstarbound.world.Side @@ -47,6 +48,8 @@ open class WorldObject( } } + val mailbox = MailboxExecutorService() + // // internal runtime properties // @@ -139,6 +142,7 @@ open class WorldObject( } open fun thinkShared() { + mailbox.executeQueuedTasks() flickerPeriod?.update(Starbound.TICK_TIME_ADVANCE, world.random) }