mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-10 18:44:05 +09:00
commiting minor changes cause I need to track down some bugs
- Text on small font goes dark gradually (?)
This commit is contained in:
1
.idea/libraries/lib.xml
generated
1
.idea/libraries/lib.xml
generated
@@ -19,6 +19,7 @@
|
|||||||
<root url="jar://$PROJECT_DIR$/lib/Terrarum_Joise.jar!/" />
|
<root url="jar://$PROJECT_DIR$/lib/Terrarum_Joise.jar!/" />
|
||||||
<root url="jar://$PROJECT_DIR$/lib/source/gdx-backend-lwjgl-sources.jar!/" />
|
<root url="jar://$PROJECT_DIR$/lib/source/gdx-backend-lwjgl-sources.jar!/" />
|
||||||
<root url="jar://$PROJECT_DIR$/lib/TerrarumSansBitmap.jar!/" />
|
<root url="jar://$PROJECT_DIR$/lib/TerrarumSansBitmap.jar!/" />
|
||||||
|
<root url="jar://$PROJECT_DIR$/lib/kotlin-stdlib-sources.jar!/" />
|
||||||
</SOURCES>
|
</SOURCES>
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib" recursive="false" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib" recursive="false" />
|
||||||
<jarDirectory url="file://$PROJECT_DIR$/lib/source" recursive="false" type="SOURCES" />
|
<jarDirectory url="file://$PROJECT_DIR$/lib/source" recursive="false" type="SOURCES" />
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ object DefaultConfig {
|
|||||||
jsonObject.addProperty("imtooyoungtodie", false) // no perma-death
|
jsonObject.addProperty("imtooyoungtodie", false) // no perma-death
|
||||||
jsonObject.addProperty("language", AppLoader.getSysLang())
|
jsonObject.addProperty("language", AppLoader.getSysLang())
|
||||||
jsonObject.addProperty("notificationshowuptime", 6500)
|
jsonObject.addProperty("notificationshowuptime", 6500)
|
||||||
jsonObject.addProperty("multithread", false) // experimental!
|
jsonObject.addProperty("multithread", true) // experimental!
|
||||||
|
jsonObject.addProperty("multithreadedlight", false) // experimental!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,9 @@ import net.torvald.terrarum.Terrarum
|
|||||||
* Created by minjaesong on 2016-05-25.
|
* Created by minjaesong on 2016-05-25.
|
||||||
*/
|
*/
|
||||||
object ThreadParallel {
|
object ThreadParallel {
|
||||||
private val pool: Array<Thread?> = Array(Terrarum.THREADS, { null })
|
val threads = Terrarum.THREADS // modify this to your taste
|
||||||
|
|
||||||
|
private val pool: Array<Thread?> = Array(threads, { null })
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map Runnable object to certain index of the thread pool.
|
* Map Runnable object to certain index of the thread pool.
|
||||||
@@ -14,18 +16,21 @@ object ThreadParallel {
|
|||||||
* @param runnable
|
* @param runnable
|
||||||
* @param prefix Will name each thread like "Foo-1", "Foo-2", etc.
|
* @param prefix Will name each thread like "Foo-1", "Foo-2", etc.
|
||||||
*/
|
*/
|
||||||
fun map(index: Int, runnable: Runnable, prefix: String) {
|
fun map(index: Int, prefix: String, runnable: Runnable) {
|
||||||
pool[index] = Thread(runnable, "$prefix-$index")
|
pool[index] = Thread(runnable, "$prefix-$index")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun map(index: Int, runFunc: (Int) -> Unit, prefix: String) {
|
/**
|
||||||
|
* @param runFunc A function that takes an int input (the index), and returns nothing
|
||||||
|
*/
|
||||||
|
fun map(index: Int, prefix: String, runFunc: (Int) -> Unit) {
|
||||||
val runnable = object : Runnable {
|
val runnable = object : Runnable {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
runFunc(index)
|
runFunc(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map(index, runnable, prefix)
|
map(index, prefix, runnable)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -50,4 +55,81 @@ object ThreadParallel {
|
|||||||
pool.forEach { if (it?.state != Thread.State.TERMINATED) return false }
|
pool.forEach { if (it?.state != Thread.State.TERMINATED) return false }
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object ParallelUtils {
|
||||||
|
fun <T, R> Iterable<T>.parallelMap(transform: (T) -> R): List<R> {
|
||||||
|
val tasks = this.sliceEvenly(ThreadParallel.threads)
|
||||||
|
val destination = Array(ThreadParallel.threads) { ArrayList<R>() }
|
||||||
|
tasks.forEachIndexed { index, list ->
|
||||||
|
ThreadParallel.map(index, "ParallelUtils.parallelMap@${this.javaClass.canonicalName}") {
|
||||||
|
for (item in list)
|
||||||
|
destination[index].add(transform(item as T))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadParallel.startAllWaitForDie()
|
||||||
|
|
||||||
|
return destination.flatten()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shallow flat of the array
|
||||||
|
*/
|
||||||
|
fun <T> Array<out Iterable<T>>.flatten(): List<T> {
|
||||||
|
val al = ArrayList<T>()
|
||||||
|
this.forEach { it.forEach { al.add(it) } }
|
||||||
|
return al
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shallow flat of the iterable
|
||||||
|
*/
|
||||||
|
fun <T> Iterable<out Iterable<T>>.flatten(): List<T> {
|
||||||
|
val al = ArrayList<T>()
|
||||||
|
this.forEach { it.forEach { al.add(it) } }
|
||||||
|
return al
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shallow flat of the array
|
||||||
|
*/
|
||||||
|
fun <T> Array<out Array<T>>.flatten(): List<T> {
|
||||||
|
val al = ArrayList<T>()
|
||||||
|
this.forEach { it.forEach { al.add(it) } }
|
||||||
|
return al
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Iterable<*>.sliceEvenly(slices: Int): List<List<*>> = this.toList().sliceEvenly(slices)
|
||||||
|
|
||||||
|
fun List<*>.sliceEvenly(slices: Int): List<List<*>> {
|
||||||
|
return (0 until slices).map {
|
||||||
|
this.subList(
|
||||||
|
this.size.toFloat().div(slices).times(it).roundInt(),
|
||||||
|
this.size.toFloat().div(slices).times(it + 1).roundInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Array<*>.sliceEvenly(slices: Int): List<Array<*>> {
|
||||||
|
return (0 until slices).map {
|
||||||
|
this.sliceArray(
|
||||||
|
this.size.toFloat().div(slices).times(it).roundInt() until
|
||||||
|
this.size.toFloat().div(slices).times(it + 1).roundInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IntRange.sliceEvenly(slices: Int): List<IntRange> {
|
||||||
|
if (this.step != 1) throw UnsupportedOperationException("Sorry, step != 1")
|
||||||
|
val size = this.last - this.first + 1f
|
||||||
|
|
||||||
|
return (0 until slices).map {
|
||||||
|
size.div(slices).times(it).roundInt() until
|
||||||
|
size.div(slices).times(it + 1).roundInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private inline fun Float.roundInt(): Int = Math.round(this)
|
||||||
}
|
}
|
||||||
@@ -671,12 +671,11 @@ open class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
// set up indices
|
// set up indices
|
||||||
for (i in 0..Terrarum.THREADS - 1) {
|
for (i in 0..Terrarum.THREADS - 1) {
|
||||||
ThreadParallel.map(
|
ThreadParallel.map(
|
||||||
i,
|
i, "ActorUpdate",
|
||||||
ThreadActorUpdate(
|
ThreadActorUpdate(
|
||||||
actors.div(Terrarum.THREADS).times(i).roundInt(),
|
actors.div(Terrarum.THREADS).times(i).roundInt(),
|
||||||
actors.div(Terrarum.THREADS).times(i.plus(1)).roundInt() - 1
|
actors.div(Terrarum.THREADS).times(i + 1).roundInt() - 1
|
||||||
),
|
)
|
||||||
"ActorUpdate"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -781,13 +781,12 @@ object WorldGenerator {
|
|||||||
// set up indices
|
// set up indices
|
||||||
for (i in 0 until Terrarum.THREADS) {
|
for (i in 0 until Terrarum.THREADS) {
|
||||||
ThreadParallel.map(
|
ThreadParallel.map(
|
||||||
i,
|
i, "SampleJoiseMap",
|
||||||
ThreadProcessNoiseLayers(
|
ThreadProcessNoiseLayers(
|
||||||
HEIGHT.toFloat().div(Terrarum.THREADS).times(i).roundInt(),
|
HEIGHT.toFloat().div(Terrarum.THREADS).times(i).roundInt(),
|
||||||
HEIGHT.toFloat().div(Terrarum.THREADS).times(i.plus(1)).roundInt() - 1,
|
HEIGHT.toFloat().div(Terrarum.THREADS).times(i.plus(1)).roundInt() - 1,
|
||||||
noiseRecords
|
noiseRecords
|
||||||
),
|
)
|
||||||
"SampleJoiseMap"
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -10,14 +10,17 @@ import net.torvald.terrarum.blockproperties.BlockCodex
|
|||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.terrarum.AppLoader.printdbg
|
import net.torvald.terrarum.AppLoader.printdbg
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
|
import net.torvald.terrarum.blendNormal
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.gameactors.*
|
import net.torvald.terrarum.gameactors.*
|
||||||
import net.torvald.terrarum.gameactors.ActorWBMovable
|
import net.torvald.terrarum.gameactors.ActorWBMovable
|
||||||
import net.torvald.terrarum.ceilInt
|
import net.torvald.terrarum.ceilInt
|
||||||
|
import net.torvald.terrarum.concurrent.ThreadParallel
|
||||||
import net.torvald.terrarum.floorInt
|
import net.torvald.terrarum.floorInt
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import java.util.*
|
import net.torvald.terrarum.concurrent.ParallelUtils.sliceEvenly
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
import kotlin.system.measureNanoTime
|
import kotlin.system.measureNanoTime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -148,6 +151,10 @@ object LightmapRenderer {
|
|||||||
|
|
||||||
// TODO in regard of "colour math against integers", take Int
|
// TODO in regard of "colour math against integers", take Int
|
||||||
private fun setLight(x: Int, y: Int, colour: Color) {
|
private fun setLight(x: Int, y: Int, colour: Color) {
|
||||||
|
setLightOf(lightmap, x, y, colour)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setLightOf(list: Array<Color>, x: Int, y: Int, colour: Color) {
|
||||||
if (y - for_y_start + overscan_open in 0 until LIGHTMAP_HEIGHT &&
|
if (y - for_y_start + overscan_open in 0 until LIGHTMAP_HEIGHT &&
|
||||||
x - for_x_start + overscan_open in 0 until LIGHTMAP_WIDTH) {
|
x - for_x_start + overscan_open in 0 until LIGHTMAP_WIDTH) {
|
||||||
|
|
||||||
@@ -155,7 +162,7 @@ object LightmapRenderer {
|
|||||||
val xpos = x - for_x_start + overscan_open
|
val xpos = x - for_x_start + overscan_open
|
||||||
|
|
||||||
//lightmap[ypos][xpos] = colour
|
//lightmap[ypos][xpos] = colour
|
||||||
lightmap[ypos * LIGHTMAP_WIDTH + xpos] = colour
|
list[ypos * LIGHTMAP_WIDTH + xpos] = colour
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,9 +202,9 @@ object LightmapRenderer {
|
|||||||
// Because of inevitable overlaps on the area, it only works with ADDITIVE blend (aka maxblend)
|
// Because of inevitable overlaps on the area, it only works with ADDITIVE blend (aka maxblend)
|
||||||
|
|
||||||
|
|
||||||
// each usually takes 1-3 miliseconds when not threaded
|
// each usually takes 8 000 000..12 000 000 miliseconds total when not threaded
|
||||||
|
|
||||||
if (!Terrarum.getConfigBoolean("multithread")) {
|
if (!Terrarum.getConfigBoolean("multithreadedlight")) {
|
||||||
// Round 1
|
// Round 1
|
||||||
Terrarum.debugTimers["Renderer.Light1"] = measureNanoTime {
|
Terrarum.debugTimers["Renderer.Light1"] = measureNanoTime {
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
for (y in for_y_start - overscan_open..for_y_end) {
|
||||||
@@ -233,13 +240,103 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Terrarum.debugTimers["Renderer.LightSequential"] =
|
||||||
|
Terrarum.debugTimers["Renderer.Light1"]!! +
|
||||||
|
Terrarum.debugTimers["Renderer.Light2"]!! +
|
||||||
|
Terrarum.debugTimers["Renderer.Light3"]!! +
|
||||||
|
Terrarum.debugTimers["Renderer.Light4"]!!
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
TODO()
|
Terrarum.debugTimers["Renderer.LightPre"] = measureNanoTime {
|
||||||
//val bufferForPasses = arrayOf(lightmap.)
|
|
||||||
|
val bufferForPasses = arrayOf(
|
||||||
|
lightmap.copyOf(), lightmap.copyOf(), lightmap.copyOf(), lightmap.copyOf()
|
||||||
|
)
|
||||||
|
//val combiningBuffer = Array(lightmap.size) { Color(0) }
|
||||||
|
|
||||||
|
// this is kind of inefficient...
|
||||||
|
val calcTask = ArrayList<ThreadedLightmapUpdateMessage>()
|
||||||
|
|
||||||
|
// Round 1 preload
|
||||||
|
for (y in for_y_start - overscan_open..for_y_end) {
|
||||||
|
for (x in for_x_start - overscan_open..for_x_end) {
|
||||||
|
calcTask.add(ThreadedLightmapUpdateMessage(x, y, 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round 2 preload
|
||||||
|
for (y in for_y_end + overscan_open downTo for_y_start) {
|
||||||
|
for (x in for_x_start - overscan_open..for_x_end) {
|
||||||
|
calcTask.add(ThreadedLightmapUpdateMessage(x, y, 2))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round 3 preload
|
||||||
|
for (y in for_y_end + overscan_open downTo for_y_start) {
|
||||||
|
for (x in for_x_end + overscan_open downTo for_x_start) {
|
||||||
|
calcTask.add(ThreadedLightmapUpdateMessage(x, y, 3))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round 4 preload
|
||||||
|
for (y in for_y_start - overscan_open..for_y_end) {
|
||||||
|
for (x in for_x_end + overscan_open downTo for_x_start) {
|
||||||
|
calcTask.add(ThreadedLightmapUpdateMessage(x, y, 4))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val calcTasks = calcTask.sliceEvenly(Terrarum.THREADS)
|
||||||
|
val combineTasks = (0 until lightmap.size).sliceEvenly(Terrarum.THREADS)
|
||||||
|
|
||||||
|
|
||||||
|
// couldn't help but do this nested timer
|
||||||
|
|
||||||
|
Terrarum.debugTimers["Renderer.LightParallel${Terrarum.THREADS}x"] = measureNanoTime {
|
||||||
|
calcTasks.forEachIndexed { index, list ->
|
||||||
|
ThreadParallel.map(index, "LightCalculate") { index -> // this index is that index
|
||||||
|
list.forEach {
|
||||||
|
val msg = it as ThreadedLightmapUpdateMessage
|
||||||
|
|
||||||
|
setLightOf(bufferForPasses[it.pass - 1], it.x, it.y, calculate(it.x, it.y, it.pass))
|
||||||
|
//setLightOf(bufferForPasses[it.pass - 1], it.x, it.y, calculate(it.x, it.y, 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadParallel.startAllWaitForDie()
|
||||||
|
}
|
||||||
|
|
||||||
|
Terrarum.debugTimers["Runderer.LightPost"] = measureNanoTime {
|
||||||
|
combineTasks.forEachIndexed { index, intRange ->
|
||||||
|
ThreadParallel.map(index, "LightCombine") { index -> // this index is that index
|
||||||
|
for (i in intRange) {
|
||||||
|
val max1 = bufferForPasses[0][i] maxBlend bufferForPasses[1][i]
|
||||||
|
val max2 = bufferForPasses[2][i] maxBlend bufferForPasses[3][i]
|
||||||
|
val max = max1 maxBlend max2
|
||||||
|
|
||||||
|
lightmap[i] = max
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ThreadParallel.startAllWaitForDie()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// get correct Renderer.LightPre by subtracting some shits
|
||||||
|
Terrarum.debugTimers["Renderer.LightParaTotal"] = Terrarum.debugTimers["Renderer.LightPre"]!!
|
||||||
|
Terrarum.debugTimers["Renderer.LightPre"] =
|
||||||
|
Terrarum.debugTimers["Renderer.LightPre"]!! -
|
||||||
|
Terrarum.debugTimers["Renderer.LightParallel${Terrarum.THREADS}x"]!! -
|
||||||
|
Terrarum.debugTimers["Runderer.LightPost"]!!
|
||||||
|
|
||||||
|
// accuracy may suffer (overheads maybe?) but it doesn't matter (i think...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal data class ThreadedLightmapUpdateMessage(val x: Int, val y: Int, val pass: Int)
|
||||||
|
|
||||||
|
|
||||||
private fun buildLanternmap() {
|
private fun buildLanternmap() {
|
||||||
@@ -282,9 +379,14 @@ object LightmapRenderer {
|
|||||||
private var thisTileOpacity = Color(0f,0f,0f,0f)
|
private var thisTileOpacity = Color(0f,0f,0f,0f)
|
||||||
private var sunLight = Color(0f,0f,0f,0f)
|
private var sunLight = Color(0f,0f,0f,0f)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param pass one-based
|
||||||
|
*/
|
||||||
private fun calculate(x: Int, y: Int, pass: Int): Color = calculate(x, y, pass, false)
|
private fun calculate(x: Int, y: Int, pass: Int): Color = calculate(x, y, pass, false)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param pass one-based
|
||||||
|
*/
|
||||||
private fun calculate(x: Int, y: Int, pass: Int, doNotCalculateAmbient: Boolean): Color {
|
private fun calculate(x: Int, y: Int, pass: Int, doNotCalculateAmbient: Boolean): Color {
|
||||||
// O(9n) == O(n) where n is a size of the map
|
// O(9n) == O(n) where n is a size of the map
|
||||||
// TODO devise multithreading on this
|
// TODO devise multithreading on this
|
||||||
@@ -392,9 +494,9 @@ object LightmapRenderer {
|
|||||||
val this_y_end = for_y_end// + overscan_open
|
val this_y_end = for_y_end// + overscan_open
|
||||||
|
|
||||||
// wipe out beforehand. You DO need this
|
// wipe out beforehand. You DO need this
|
||||||
lightBuffer.blending = Pixmap.Blending.None // gonna overwrite
|
lightBuffer.blending = Pixmap.Blending.None // gonna overwrite (remove this line causes the world to go bit darker)
|
||||||
lightBuffer.setColor(colourNull)
|
lightBuffer.setColor(colourNull)
|
||||||
lightBuffer.fillRectangle(0, 0, lightBuffer.width, lightBuffer.height)
|
lightBuffer.fill()
|
||||||
|
|
||||||
|
|
||||||
// write to colour buffer
|
// write to colour buffer
|
||||||
@@ -443,8 +545,6 @@ object LightmapRenderer {
|
|||||||
batch.draw(_lightBufferAsTex, 0f, 0f, _lightBufferAsTex.width * DRAW_TILE_SIZE, _lightBufferAsTex.height * DRAW_TILE_SIZE)
|
batch.draw(_lightBufferAsTex, 0f, 0f, _lightBufferAsTex.width * DRAW_TILE_SIZE, _lightBufferAsTex.height * DRAW_TILE_SIZE)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun dispose() {
|
fun dispose() {
|
||||||
|
|||||||
Reference in New Issue
Block a user