Misc fixes
This commit is contained in:
parent
b1b5b598f0
commit
ba0d792e83
@ -125,9 +125,11 @@ fun main() {
|
|||||||
for (i in 0 .. 128) {
|
for (i in 0 .. 128) {
|
||||||
val item = ItemEntity(client.world!!, Registries.items.values.random().value)
|
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.spawn()
|
||||||
item.velocity = Vector2d(rand.nextDouble() * 32.0 - 16.0, rand.nextDouble() * 32.0 - 16.0)
|
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))
|
//item.movement.applyVelocity(Vector2d(rand.nextDouble() * 1000.0 - 500.0, rand.nextDouble() * 1000.0 - 500.0))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,9 @@ class ClientWorld(
|
|||||||
throw RuntimeException("unreachable code")
|
throw RuntimeException("unreachable code")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override val isClient: Boolean
|
||||||
|
get() = true
|
||||||
|
|
||||||
val renderRegionWidth = if (size == null) 16 else determineChunkSize(size.x)
|
val renderRegionWidth = if (size == null) 16 else determineChunkSize(size.x)
|
||||||
val renderRegionHeight = if (size == null) 16 else determineChunkSize(size.y)
|
val renderRegionHeight = if (size == null) 16 else determineChunkSize(size.y)
|
||||||
val renderRegionsX = if (size == null) 0 else size.x / renderRegionWidth
|
val renderRegionsX = if (size == null) 0 else size.x / renderRegionWidth
|
||||||
@ -304,18 +307,7 @@ class ClientWorld(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun thinkInner() {
|
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 {
|
companion object {
|
||||||
|
@ -22,6 +22,8 @@ interface BaseMovementParameters {
|
|||||||
// horizontal ground without losing horizontal speed.
|
// horizontal ground without losing horizontal speed.
|
||||||
val enableSurfaceSlopeCorrection: KOptional<Boolean>
|
val enableSurfaceSlopeCorrection: KOptional<Boolean>
|
||||||
val slopeSlidingFactor: KOptional<Double>
|
val slopeSlidingFactor: KOptional<Double>
|
||||||
|
|
||||||
|
// ignored
|
||||||
val maxMovementPerStep: KOptional<Double>
|
val maxMovementPerStep: KOptional<Double>
|
||||||
val maximumCorrection: KOptional<Double>
|
val maximumCorrection: KOptional<Double>
|
||||||
val speedLimit: KOptional<Double>
|
val speedLimit: KOptional<Double>
|
||||||
|
@ -16,9 +16,6 @@ import ru.dbotthepony.kstarbound.world.entities.Entity
|
|||||||
import ru.dbotthepony.kvector.arrays.Object2DArray
|
import ru.dbotthepony.kvector.arrays.Object2DArray
|
||||||
import ru.dbotthepony.kvector.util2d.AABB
|
import ru.dbotthepony.kvector.util2d.AABB
|
||||||
import ru.dbotthepony.kvector.vector.Vector2d
|
import ru.dbotthepony.kvector.vector.Vector2d
|
||||||
import java.util.*
|
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
import kotlin.concurrent.withLock
|
import kotlin.concurrent.withLock
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -261,7 +258,7 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
protected open fun onEntityRemoved(entity: Entity) { }
|
protected open fun onEntityRemoved(entity: Entity) { }
|
||||||
|
|
||||||
fun addEntity(entity: Entity) {
|
fun addEntity(entity: Entity) {
|
||||||
world.entityMoveLock.withLock {
|
world.entityListsLock.withLock {
|
||||||
if (!entities.add(entity)) {
|
if (!entities.add(entity)) {
|
||||||
throw IllegalArgumentException("Already having having entity $entity")
|
throw IllegalArgumentException("Already having having entity $entity")
|
||||||
}
|
}
|
||||||
@ -272,7 +269,7 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun transferEntity(entity: Entity, otherChunk: Chunk<*, *>) {
|
fun transferEntity(entity: Entity, otherChunk: Chunk<*, *>) {
|
||||||
world.entityMoveLock.withLock {
|
world.entityListsLock.withLock {
|
||||||
if (otherChunk == this)
|
if (otherChunk == this)
|
||||||
throw IllegalArgumentException("what?")
|
throw IllegalArgumentException("what?")
|
||||||
|
|
||||||
@ -295,7 +292,7 @@ abstract class Chunk<WorldType : World<WorldType, This>, This : Chunk<WorldType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun removeEntity(entity: Entity) {
|
fun removeEntity(entity: Entity) {
|
||||||
world.entityMoveLock.withLock {
|
world.entityListsLock.withLock {
|
||||||
if (!entities.remove(entity)) {
|
if (!entities.remove(entity)) {
|
||||||
throw IllegalArgumentException("Already not having entity $entity")
|
throw IllegalArgumentException("Already not having entity $entity")
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,9 @@
|
|||||||
package ru.dbotthepony.kstarbound.world
|
package ru.dbotthepony.kstarbound.world
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableList
|
||||||
|
import it.unimi.dsi.fastutil.ints.IntList
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap
|
||||||
|
import it.unimi.dsi.fastutil.objects.ObjectArrayList
|
||||||
import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet
|
import it.unimi.dsi.fastutil.objects.ReferenceLinkedOpenHashSet
|
||||||
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet
|
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet
|
||||||
import ru.dbotthepony.kstarbound.math.*
|
import ru.dbotthepony.kstarbound.math.*
|
||||||
@ -12,6 +15,7 @@ import ru.dbotthepony.kstarbound.world.api.TileView
|
|||||||
import ru.dbotthepony.kstarbound.world.entities.Entity
|
import ru.dbotthepony.kstarbound.world.entities.Entity
|
||||||
import ru.dbotthepony.kstarbound.world.entities.WorldObject
|
import ru.dbotthepony.kstarbound.world.entities.WorldObject
|
||||||
import ru.dbotthepony.kstarbound.world.physics.CollisionPoly
|
import ru.dbotthepony.kstarbound.world.physics.CollisionPoly
|
||||||
|
import ru.dbotthepony.kstarbound.world.physics.CollisionType
|
||||||
import ru.dbotthepony.kstarbound.world.physics.Poly
|
import ru.dbotthepony.kstarbound.world.physics.Poly
|
||||||
import ru.dbotthepony.kvector.api.IStruct2d
|
import ru.dbotthepony.kvector.api.IStruct2d
|
||||||
import ru.dbotthepony.kvector.api.IStruct2i
|
import ru.dbotthepony.kvector.api.IStruct2i
|
||||||
@ -233,16 +237,39 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
|
|
||||||
val random: RandomGenerator = RandomGenerator.of("Xoroshiro128PlusPlus")
|
val random: RandomGenerator = RandomGenerator.of("Xoroshiro128PlusPlus")
|
||||||
var gravity = Vector2d(0.0, -EARTH_FREEFALL_ACCELERATION)
|
var gravity = Vector2d(0.0, -EARTH_FREEFALL_ACCELERATION)
|
||||||
|
abstract val isClient: Boolean
|
||||||
|
|
||||||
// used by world chunks to synchronize entity additions/transfer
|
// used by world chunks to synchronize entity additions/transfer
|
||||||
val entityMoveLock = ReentrantLock()
|
val entityListsLock = ReentrantLock()
|
||||||
|
|
||||||
fun think() {
|
fun think() {
|
||||||
try {
|
try {
|
||||||
mailbox.executeQueuedTasks()
|
mailbox.executeQueuedTasks()
|
||||||
|
val entities = ObjectArrayList(entities)
|
||||||
ForkJoinPool.commonPool().submit(ParallelPerform(entities.spliterator(), Entity::move)).join()
|
ForkJoinPool.commonPool().submit(ParallelPerform(entities.spliterator(), Entity::move)).join()
|
||||||
mailbox.executeQueuedTasks()
|
mailbox.executeQueuedTasks()
|
||||||
|
|
||||||
|
for (ent in entities) {
|
||||||
|
ent.thinkShared()
|
||||||
|
|
||||||
|
if (isClient)
|
||||||
|
ent.thinkClient()
|
||||||
|
else
|
||||||
|
ent.thinkServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
val objects = ObjectArrayList(objects)
|
||||||
|
|
||||||
|
for (ent in objects) {
|
||||||
|
ent.thinkShared()
|
||||||
|
|
||||||
|
if (isClient)
|
||||||
|
ent.thinkClient()
|
||||||
|
else
|
||||||
|
ent.thinkServer()
|
||||||
|
}
|
||||||
|
|
||||||
|
mailbox.executeQueuedTasks()
|
||||||
thinkInner()
|
thinkInner()
|
||||||
} catch(err: Throwable) {
|
} catch(err: Throwable) {
|
||||||
throw RuntimeException("Ticking world $this", err)
|
throw RuntimeException("Ticking world $this", err)
|
||||||
@ -251,16 +278,8 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
|
|
||||||
protected abstract fun thinkInner()
|
protected abstract fun thinkInner()
|
||||||
|
|
||||||
/**
|
|
||||||
* Сущности, у которых нет чанка, но они находятся в этом мире
|
|
||||||
*/
|
|
||||||
val orphanedEntities = ReferenceOpenHashSet<Entity>()
|
val orphanedEntities = ReferenceOpenHashSet<Entity>()
|
||||||
|
|
||||||
/**
|
|
||||||
* Сущности, находящиеся в этом мире
|
|
||||||
*/
|
|
||||||
val entities = ReferenceLinkedOpenHashSet<Entity>()
|
val entities = ReferenceLinkedOpenHashSet<Entity>()
|
||||||
|
|
||||||
val objects = ReferenceLinkedOpenHashSet<WorldObject>()
|
val objects = ReferenceLinkedOpenHashSet<WorldObject>()
|
||||||
|
|
||||||
protected abstract fun chunkFactory(pos: ChunkPos): ChunkType
|
protected abstract fun chunkFactory(pos: ChunkPos): ChunkType
|
||||||
@ -285,6 +304,48 @@ abstract class World<This : World<This, ChunkType>, ChunkType : Chunk<This, Chun
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
private val POLY_VERTICES: ImmutableList<Vector2d> = 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<IntList> = 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 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)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,10 @@ import ru.dbotthepony.kstarbound.world.physics.CollisionPoly
|
|||||||
import ru.dbotthepony.kstarbound.world.physics.CollisionType
|
import ru.dbotthepony.kstarbound.world.physics.CollisionType
|
||||||
import ru.dbotthepony.kstarbound.world.physics.Poly
|
import ru.dbotthepony.kstarbound.world.physics.Poly
|
||||||
import ru.dbotthepony.kvector.util2d.AABB
|
import ru.dbotthepony.kvector.util2d.AABB
|
||||||
|
import ru.dbotthepony.kvector.vector.RGBAColor
|
||||||
import ru.dbotthepony.kvector.vector.Vector2d
|
import ru.dbotthepony.kvector.vector.Vector2d
|
||||||
import java.util.EnumSet
|
import java.util.EnumSet
|
||||||
|
import kotlin.concurrent.withLock
|
||||||
|
|
||||||
abstract class Entity(val world: World<*, *>) {
|
abstract class Entity(val world: World<*, *>) {
|
||||||
var chunk: Chunk<*, *>? = null
|
var chunk: Chunk<*, *>? = null
|
||||||
@ -35,14 +37,16 @@ abstract class Entity(val world: World<*, *>) {
|
|||||||
val oldChunk = field
|
val oldChunk = field
|
||||||
field = value
|
field = value
|
||||||
|
|
||||||
if (oldChunk == null && value != null) {
|
world.entityListsLock.withLock {
|
||||||
world.orphanedEntities.remove(this)
|
if (oldChunk == null && value != null) {
|
||||||
value.addEntity(this)
|
world.orphanedEntities.remove(this)
|
||||||
} else if (oldChunk != null && value == null) {
|
value.addEntity(this)
|
||||||
world.orphanedEntities.add(this)
|
} else if (oldChunk != null && value == null) {
|
||||||
oldChunk.removeEntity(this)
|
world.orphanedEntities.add(this)
|
||||||
} else if (oldChunk != null && value != null) {
|
oldChunk.removeEntity(this)
|
||||||
value.transferEntity(this, oldChunk)
|
} 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
|
* this function is executed sequentially
|
||||||
*/
|
*/
|
||||||
fun think() {
|
open fun thinkShared() {
|
||||||
if (!isSpawned) {
|
|
||||||
throw IllegalStateException("Tried to think before spawning in world")
|
|
||||||
}
|
|
||||||
|
|
||||||
mailbox.executeQueuedTasks()
|
mailbox.executeQueuedTasks()
|
||||||
thinkInner()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract fun thinkInner()
|
open fun thinkClient() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun thinkServer() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this function is executed in parallel
|
* this function is executed in parallel
|
||||||
@ -146,6 +151,12 @@ abstract class Entity(val world: World<*, *>) {
|
|||||||
var physicsSleepTicks = physicsSleepTicks
|
var physicsSleepTicks = physicsSleepTicks
|
||||||
velocity += world.gravity * Starbound.TICK_TIME_ADVANCE
|
velocity += world.gravity * Starbound.TICK_TIME_ADVANCE
|
||||||
|
|
||||||
|
movementParameters.speedLimit.ifPresent {
|
||||||
|
if (velocity.length > it) {
|
||||||
|
velocity = velocity.unitVector * it
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (hitboxes.isEmpty()) {
|
if (hitboxes.isEmpty()) {
|
||||||
position += velocity * Starbound.TICK_TIME_ADVANCE
|
position += velocity * Starbound.TICK_TIME_ADVANCE
|
||||||
return
|
return
|
||||||
@ -161,7 +172,7 @@ abstract class Entity(val world: World<*, *>) {
|
|||||||
val localHitboxes = hitboxes.map { it + position }
|
val localHitboxes = hitboxes.map { it + position }
|
||||||
|
|
||||||
val polies = world.queryCollisions(
|
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 {
|
).filter {
|
||||||
if (collisionFilterMode)
|
if (collisionFilterMode)
|
||||||
it.type in collisionFilter
|
it.type in collisionFilter
|
||||||
@ -211,6 +222,15 @@ abstract class Entity(val world: World<*, *>) {
|
|||||||
|
|
||||||
open fun render(client: StarboundClient = StarboundClient.current()) {
|
open fun render(client: StarboundClient = StarboundClient.current()) {
|
||||||
hitboxes.forEach { (it + position).render(client) }
|
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
|
open var maxHealth = 0.0
|
||||||
@ -222,5 +242,6 @@ abstract class Entity(val world: World<*, *>) {
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val PHYSICS_TICKS_UNTIL_SLEEP = 16
|
const val PHYSICS_TICKS_UNTIL_SLEEP = 16
|
||||||
|
val BLOCK_COLLISION_COLOR = RGBAColor(65, 179, 217)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,9 +10,4 @@ class ItemEntity(world: World<*, *>, val def: IItemDefinition) : Entity(world) {
|
|||||||
init {
|
init {
|
||||||
hitboxes.add(Poly(AABB.rectangle(Vector2d.ZERO, 0.75, 0.75)))
|
hitboxes.add(Poly(AABB.rectangle(Vector2d.ZERO, 0.75, 0.75)))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun thinkInner() {
|
|
||||||
// TODO: деспавнинг?
|
|
||||||
// просто, как бы, предметы не должны уж так сильно нагружать процессор
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@ import ru.dbotthepony.kstarbound.defs.JsonDriven
|
|||||||
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
import ru.dbotthepony.kstarbound.defs.image.SpriteReference
|
||||||
import ru.dbotthepony.kstarbound.defs.`object`.ObjectDefinition
|
import ru.dbotthepony.kstarbound.defs.`object`.ObjectDefinition
|
||||||
import ru.dbotthepony.kstarbound.defs.`object`.ObjectOrientation
|
import ru.dbotthepony.kstarbound.defs.`object`.ObjectOrientation
|
||||||
|
import ru.dbotthepony.kstarbound.util.MailboxExecutorService
|
||||||
import ru.dbotthepony.kstarbound.util.get
|
import ru.dbotthepony.kstarbound.util.get
|
||||||
import ru.dbotthepony.kstarbound.util.set
|
import ru.dbotthepony.kstarbound.util.set
|
||||||
import ru.dbotthepony.kstarbound.world.Side
|
import ru.dbotthepony.kstarbound.world.Side
|
||||||
@ -47,6 +48,8 @@ open class WorldObject(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val mailbox = MailboxExecutorService()
|
||||||
|
|
||||||
//
|
//
|
||||||
// internal runtime properties
|
// internal runtime properties
|
||||||
//
|
//
|
||||||
@ -139,6 +142,7 @@ open class WorldObject(
|
|||||||
}
|
}
|
||||||
|
|
||||||
open fun thinkShared() {
|
open fun thinkShared() {
|
||||||
|
mailbox.executeQueuedTasks()
|
||||||
flickerPeriod?.update(Starbound.TICK_TIME_ADVANCE, world.random)
|
flickerPeriod?.update(Starbound.TICK_TIME_ADVANCE, world.random)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user