From cac9e947f7a0d34fe536e360c77bbfac888a0570 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Fri, 16 Feb 2024 02:55:36 +0900 Subject: [PATCH] better boom-job juggling --- .../modulebasegame/ExplosionManager.kt | 40 +++++++++++++++++-- .../terrarum/modulebasegame/TerrarumIngame.kt | 12 +++--- .../gameactors/ActorPrimedBomb.kt | 10 ++--- 3 files changed, 49 insertions(+), 13 deletions(-) diff --git a/src/net/torvald/terrarum/modulebasegame/ExplosionManager.kt b/src/net/torvald/terrarum/modulebasegame/ExplosionManager.kt index 345e48af2..4b7be02b0 100644 --- a/src/net/torvald/terrarum/modulebasegame/ExplosionManager.kt +++ b/src/net/torvald/terrarum/modulebasegame/ExplosionManager.kt @@ -1,5 +1,6 @@ package net.torvald.terrarum.modulebasegame +import com.badlogic.gdx.utils.Queue import net.torvald.terrarum.BlockCodex import net.torvald.terrarum.ItemCodex import net.torvald.terrarum.OreCodex @@ -11,12 +12,23 @@ import net.torvald.terrarum.gameworld.fmod import net.torvald.terrarum.gameworld.getOffset import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore import net.torvald.unsafe.UnsafeHelper +import java.util.concurrent.* import kotlin.math.* /** * Created by minjaesong on 2024-02-13. */ object ExplosionManager { + + private val executor = Executors.newSingleThreadExecutor() + private val futures = ArrayList>() + private val runners = ArrayList() + + data class CallableWithState( + val runner: Callable, + var executed: Boolean = false + ) + fun goBoom(world: GameWorld, tx: Int, ty: Int, power: Float, dropProbNonOre: Float, dropProbOre: Float, callback: () -> Unit) { val CALC_RADIUS = power.ceilToInt() + 2 val CALC_WIDTH = CALC_RADIUS * 2 + 1 @@ -31,7 +43,29 @@ object ExplosionManager { memcpyFromWorldBreakage(CALC_WIDTH, world, tx - CALC_RADIUS, ty - CALC_RADIUS, line, breakmap) } - createExplosionWorker(CALC_RADIUS, CALC_WIDTH, world, breakmap, tilemap, tx, ty, power, dropProbNonOre, dropProbOre, callback).start() + val runner = createExplosionWorker(CALC_RADIUS, CALC_WIDTH, world, breakmap, tilemap, tx, ty, power, dropProbNonOre, dropProbOre, callback) +// futures.add(executor.submit(runner)) + + runners.removeIf { it.executed } + runners.add(CallableWithState(runner)) + } + + init { + Thread { + while (true) { + try { + val job = runners.first { !it.executed } + val executor = Executors.newSingleThreadExecutor() + executor.submit(job.runner).get(500L, TimeUnit.MILLISECONDS) + executor.shutdownNow() + job.executed = true + } + catch (_: TimeoutException) { } + catch (_: NoSuchElementException) { } + + Thread.sleep(50L) + } + }.start() } private fun memcpyFromWorldTiles(CALC_RADIUS: Int, CALC_WIDTH: Int, world: GameWorld, xStart: Int, yStart: Int, yOff: Int, out: BlockLayerI16) { @@ -125,8 +159,8 @@ object ExplosionManager { power: Float, dropProbNonOre: Float, dropProbOre: Float, - callback: () -> Unit): Thread - { return Thread { + callback: () -> Unit): Callable + { return Callable { val mapBoomPow = UnsafeFloatArray(CALC_WIDTH, CALC_WIDTH) // explosion power map val mapTileStr = UnsafeFloatArray(CALC_WIDTH, CALC_WIDTH) // the tile strengths val mapTileStr2 = UnsafeFloatArray(CALC_WIDTH, CALC_WIDTH) // the tile strengths diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index 785d59d5b..2241ad0bc 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -876,8 +876,9 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) { repossessActor() // process actor addition requests - actorAdditionQueue.forEach { forceAddActor(it.first, it.second) } - actorAdditionQueue.clear() + val addCueCpy = actorAdditionQueue.toList() + addCueCpy.forEach { forceAddActor(it.first, it.second) } + actorAdditionQueue.removeAll(addCueCpy) // determine whether the inactive actor should be activated wakeDormantActors() // update NOW; allow one last update for the actors flagged to despawn @@ -885,10 +886,11 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) { // determine whether the actor should keep being activated or be dormant killOrKnockdownActors() // process actor removal requests - actorRemovalQueue.forEach { forceRemoveActor(it.first, it.second) } - actorRemovalQueue.clear() + val remCueCpy = actorRemovalQueue.toList() + remCueCpy.forEach { forceRemoveActor(it.first, it.second) } + actorRemovalQueue.removeAll(remCueCpy) // update particles - particlesContainer.forEach { if (!it.flagDespawn) particlesActive++; it.update(delta) } + particlesContainer.toList().forEach { if (!it.flagDespawn) particlesActive++; it.update(delta) } // TODO thread pool(?) CollisionSolver.process() diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/ActorPrimedBomb.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/ActorPrimedBomb.kt index dc7bdbc99..cecd5ac08 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/ActorPrimedBomb.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/ActorPrimedBomb.kt @@ -46,10 +46,6 @@ open class ActorPrimedBomb( if (fuse <= 0f && !explosionCalled) { explosionCalled = true - physProp.usePhysics = false - - this.isVisible = false // or play explosion anim - startAudio(boomSound, 10.0) ExplosionManager.goBoom( INGAME.world, @@ -58,7 +54,11 @@ open class ActorPrimedBomb( explosionPower, dropProbNonOre, dropProbOre - ) {} + ) { + physProp.usePhysics = false + this.isVisible = false // or play explosion anim + startAudio(boomSound, 10.0) + } } }