From 096a34c6a6d2034471a4ac252fb5dd840f872677 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Wed, 29 Apr 2020 11:26:59 +0900 Subject: [PATCH] implementing working multithreading Terragen to the game --- .../terrarum/modulebasegame/worldgenerator/Terragen.kt | 8 ++++---- .../modulebasegame/worldgenerator/WorldGenerator.kt | 1 + src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt index 5c0ef1def..2df42d031 100644 --- a/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt +++ b/src/net/torvald/terrarum/modulebasegame/worldgenerator/Terragen.kt @@ -18,21 +18,21 @@ import kotlin.math.sin */ class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, params) { - private val genSlices = 1 // world.width / 64 + private val genSlices = world.width / 8 private var genFutures: Array?> = arrayOfNulls(genSlices) override var generationStarted: Boolean = false override val generationDone: Boolean - get() = generationStarted && genFutures.fold(1) { acc, f -> acc * (f?.isDone ?: true).toInt() } == 1 + get() = generationStarted && genFutures.fold(true) { acc, f -> acc and (f?.isDone ?: true) } override fun run() { - val joise = getGenerator(seed, params as TerragenParams) generationStarted = true // single-threaded impl because I couldn't resolve multithread memory corruption issue... (0 until world.width).sliceEvenly(genSlices).mapIndexed { i, xs -> genFutures[i] = ThreadExecutor.submit { + val localJoise = getGenerator(seed, params as TerragenParams) for (x in xs) { for (y in 0 until world.height) { val sampleTheta = (x.toDouble() / world.width) * TWO_PI @@ -40,7 +40,7 @@ class Terragen(world: GameWorld, seed: Long, params: Any) : Gen(world, seed, par val sampleX = sin(sampleTheta) * sampleOffset + sampleOffset // plus sampleOffset to make only val sampleZ = cos(sampleTheta) * sampleOffset + sampleOffset // positive points are to be sampled val sampleY = y.toDouble() - val noise = joise.map { it.get(sampleX, sampleY, sampleZ) } + val noise = localJoise.map { it.get(sampleX, sampleY, sampleZ) } draw(x, y, noise, world) } diff --git a/src/net/torvald/terrarum/modulebasegame/worldgenerator/WorldGenerator.kt b/src/net/torvald/terrarum/modulebasegame/worldgenerator/WorldGenerator.kt index 680c66a77..1c1d341d9 100644 --- a/src/net/torvald/terrarum/modulebasegame/worldgenerator/WorldGenerator.kt +++ b/src/net/torvald/terrarum/modulebasegame/worldgenerator/WorldGenerator.kt @@ -13,6 +13,7 @@ import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.roundInt import java.util.* +@Deprecated("Old non-thread-safe version", ReplaceWith("Terragen", "net.torvald.terrarum.modulebasegame.worldgenerator")) object WorldGenerator { internal lateinit var world: GameWorld diff --git a/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt b/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt index eb5867308..6b918a7c4 100644 --- a/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt +++ b/src/net/torvald/terrarum/tests/WorldgenNoiseSandbox.kt @@ -91,7 +91,7 @@ class WorldgenNoiseSandbox : ApplicationAdapter() { renderNoise() } - val coroutineExecFinished = (coroutineJobs.fold(true) { acc, it -> acc and it.isCompleted }) + val coroutineExecFinished = coroutineJobs.fold(true) { acc, it -> acc and it.isCompleted } // check if generation is done if (coroutineExecFinished) { generateKeyLatched = false