mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-13 03:54:06 +09:00
code cleanup
This commit is contained in:
@@ -20,7 +20,7 @@ import com.google.gson.JsonObject;
|
|||||||
import com.google.gson.JsonPrimitive;
|
import com.google.gson.JsonPrimitive;
|
||||||
import net.torvald.gdx.graphics.PixmapIO2;
|
import net.torvald.gdx.graphics.PixmapIO2;
|
||||||
import net.torvald.getcpuname.GetCpuName;
|
import net.torvald.getcpuname.GetCpuName;
|
||||||
import net.torvald.terrarum.concurrent.ThreadParallel;
|
import net.torvald.terrarum.concurrent.ThreadExecutor;
|
||||||
import net.torvald.terrarum.controller.GdxControllerAdapter;
|
import net.torvald.terrarum.controller.GdxControllerAdapter;
|
||||||
import net.torvald.terrarum.controller.TerrarumController;
|
import net.torvald.terrarum.controller.TerrarumController;
|
||||||
import net.torvald.terrarum.controller.XinputControllerAdapter;
|
import net.torvald.terrarum.controller.XinputControllerAdapter;
|
||||||
@@ -136,7 +136,7 @@ public class AppLoader implements ApplicationListener {
|
|||||||
public static String renderer = "(a super-fancy virtual photoradiator)";
|
public static String renderer = "(a super-fancy virtual photoradiator)";
|
||||||
public static String rendererVendor = "(aperture science psychovisualcomputation laboratory)";
|
public static String rendererVendor = "(aperture science psychovisualcomputation laboratory)";
|
||||||
|
|
||||||
public static int THREADS = ThreadParallel.INSTANCE.getThreadCount();
|
public static int THREAD_COUNT = ThreadExecutor.INSTANCE.getThreadCount();
|
||||||
public static boolean MULTITHREAD;
|
public static boolean MULTITHREAD;
|
||||||
|
|
||||||
public static final boolean is32BitJVM = !System.getProperty("sun.arch.data.model").contains("64");
|
public static final boolean is32BitJVM = !System.getProperty("sun.arch.data.model").contains("64");
|
||||||
@@ -350,7 +350,7 @@ public class AppLoader implements ApplicationListener {
|
|||||||
System.err.println("Game not started using DEBUG MODE -- current build of the game will display black screen without debug mode");
|
System.err.println("Game not started using DEBUG MODE -- current build of the game will display black screen without debug mode");
|
||||||
}
|
}
|
||||||
// set some more configuration vars
|
// set some more configuration vars
|
||||||
MULTITHREAD = ThreadParallel.INSTANCE.getThreadCount() >= 3 && getConfigBoolean("multithread");
|
MULTITHREAD = THREAD_COUNT >= 3 && getConfigBoolean("multithread");
|
||||||
|
|
||||||
new LwjglApplication(new AppLoader(appConfig), appConfig);
|
new LwjglApplication(new AppLoader(appConfig), appConfig);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1172,8 +1172,8 @@ class Ingame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
ThreadParallel.map(
|
ThreadParallel.map(
|
||||||
i,
|
i,
|
||||||
ThreadActorUpdate(
|
ThreadActorUpdate(
|
||||||
actors.div(Terrarum.THREADS).times(i).roundInt(),
|
actors.div(Terrarum.THREADS).times(i).roundToInt(),
|
||||||
actors.div(Terrarum.THREADS).times(i.plus(1)).roundInt() - 1
|
actors.div(Terrarum.THREADS).times(i.plus(1)).roundToInt() - 1
|
||||||
),
|
),
|
||||||
"ActorUpdate"
|
"ActorUpdate"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import net.torvald.util.CircularArray
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.PrintStream
|
import java.io.PrintStream
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.round
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -333,10 +335,6 @@ inline fun FrameBuffer.inAction(camera: OrthographicCamera?, batch: SpriteBatch?
|
|||||||
batch?.projectionMatrix = camera?.combined
|
batch?.projectionMatrix = camera?.combined
|
||||||
}
|
}
|
||||||
|
|
||||||
fun Float.round(): Float {
|
|
||||||
return Math.round(this).toFloat()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ShapeRenderer alternative for rects
|
// ShapeRenderer alternative for rects
|
||||||
fun SpriteBatch.fillRect(x: Float, y: Float, w: Float, h: Float) {
|
fun SpriteBatch.fillRect(x: Float, y: Float, w: Float, h: Float) {
|
||||||
@@ -506,11 +504,10 @@ fun Float.floor() = FastMath.floor(this).toFloat()
|
|||||||
fun Double.ceilInt() = Math.ceil(this).toInt()
|
fun Double.ceilInt() = Math.ceil(this).toInt()
|
||||||
fun Float.ceil(): Float = FastMath.ceil(this).toFloat()
|
fun Float.ceil(): Float = FastMath.ceil(this).toFloat()
|
||||||
fun Float.ceilInt() = FastMath.ceil(this)
|
fun Float.ceilInt() = FastMath.ceil(this)
|
||||||
|
fun Float.round(): Float = round(this)
|
||||||
fun Double.round() = Math.round(this).toDouble()
|
fun Double.round() = Math.round(this).toDouble()
|
||||||
fun Double.floor() = Math.floor(this)
|
fun Double.floor() = Math.floor(this)
|
||||||
fun Double.ceil() = this.floor() + 1.0
|
fun Double.ceil() = this.floor() + 1.0
|
||||||
@Deprecated("Use kotlin.roundToInt") fun Double.roundInt(): Int = Math.round(this).toInt()
|
|
||||||
@Deprecated("Use kotlin.roundToInt") fun Float.roundInt(): Int = Math.round(this)
|
|
||||||
fun Double.abs() = Math.abs(this)
|
fun Double.abs() = Math.abs(this)
|
||||||
fun Double.sqr() = this * this
|
fun Double.sqr() = this * this
|
||||||
fun Float.sqr() = this * this
|
fun Float.sqr() = this * this
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import net.torvald.terrarum.modulebasegame.ui.UIInventoryFull
|
|||||||
import net.torvald.terrarum.ui.UIItem
|
import net.torvald.terrarum.ui.UIItem
|
||||||
import net.torvald.terrarum.ui.UIItemImageButton
|
import net.torvald.terrarum.ui.UIItemImageButton
|
||||||
import net.torvald.terrarum.ui.UIUtils
|
import net.torvald.terrarum.ui.UIUtils
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2017-10-20.
|
* Created by minjaesong on 2017-10-20.
|
||||||
@@ -45,7 +46,7 @@ class UIItemInventoryCatBar(
|
|||||||
init {
|
init {
|
||||||
// place sub UIs: Image Buttons
|
// place sub UIs: Image Buttons
|
||||||
mainButtons = Array(catArrangement.size) { index ->
|
mainButtons = Array(catArrangement.size) { index ->
|
||||||
val iconPosX = ((buttonGapSize / 2) + index * (catIcons.tileW + buttonGapSize)).roundInt()
|
val iconPosX = ((buttonGapSize / 2) + index * (catIcons.tileW + buttonGapSize)).roundToInt()
|
||||||
val iconPosY = 0
|
val iconPosY = 0
|
||||||
|
|
||||||
UIItemImageButton(
|
UIItemImageButton(
|
||||||
@@ -75,9 +76,9 @@ class UIItemInventoryCatBar(
|
|||||||
|
|
||||||
sideButtons = Array(iconIndex.size) { index ->
|
sideButtons = Array(iconIndex.size) { index ->
|
||||||
val iconPosX = if (index < 2)
|
val iconPosX = if (index < 2)
|
||||||
(relativeStartX + sideButtonsGap + (sideButtonsGap + catIcons.tileW) * index).roundInt()
|
(relativeStartX + sideButtonsGap + (sideButtonsGap + catIcons.tileW) * index).roundToInt()
|
||||||
else
|
else
|
||||||
(relativeStartX + width + 2 * sideButtonsGap + (sideButtonsGap + catIcons.tileW) * index).roundInt()
|
(relativeStartX + width + 2 * sideButtonsGap + (sideButtonsGap + catIcons.tileW) * index).roundToInt()
|
||||||
val iconPosY = 0
|
val iconPosY = 0
|
||||||
|
|
||||||
UIItemImageButton(
|
UIItemImageButton(
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package net.torvald.terrarum.blockstats
|
package net.torvald.terrarum.blockstats
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Color
|
|
||||||
import com.badlogic.gdx.graphics.Pixmap
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
import com.badlogic.gdx.utils.Disposable
|
import com.badlogic.gdx.utils.Disposable
|
||||||
@@ -60,7 +59,7 @@ object MinimapComposer : Disposable {
|
|||||||
private val liveTilesMeta = Array(TILES_IN_X * TILES_IN_Y) { LiveTileMeta(revalidate = true) }
|
private val liveTilesMeta = Array(TILES_IN_X * TILES_IN_Y) { LiveTileMeta(revalidate = true) }
|
||||||
|
|
||||||
private val updaterQueue = Queue<Runnable>(TILES_IN_X * TILES_IN_Y * 2)
|
private val updaterQueue = Queue<Runnable>(TILES_IN_X * TILES_IN_Y * 2)
|
||||||
private var currentThreads = Array(maxOf(1, AppLoader.THREADS.times(2).div(3))) {
|
private var currentThreads = Array(maxOf(1, AppLoader.THREAD_COUNT.times(2).div(3))) {
|
||||||
Thread()
|
Thread()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
137
src/net/torvald/terrarum/concurrent/ThreadExecutor.kt
Normal file
137
src/net/torvald/terrarum/concurrent/ThreadExecutor.kt
Normal file
@@ -0,0 +1,137 @@
|
|||||||
|
package net.torvald.terrarum.concurrent
|
||||||
|
|
||||||
|
import java.util.concurrent.*
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
typealias RunnableFun = () -> Unit
|
||||||
|
/** Int: index of the processing core */
|
||||||
|
typealias ThreadableFun = (Int) -> Unit
|
||||||
|
|
||||||
|
|
||||||
|
object ThreadExecutor {
|
||||||
|
val threadCount = Runtime.getRuntime().availableProcessors() // not using (logicalCores + 1) method; it's often better idea to reserve one extra thread for other jobs in the app
|
||||||
|
private lateinit var executor: ExecutorService// = Executors.newFixedThreadPool(threadCount)
|
||||||
|
val futures = ArrayList<Future<*>>()
|
||||||
|
private var isOpen = true
|
||||||
|
|
||||||
|
var allFinished = true
|
||||||
|
private set
|
||||||
|
|
||||||
|
private fun checkShutdown() {
|
||||||
|
try {
|
||||||
|
if (executor.isTerminated)
|
||||||
|
throw IllegalStateException("Executor terminated, renew the executor service.")
|
||||||
|
if (!isOpen || executor.isShutdown)
|
||||||
|
throw IllegalStateException("Pool is closed, come back when all the threads are terminated.")
|
||||||
|
}
|
||||||
|
catch (e: UninitializedPropertyAccessException) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun renew() {
|
||||||
|
try {
|
||||||
|
if (!executor.isTerminated && !executor.isShutdown) throw IllegalStateException("Pool is still running")
|
||||||
|
}
|
||||||
|
catch (_: UninitializedPropertyAccessException) {}
|
||||||
|
|
||||||
|
executor = Executors.newFixedThreadPool(threadCount)
|
||||||
|
futures.clear()
|
||||||
|
isOpen = true
|
||||||
|
allFinished = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/*fun invokeAll(ts: List<Callable<Unit>>) {
|
||||||
|
checkShutdown()
|
||||||
|
executor.invokeAll(ts)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
fun submit(t: Callable<Unit>) {
|
||||||
|
checkShutdown()
|
||||||
|
futures.add(executor.submit(t))
|
||||||
|
}
|
||||||
|
fun submitAll(ts: List<Callable<Unit>>) {
|
||||||
|
checkShutdown()
|
||||||
|
ts.forEach { futures.add(executor.submit(it)) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://stackoverflow.com/questions/28818494/threads-stopping-prematurely-for-certain-values
|
||||||
|
fun join() {
|
||||||
|
println("ThreadExecutor.join")
|
||||||
|
isOpen = false
|
||||||
|
futures.forEach {
|
||||||
|
try {
|
||||||
|
it.get()
|
||||||
|
}
|
||||||
|
catch (e: ExecutionException) {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
executor.shutdown() // thread status of completed ones will be WAIT instead of TERMINATED without this line...
|
||||||
|
executor.awaitTermination(24L, TimeUnit.HOURS)
|
||||||
|
allFinished = true
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 <T> Iterable<T>.sliceEvenly(slices: Int): List<List<T>> = this.toList().sliceEvenly(slices)
|
||||||
|
|
||||||
|
fun <T> List<T>.sliceEvenly(slices: Int): List<List<T>> {
|
||||||
|
return (0 until slices).map {
|
||||||
|
this.subList(
|
||||||
|
this.size.toFloat().div(slices).times(it).roundToInt(),
|
||||||
|
this.size.toFloat().div(slices).times(it + 1).roundToInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> Array<T>.sliceEvenly(slices: Int): List<Array<T>> {
|
||||||
|
return (0 until slices).map {
|
||||||
|
this.sliceArray(
|
||||||
|
this.size.toFloat().div(slices).times(it).roundToInt() until
|
||||||
|
this.size.toFloat().div(slices).times(it + 1).roundToInt()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun IntProgression.sliceEvenly(slices: Int): List<IntProgression> {
|
||||||
|
if (this.step.absoluteValue != 1) throw UnsupportedOperationException("Sorry, step != +1/-1")
|
||||||
|
val size = (this.last - this.first).absoluteValue + (this.step.toFloat()).absoluteValue
|
||||||
|
|
||||||
|
// println(size)
|
||||||
|
|
||||||
|
return if (this.first < this.last) (0 until slices).map {
|
||||||
|
this.first + size.div(slices).times(it).roundToInt() ..
|
||||||
|
this.first + size.div(slices).times(it + 1).roundToInt() - 1
|
||||||
|
}
|
||||||
|
else (0 until slices).map {
|
||||||
|
this.first - size.div(slices).times(it).roundToInt() downTo
|
||||||
|
this.first - size.div(slices).times(it + 1).roundToInt() + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,284 +0,0 @@
|
|||||||
package net.torvald.terrarum.concurrent
|
|
||||||
|
|
||||||
import java.util.concurrent.*
|
|
||||||
import kotlin.math.absoluteValue
|
|
||||||
|
|
||||||
typealias RunnableFun = () -> Unit
|
|
||||||
/** Int: index of the processing core */
|
|
||||||
typealias ThreadableFun = (Int) -> Unit
|
|
||||||
|
|
||||||
|
|
||||||
object ThreadExecutor {
|
|
||||||
val threadCount = Runtime.getRuntime().availableProcessors() // not using (logicalCores + 1) method; it's often better idea to reserve one extra thread for other jobs in the app
|
|
||||||
private lateinit var executor: ExecutorService// = Executors.newFixedThreadPool(threadCount)
|
|
||||||
val futures = ArrayList<Future<*>>()
|
|
||||||
private var isOpen = true
|
|
||||||
|
|
||||||
private fun checkShutdown() {
|
|
||||||
try {
|
|
||||||
if (executor.isTerminated)
|
|
||||||
throw IllegalStateException("Executor terminated, renew the executor service.")
|
|
||||||
if (!isOpen || executor.isShutdown)
|
|
||||||
throw IllegalStateException("Pool is closed, come back when all the threads are terminated.")
|
|
||||||
}
|
|
||||||
catch (e: UninitializedPropertyAccessException) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun renew() {
|
|
||||||
try {
|
|
||||||
if (!executor.isTerminated && !executor.isShutdown) throw IllegalStateException("Pool is still running")
|
|
||||||
}
|
|
||||||
catch (_: UninitializedPropertyAccessException) {}
|
|
||||||
|
|
||||||
executor = Executors.newFixedThreadPool(threadCount)
|
|
||||||
futures.clear()
|
|
||||||
isOpen = true
|
|
||||||
}
|
|
||||||
|
|
||||||
/*fun invokeAll(ts: List<Callable<Unit>>) {
|
|
||||||
checkShutdown()
|
|
||||||
executor.invokeAll(ts)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
fun submit(t: Callable<Unit>) {
|
|
||||||
checkShutdown()
|
|
||||||
val fut = executor.submit(t)
|
|
||||||
futures.add(fut)
|
|
||||||
}
|
|
||||||
/*fun submit(f: RunnableFun) {
|
|
||||||
checkShutdown()
|
|
||||||
val fut = executor.submit { f() }
|
|
||||||
futures.add(fut)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/28818494/threads-stopping-prematurely-for-certain-values
|
|
||||||
fun join() {
|
|
||||||
println("ThreadExecutor.join")
|
|
||||||
isOpen = false
|
|
||||||
futures.forEach {
|
|
||||||
try {
|
|
||||||
it.get()
|
|
||||||
}
|
|
||||||
catch (e: ExecutionException) {
|
|
||||||
throw e
|
|
||||||
}
|
|
||||||
}
|
|
||||||
executor.shutdown() // thread status of completed ones will be WAIT instead of TERMINATED without this line...
|
|
||||||
executor.awaitTermination(24L, TimeUnit.HOURS)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by minjaesong on 2016-05-25.
|
|
||||||
*/
|
|
||||||
@Deprecated("Hooey implementation", ReplaceWith("ThreadExecutor", "net.torvald.terrarum.concurrent.ThreadExecutor"))
|
|
||||||
object ThreadParallel {
|
|
||||||
val threadCount = Runtime.getRuntime().availableProcessors() // not using (logicalCores + 1) method; it's often better idea to reserve one extra thread for other jobs in the app
|
|
||||||
|
|
||||||
private val pool: Array<Thread?> = Array(threadCount) { null }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Map Runnable object to certain index of the thread pool.
|
|
||||||
* @param index of the runnable
|
|
||||||
* @param runnable
|
|
||||||
* @param prefix Will name each thread like "Foo-1", "Foo-2", etc.
|
|
||||||
*/
|
|
||||||
fun map(index: Int, prefix: String, runnable: Runnable) {
|
|
||||||
pool[index] = Thread(runnable, "$prefix-$index")
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param runFunc A function that takes an int input (the index), and returns nothing
|
|
||||||
*/
|
|
||||||
fun map(index: Int, prefix: String, runFunc: ThreadableFun) {
|
|
||||||
val runnable = object : Runnable {
|
|
||||||
override fun run() {
|
|
||||||
runFunc(index)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
map(index, prefix, runnable)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start all thread in the pool. If the thread in the pool is NULL, it will simply ignored.
|
|
||||||
*/
|
|
||||||
fun startAll() {
|
|
||||||
pool.forEach { it?.start() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Start all thread in the pool and wait for them to all die. If the thread in the pool is NULL, it will simply ignored.
|
|
||||||
*/
|
|
||||||
fun startAllWaitForDie() {
|
|
||||||
// ThreadParallelTester says this function actually works as intended...
|
|
||||||
pool.forEach { it?.start() }
|
|
||||||
pool.forEach { it?.join() }
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Primitive locking
|
|
||||||
*/
|
|
||||||
fun allFinished(): Boolean {
|
|
||||||
pool.forEach { if (it != null && it.state != Thread.State.TERMINATED) return false }
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A thread pool that will hold the execution until all the tasks are completed.
|
|
||||||
*
|
|
||||||
* Tasks are not guaranteed to be done orderly; but the first task in the list will be executed first.
|
|
||||||
*/
|
|
||||||
@Deprecated("Experimental.", ReplaceWith("ThreadParallel", "net.torvald.terrarum.concurrent.ThreadParallel"))
|
|
||||||
object BlockingThreadPool {
|
|
||||||
val threadCount = Runtime.getRuntime().availableProcessors() + 1 // modify this to your taste
|
|
||||||
private val pool: Array<Thread?> = Array(threadCount, { null })
|
|
||||||
private var tasks: List<RunnableFun> = ArrayList<RunnableFun>()
|
|
||||||
@Volatile private var dispatchedTasks = 0
|
|
||||||
private var threadPrefix = ""
|
|
||||||
|
|
||||||
/** @return false on failure (likely the previous jobs not finished), true on success */
|
|
||||||
fun map(prefix: String, tasks: List<RunnableFun>) = setTasks(tasks, prefix)
|
|
||||||
/** @return false on failure (likely the previous jobs not finished), true on success */
|
|
||||||
fun setTasks(tasks: List<RunnableFun>, prefix: String): Boolean {
|
|
||||||
if (!allFinished())
|
|
||||||
return false
|
|
||||||
|
|
||||||
this.tasks = tasks
|
|
||||||
dispatchedTasks = 0
|
|
||||||
threadPrefix = prefix
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun dequeueTask(): RunnableFun {
|
|
||||||
dispatchedTasks += 1
|
|
||||||
return tasks[dispatchedTasks - 1]
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun startAllWaitForDie() {
|
|
||||||
while (dispatchedTasks <= tasks.lastIndex) {
|
|
||||||
// marble rolling down the slanted channel-track of threads, if a channel is empty (a task assigned
|
|
||||||
// to the thread is dead) the marble will roll into the channel, and the marble is a task #MarbleMachineX
|
|
||||||
for (i in 0 until threadCount) {
|
|
||||||
// but unlike the marble machine, marble don't actually roll down, we can just pick up any number
|
|
||||||
// of marbles and put it into an empty channel whenever we encounter one
|
|
||||||
|
|
||||||
// SO WHAT WE DO is first fill any empty channels:
|
|
||||||
if (dispatchedTasks <= tasks.lastIndex && // because cache invalidation damnit
|
|
||||||
(pool[i] == null || pool[i]!!.state == Thread.State.TERMINATED)) {
|
|
||||||
pool[i] = Thread(dequeueTask().makeRunnable(), "$threadPrefix-$dispatchedTasks") // thread name index is one-based
|
|
||||||
pool[i]!!.start()
|
|
||||||
}
|
|
||||||
|
|
||||||
// then, sleep this very thread, wake if any of the thread in the pool is terminated,
|
|
||||||
// and GOTO loop_start; if we don't sleep, this function will be busy-waiting
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun allFinished(): Boolean {
|
|
||||||
pool.forEach { if (it != null && it.state != Thread.State.TERMINATED) return false }
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun RunnableFun.makeRunnable() = Runnable {
|
|
||||||
this.invoke()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun <T, R> Iterable<T>.parallelMap(transform: (T) -> R): List<R> {
|
|
||||||
val tasks = this.sliceEvenly(ThreadParallel.threadCount)
|
|
||||||
val destination = Array(ThreadParallel.threadCount) { 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 <T> Iterable<T>.sliceEvenly(slices: Int): List<List<T>> = this.toList().sliceEvenly(slices)
|
|
||||||
|
|
||||||
fun <T> List<T>.sliceEvenly(slices: Int): List<List<T>> {
|
|
||||||
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 <T> Array<T>.sliceEvenly(slices: Int): List<Array<T>> {
|
|
||||||
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 IntProgression.sliceEvenly(slices: Int): List<IntProgression> {
|
|
||||||
if (this.step.absoluteValue != 1) throw UnsupportedOperationException("Sorry, step != +1/-1")
|
|
||||||
val size = (this.last - this.first).absoluteValue + (this.step.toFloat()).absoluteValue
|
|
||||||
|
|
||||||
// println(size)
|
|
||||||
|
|
||||||
return if (this.first < this.last) (0 until slices).map {
|
|
||||||
this.first + size.div(slices).times(it).roundInt() ..
|
|
||||||
this.first + size.div(slices).times(it + 1).roundInt() - 1
|
|
||||||
}
|
|
||||||
else (0 until slices).map {
|
|
||||||
this.first - size.div(slices).times(it).roundInt() downTo
|
|
||||||
this.first - size.div(slices).times(it + 1).roundInt() + 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun IntProgression.mapToThreadPoolDirectly(prefix: String, worker: (IntProgression) -> Unit) {
|
|
||||||
this.sliceEvenly(ThreadParallel.threadCount).forEachIndexed { index, intProgression ->
|
|
||||||
val workerFun: ThreadableFun = {
|
|
||||||
worker(intProgression)
|
|
||||||
}
|
|
||||||
ThreadParallel.map(index, prefix, workerFun)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private inline fun Float.roundInt(): Int = Math.round(this)
|
|
||||||
@@ -20,6 +20,7 @@ import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
|||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.roundToInt
|
||||||
import kotlin.math.sign
|
import kotlin.math.sign
|
||||||
|
|
||||||
|
|
||||||
@@ -1257,28 +1258,28 @@ open class ActorWithBody(renderOrder: RenderOrder, val physProp: PhysProperties)
|
|||||||
if (world == null) return 0
|
if (world == null) return 0
|
||||||
|
|
||||||
var contactAreaCounter = 0
|
var contactAreaCounter = 0
|
||||||
for (i in 0..(if (side % 2 == 0) hitbox.width else hitbox.height).roundInt() - 1) {
|
for (i in 0..(if (side % 2 == 0) hitbox.width else hitbox.height).roundToInt() - 1) {
|
||||||
// set tile positions
|
// set tile positions
|
||||||
val tileX: Int
|
val tileX: Int
|
||||||
val tileY: Int
|
val tileY: Int
|
||||||
if (side == COLLIDING_LEFT) {
|
if (side == COLLIDING_LEFT) {
|
||||||
tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundInt()
|
tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundToInt()
|
||||||
+ i + translateX)
|
+ i + translateX)
|
||||||
tileY = div16TruncateToMapHeight(hitbox.hitboxEnd.y.roundInt() + translateY)
|
tileY = div16TruncateToMapHeight(hitbox.hitboxEnd.y.roundToInt() + translateY)
|
||||||
}
|
}
|
||||||
else if (side == COLLIDING_TOP) {
|
else if (side == COLLIDING_TOP) {
|
||||||
tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundInt()
|
tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundToInt()
|
||||||
+ i + translateX)
|
+ i + translateX)
|
||||||
tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundInt() + translateY)
|
tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundToInt() + translateY)
|
||||||
}
|
}
|
||||||
else if (side == COLLIDING_RIGHT) {
|
else if (side == COLLIDING_RIGHT) {
|
||||||
tileX = div16TruncateToMapWidth(hitbox.hitboxEnd.x.roundInt() + translateX)
|
tileX = div16TruncateToMapWidth(hitbox.hitboxEnd.x.roundToInt() + translateX)
|
||||||
tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundInt()
|
tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundToInt()
|
||||||
+ i + translateY)
|
+ i + translateY)
|
||||||
}
|
}
|
||||||
else if (side == COLLIDING_LEFT) {
|
else if (side == COLLIDING_LEFT) {
|
||||||
tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundInt() + translateX)
|
tileX = div16TruncateToMapWidth(hitbox.hitboxStart.x.roundToInt() + translateX)
|
||||||
tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundInt()
|
tileY = div16TruncateToMapHeight(hitbox.hitboxStart.y.roundToInt()
|
||||||
+ i + translateY)
|
+ i + translateY)
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ import net.torvald.terrarum.AppLoader.printdbg
|
|||||||
import net.torvald.terrarum.blockproperties.BlockPropUtil
|
import net.torvald.terrarum.blockproperties.BlockPropUtil
|
||||||
import net.torvald.terrarum.blockstats.BlockStats
|
import net.torvald.terrarum.blockstats.BlockStats
|
||||||
import net.torvald.terrarum.blockstats.MinimapComposer
|
import net.torvald.terrarum.blockstats.MinimapComposer
|
||||||
import net.torvald.terrarum.concurrent.ThreadParallel
|
import net.torvald.terrarum.concurrent.ThreadExecutor
|
||||||
import net.torvald.terrarum.console.Authenticator
|
import net.torvald.terrarum.console.Authenticator
|
||||||
import net.torvald.terrarum.gameactors.Actor
|
import net.torvald.terrarum.gameactors.Actor
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
@@ -37,6 +37,7 @@ import net.torvald.terrarum.worlddrawer.WorldCamera
|
|||||||
import net.torvald.util.CircularArray
|
import net.torvald.util.CircularArray
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import java.util.concurrent.locks.ReentrantLock
|
import java.util.concurrent.locks.ReentrantLock
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -719,19 +720,20 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
|
|||||||
*/
|
*/
|
||||||
fun updateActors(delta: Float) {
|
fun updateActors(delta: Float) {
|
||||||
if (false) { // don't multithread this for now, it's SLOWER //if (Terrarum.MULTITHREAD && actorContainerActive.size > Terrarum.THREADS) {
|
if (false) { // don't multithread this for now, it's SLOWER //if (Terrarum.MULTITHREAD && actorContainerActive.size > Terrarum.THREADS) {
|
||||||
|
ThreadExecutor.renew()
|
||||||
|
|
||||||
val actors = actorContainerActive.size.toFloat()
|
val actors = actorContainerActive.size.toFloat()
|
||||||
// set up indices
|
// set up indices
|
||||||
for (i in 0..AppLoader.THREADS - 1) {
|
for (i in 0..AppLoader.THREAD_COUNT - 1) {
|
||||||
ThreadParallel.map(
|
ThreadExecutor.submit(
|
||||||
i, "ActorUpdate",
|
|
||||||
ThreadActorUpdate(
|
ThreadActorUpdate(
|
||||||
actors.div(AppLoader.THREADS).times(i).roundInt(),
|
actors.div(AppLoader.THREAD_COUNT).times(i).roundToInt(),
|
||||||
actors.div(AppLoader.THREADS).times(i + 1).roundInt() - 1
|
actors.div(AppLoader.THREAD_COUNT).times(i + 1).roundToInt() - 1
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
ThreadParallel.startAll()
|
ThreadExecutor.join()
|
||||||
|
|
||||||
actorNowPlaying?.update(delta)
|
actorNowPlaying?.update(delta)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import net.torvald.terrarum.ui.UICanvas
|
|||||||
import net.torvald.terrarum.ui.UIItemImageButton
|
import net.torvald.terrarum.ui.UIItemImageButton
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
import org.dyn4j.geometry.Vector2
|
import org.dyn4j.geometry.Vector2
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2019-02-16.
|
* Created by minjaesong on 2019-02-16.
|
||||||
@@ -57,8 +58,8 @@ class UIBuildingMakerPenMenu(val parent: BuildingMaker): UICanvas() {
|
|||||||
backgroundCol = Color(0),
|
backgroundCol = Color(0),
|
||||||
highlightBackCol = Color(0),
|
highlightBackCol = Color(0),
|
||||||
activeBackCol = Color(0),
|
activeBackCol = Color(0),
|
||||||
initialX = newvec.x.roundInt(),
|
initialX = newvec.x.roundToInt(),
|
||||||
initialY = newvec.y.roundInt(),
|
initialY = newvec.y.roundToInt(),
|
||||||
width = ICON_SIZE, height = ICON_SIZE,
|
width = ICON_SIZE, height = ICON_SIZE,
|
||||||
highlightable = false
|
highlightable = false
|
||||||
)
|
)
|
||||||
@@ -154,8 +155,8 @@ class UIBuildingMakerPenMenu(val parent: BuildingMaker): UICanvas() {
|
|||||||
batch.color = blockCellCol
|
batch.color = blockCellCol
|
||||||
val slotConfig = AppLoader.getConfigIntArray("buildingmakerfavs")
|
val slotConfig = AppLoader.getConfigIntArray("buildingmakerfavs")
|
||||||
for (i in 0 until PALETTE_SIZE) {
|
for (i in 0 until PALETTE_SIZE) {
|
||||||
val x = blockCellPos[i].x.roundInt().toFloat()
|
val x = blockCellPos[i].x.roundToInt().toFloat()
|
||||||
val y = blockCellPos[i].y.roundInt().toFloat()
|
val y = blockCellPos[i].y.roundToInt().toFloat()
|
||||||
batch.color = blockCellCol
|
batch.color = blockCellCol
|
||||||
repeat((i == mouseOnBlocksSlot).toInt() + 1) { batch.fillCircle(x - BLOCK_BACK_RADIUS, y - BLOCK_BACK_RADIUS, BLOCK_BACK_SIZE.toFloat(), BLOCK_BACK_SIZE.toFloat()) }
|
repeat((i == mouseOnBlocksSlot).toInt() + 1) { batch.fillCircle(x - BLOCK_BACK_RADIUS, y - BLOCK_BACK_RADIUS, BLOCK_BACK_SIZE.toFloat(), BLOCK_BACK_SIZE.toFloat()) }
|
||||||
batch.color = Color.WHITE
|
batch.color = Color.WHITE
|
||||||
|
|||||||
@@ -3,12 +3,13 @@ package net.torvald.terrarum.modulebasegame.gameactors
|
|||||||
import net.torvald.terrarum.AppLoader
|
import net.torvald.terrarum.AppLoader
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||||
|
import java.util.concurrent.Callable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2016-05-25.
|
* Created by minjaesong on 2016-05-25.
|
||||||
*/
|
*/
|
||||||
class ThreadActorUpdate(val startIndex: Int, val endIndex: Int) : Runnable {
|
class ThreadActorUpdate(val startIndex: Int, val endIndex: Int) : Callable<Unit> {
|
||||||
override fun run() {
|
override fun call() {
|
||||||
for (i in startIndex..endIndex) {
|
for (i in startIndex..endIndex) {
|
||||||
val it = Terrarum.ingame!!.actorContainerActive[i]
|
val it = Terrarum.ingame!!.actorContainerActive[i]
|
||||||
it.update(AppLoader.UPDATE_RATE)
|
it.update(AppLoader.UPDATE_RATE)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
|
|||||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
||||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.TILE_SIZE
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.TILE_SIZE
|
||||||
import org.khelekore.prtree.*
|
import org.khelekore.prtree.*
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2016-08-03.
|
* Created by minjaesong on 2016-08-03.
|
||||||
@@ -77,8 +78,8 @@ object WorldSimulator {
|
|||||||
//printdbg(this, "============================")
|
//printdbg(this, "============================")
|
||||||
|
|
||||||
if (player != null) {
|
if (player != null) {
|
||||||
updateXFrom = player.hitbox.centeredX.div(CreateTileAtlas.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt()
|
updateXFrom = player.hitbox.centeredX.div(CreateTileAtlas.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundToInt()
|
||||||
updateYFrom = player.hitbox.centeredY.div(CreateTileAtlas.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundInt()
|
updateYFrom = player.hitbox.centeredY.div(CreateTileAtlas.TILE_SIZE).minus(FLUID_UPDATING_SQUARE_RADIUS).roundToInt()
|
||||||
updateXTo = updateXFrom + DOUBLE_RADIUS
|
updateXTo = updateXFrom + DOUBLE_RADIUS
|
||||||
updateYTo = updateYFrom + DOUBLE_RADIUS
|
updateYTo = updateYFrom + DOUBLE_RADIUS
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import net.torvald.terrarum.modulebasegame.gameworld.WorldTime
|
|||||||
import net.torvald.terrarum.modulebasegame.imagefont.WatchFont
|
import net.torvald.terrarum.modulebasegame.imagefont.WatchFont
|
||||||
import net.torvald.terrarum.ui.UICanvas
|
import net.torvald.terrarum.ui.UICanvas
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2017-06-11.
|
* Created by minjaesong on 2017-06-11.
|
||||||
@@ -88,7 +89,7 @@ class UITierOneWatch(private val player: ActorHumanoid?) : UICanvas() {
|
|||||||
|
|
||||||
|
|
||||||
// moon dial
|
// moon dial
|
||||||
val moonPhase = (worldTime.moonPhase * moonDialCount).roundInt() % moonDialCount
|
val moonPhase = (worldTime.moonPhase * moonDialCount).roundToInt() % moonDialCount
|
||||||
batch.color = lcdLitCol
|
batch.color = lcdLitCol
|
||||||
batch.draw(moonDial.get(moonPhase, 0), 6f, 3f)
|
batch.draw(moonDial.get(moonPhase, 0), 6f, 3f)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ import net.torvald.terrarum.modulebasegame.RNGConsumer
|
|||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.modulebasegame.gameactors.ParticleMegaRain
|
import net.torvald.terrarum.modulebasegame.gameactors.ParticleMegaRain
|
||||||
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
import net.torvald.terrarum.modulebasegame.gameworld.GameWorldExtension
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.WorldGenerator
|
|
||||||
import net.torvald.terrarum.utils.JsonFetcher
|
import net.torvald.terrarum.utils.JsonFetcher
|
||||||
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
import net.torvald.terrarum.worlddrawer.CreateTileAtlas
|
||||||
import net.torvald.terrarum.worlddrawer.WorldCamera
|
import net.torvald.terrarum.worlddrawer.WorldCamera
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.worldgenerator
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by minjaesong on 2016-03-31.
|
|
||||||
*/
|
|
||||||
interface NoiseFilter {
|
|
||||||
fun getGrad(func_argX: Int, start: Double, end: Double): Double
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.worldgenerator
|
|
||||||
|
|
||||||
import com.jme3.math.FastMath
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Double Quadratic polynomial
|
|
||||||
* (16/9) * (start-end)/height^2 * (x-height)^2 + end
|
|
||||||
* 16/9: terrain is formed from 1/4 of height.
|
|
||||||
* 1 - (1/4) = 3/4, reverse it and square it.
|
|
||||||
* That makes 16/9.
|
|
||||||
|
|
||||||
* Shape:
|
|
||||||
|
|
||||||
* cavity -
|
|
||||||
* small
|
|
||||||
* -
|
|
||||||
* -
|
|
||||||
* --
|
|
||||||
* ----
|
|
||||||
* cavity --------
|
|
||||||
* large ----------------
|
|
||||||
|
|
||||||
* @param func_argX
|
|
||||||
* *
|
|
||||||
* @param start
|
|
||||||
* *
|
|
||||||
* @param end
|
|
||||||
* *
|
|
||||||
* @return
|
|
||||||
* Created by minjaesong on 2016-03-31.
|
|
||||||
*/
|
|
||||||
object NoiseFilterCubic : NoiseFilter {
|
|
||||||
override fun getGrad(func_argX: Int, start: Double, end: Double): Double {
|
|
||||||
val graph_gradient = -FastMath.pow(FastMath.pow((1 - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat(), 3f), -1f) * // 1/4 -> 3/4 -> 9/16 -> 16/9
|
|
||||||
(start - end) / FastMath.pow(WorldGenerator.HEIGHT.toFloat(), 3f) *
|
|
||||||
FastMath.pow((func_argX - WorldGenerator.HEIGHT).toFloat(), 3f) + end
|
|
||||||
|
|
||||||
if (func_argX < WorldGenerator.TERRAIN_AVERAGE_HEIGHT) {
|
|
||||||
return start
|
|
||||||
} else if (func_argX >= WorldGenerator.HEIGHT) {
|
|
||||||
return end
|
|
||||||
} else {
|
|
||||||
return graph_gradient
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.worldgenerator
|
|
||||||
|
|
||||||
import com.jme3.math.FastMath
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Quadratic polynomial
|
|
||||||
* -(16/9) * (start-end)/height^2 * (x - 0.25 * height)^2 + start
|
|
||||||
* 16/9: terrain is formed from 1/4 of height.
|
|
||||||
* 1 - (1/4) = 3/4, reverse it and square it.
|
|
||||||
* That makes 16/9.
|
|
||||||
|
|
||||||
* Shape:
|
|
||||||
|
|
||||||
* cavity _
|
|
||||||
* small
|
|
||||||
* _
|
|
||||||
* _
|
|
||||||
* __
|
|
||||||
* ____
|
|
||||||
* cavity ________
|
|
||||||
* large ________________
|
|
||||||
|
|
||||||
* @param func_argX
|
|
||||||
* *
|
|
||||||
* @param start
|
|
||||||
* *
|
|
||||||
* @param end
|
|
||||||
* *
|
|
||||||
* @return
|
|
||||||
* Created by minjaesong on 2016-03-31.
|
|
||||||
*/
|
|
||||||
object NoiseFilterMinusQuadratic : NoiseFilter {
|
|
||||||
override fun getGrad(func_argX: Int, start: Double, end: Double): Double {
|
|
||||||
val graph_gradient = -FastMath.pow(FastMath.sqr((1 - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat()), -1f) * // 1/4 -> 3/4 -> 9/16 -> 16/9
|
|
||||||
(start - end) / FastMath.sqr(WorldGenerator.HEIGHT.toFloat()) *
|
|
||||||
FastMath.sqr((func_argX - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat()) + start
|
|
||||||
|
|
||||||
if (func_argX < WorldGenerator.TERRAIN_AVERAGE_HEIGHT) {
|
|
||||||
return start
|
|
||||||
} else if (func_argX >= WorldGenerator.HEIGHT) {
|
|
||||||
return end
|
|
||||||
} else {
|
|
||||||
return graph_gradient
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.worldgenerator
|
|
||||||
|
|
||||||
import com.jme3.math.FastMath
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Quadratic polynomial
|
|
||||||
* (16/9) * (start-end)/height^2 * (x-height)^2 + end
|
|
||||||
* 16/9: terrain is formed from 1/4 of height.
|
|
||||||
* 1 - (1/4) = 3/4, reverse it and square it.
|
|
||||||
* That makes 16/9.
|
|
||||||
|
|
||||||
* Shape:
|
|
||||||
|
|
||||||
* cavity -
|
|
||||||
* small
|
|
||||||
* -
|
|
||||||
* -
|
|
||||||
* --
|
|
||||||
* ----
|
|
||||||
* cavity --------
|
|
||||||
* large ----------------
|
|
||||||
|
|
||||||
* @param func_argX
|
|
||||||
* *
|
|
||||||
* @param start
|
|
||||||
* *
|
|
||||||
* @param end
|
|
||||||
* *
|
|
||||||
* @return
|
|
||||||
*
|
|
||||||
* Created by minjaesong on 2016-03-31.
|
|
||||||
*/
|
|
||||||
object NoiseFilterQuadratic : NoiseFilter {
|
|
||||||
override fun getGrad(func_argX: Int, start: Double, end: Double): Double {
|
|
||||||
val graph_gradient = FastMath.pow(FastMath.sqr((1 - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat()), -1f) * // 1/4 -> 3/4 -> 9/16 -> 16/9
|
|
||||||
(start - end) / FastMath.sqr(WorldGenerator.HEIGHT.toFloat()) *
|
|
||||||
FastMath.sqr((func_argX - WorldGenerator.HEIGHT).toFloat()) + end
|
|
||||||
|
|
||||||
if (func_argX < WorldGenerator.TERRAIN_AVERAGE_HEIGHT) {
|
|
||||||
return start
|
|
||||||
} else if (func_argX >= WorldGenerator.HEIGHT) {
|
|
||||||
return end
|
|
||||||
} else {
|
|
||||||
return graph_gradient
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.worldgenerator
|
|
||||||
|
|
||||||
import com.jme3.math.FastMath
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by minjaesong on 2016-03-31.
|
|
||||||
*/
|
|
||||||
object NoiseFilterSqrt : NoiseFilter {
|
|
||||||
override fun getGrad(func_argX: Int, start: Double, end: Double): Double {
|
|
||||||
val graph_gradient = (end - start) / FastMath.sqrt((WorldGenerator.HEIGHT - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat()) * FastMath.sqrt((func_argX - WorldGenerator.TERRAIN_AVERAGE_HEIGHT).toFloat()) + start
|
|
||||||
|
|
||||||
if (func_argX < WorldGenerator.TERRAIN_AVERAGE_HEIGHT) {
|
|
||||||
return start
|
|
||||||
} else if (func_argX >= WorldGenerator.HEIGHT) {
|
|
||||||
return end
|
|
||||||
} else {
|
|
||||||
return graph_gradient
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.worldgenerator
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by minjaesong on 2016-03-31.
|
|
||||||
*/
|
|
||||||
object NoiseFilterUniform : NoiseFilter {
|
|
||||||
override fun getGrad(func_argX: Int, start: Double, end: Double): Double {
|
|
||||||
return 1.0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
package net.torvald.terrarum.modulebasegame.worldgenerator
|
|
||||||
|
|
||||||
import net.torvald.terrarum.AppLoader
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Created by minjaesong on 2016-06-13.
|
|
||||||
*/
|
|
||||||
class ThreadProcessNoiseLayers(val startIndex: Int, val endIndex: Int,
|
|
||||||
val noiseRecords: Array<WorldGenerator.TaggedJoise>) : Runnable {
|
|
||||||
|
|
||||||
|
|
||||||
override fun run() {
|
|
||||||
for (record in noiseRecords) {
|
|
||||||
println("[mapgenerator] ${record.message}...")
|
|
||||||
AppLoader.getLoadScreen().addMessage("${record.message}...")
|
|
||||||
|
|
||||||
for (y in startIndex..endIndex) {
|
|
||||||
for (x in 0..WorldGenerator.WIDTH - 1) {
|
|
||||||
// straight-line sampling
|
|
||||||
/*val noise: Float = record.noiseModule.get(
|
|
||||||
x.toDouble() / 48.0, // 48: Fixed value
|
|
||||||
y.toDouble() / 48.0
|
|
||||||
).toFloat()*/
|
|
||||||
// circular sampling
|
|
||||||
// Mapping function:
|
|
||||||
// World(x, y) -> Joise(sin x, y, cos x)
|
|
||||||
val sampleDensity = 48.0 / 2 // 48.0: magic number from old code
|
|
||||||
val sampleTheta = (x.toDouble() / WorldGenerator.WIDTH) * WorldGenerator.TWO_PI
|
|
||||||
val sampleOffset = (WorldGenerator.WIDTH / sampleDensity) / 8.0
|
|
||||||
val sampleX = Math.sin(sampleTheta) * sampleOffset + sampleOffset // plus sampleOffset to make only
|
|
||||||
val sampleZ = Math.cos(sampleTheta) * sampleOffset + sampleOffset // positive points are to be sampled
|
|
||||||
val sampleY = y / sampleDensity
|
|
||||||
val noise: Double = record.noiseModule.get(sampleX, sampleY, sampleZ)
|
|
||||||
|
|
||||||
val fromTerr = record.replaceFromTerrain
|
|
||||||
val fromWall = record.replaceFromWall
|
|
||||||
|
|
||||||
val to: Int = when (record.replaceTo) {
|
|
||||||
// replace to designated tile
|
|
||||||
is Int -> record.replaceTo as Int
|
|
||||||
// replace to randomly selected tile from given array of tile IDs
|
|
||||||
is IntArray -> (record.replaceTo as IntArray)[WorldGenerator.random.nextInt((record.replaceTo as IntArray).size)]
|
|
||||||
else -> throw IllegalArgumentException("[mapgenerator] Unknown replaceTo tile type '${record.replaceTo.javaClass.canonicalName}': Only 'kotlin.Int' and 'kotlin.IntArray' is valid.")
|
|
||||||
}
|
|
||||||
// replace to ALL? this is bullshit
|
|
||||||
if (to == WorldGenerator.TILE_MACRO_ALL) throw IllegalArgumentException("[mapgenerator] Invalid replaceTo: TILE_MACRO_ALL")
|
|
||||||
|
|
||||||
// filtered threshold
|
|
||||||
val threshold = record.filter.getGrad(y, record.filterArg1, record.filterArg2)
|
|
||||||
|
|
||||||
if (noise > threshold * record.scarcity) {
|
|
||||||
if (fromTerr is IntArray) {
|
|
||||||
for (i in 0..fromTerr.size - 1) {
|
|
||||||
val fromTerrVariable = fromTerr[i]
|
|
||||||
|
|
||||||
if ((WorldGenerator.world.getTileFromTerrain(x, y) == fromTerrVariable || fromTerrVariable == WorldGenerator.TILE_MACRO_ALL)
|
|
||||||
&& (WorldGenerator.world.getTileFromWall(x, y) == fromWall || fromWall == WorldGenerator.TILE_MACRO_ALL)) {
|
|
||||||
WorldGenerator.world.setTileTerrain(x, y, to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if ((WorldGenerator.world.getTileFromTerrain(x, y) == fromTerr || fromTerr == WorldGenerator.TILE_MACRO_ALL)
|
|
||||||
&& (WorldGenerator.world.getTileFromWall(x, y) == fromWall || fromWall == WorldGenerator.TILE_MACRO_ALL)) {
|
|
||||||
WorldGenerator.world.setTileTerrain(x, y, to)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -10,8 +10,8 @@ import net.torvald.terrarum.blockproperties.Block
|
|||||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||||
import net.torvald.terrarum.concurrent.ThreadParallel
|
import net.torvald.terrarum.concurrent.ThreadParallel
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.roundInt
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
@Deprecated("Old non-thread-safe version", ReplaceWith("Terragen", "net.torvald.terrarum.modulebasegame.worldgenerator"))
|
@Deprecated("Old non-thread-safe version", ReplaceWith("Terragen", "net.torvald.terrarum.modulebasegame.worldgenerator"))
|
||||||
object WorldGenerator {
|
object WorldGenerator {
|
||||||
@@ -776,12 +776,12 @@ object WorldGenerator {
|
|||||||
private fun processNoiseLayers(noiseRecords: Array<TaggedJoise>) {
|
private fun processNoiseLayers(noiseRecords: Array<TaggedJoise>) {
|
||||||
if (AppLoader.MULTITHREAD) {
|
if (AppLoader.MULTITHREAD) {
|
||||||
// set up indices
|
// set up indices
|
||||||
for (i in 0 until AppLoader.THREADS) {
|
for (i in 0 until AppLoader.THREAD_COUNT) {
|
||||||
ThreadParallel.map(
|
ThreadParallel.map(
|
||||||
i, "SampleJoiseMap",
|
i, "SampleJoiseMap",
|
||||||
ThreadProcessNoiseLayers(
|
ThreadProcessNoiseLayers(
|
||||||
HEIGHT.toFloat().div(AppLoader.THREADS).times(i).roundInt(),
|
HEIGHT.toFloat().div(AppLoader.THREAD_COUNT).times(i).roundToInt(),
|
||||||
HEIGHT.toFloat().div(AppLoader.THREADS).times(i.plus(1)).roundInt() - 1,
|
HEIGHT.toFloat().div(AppLoader.THREAD_COUNT).times(i.plus(1)).roundToInt() - 1,
|
||||||
noiseRecords
|
noiseRecords
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -13,7 +13,8 @@ import java.util.concurrent.Callable
|
|||||||
object Worldgen {
|
object Worldgen {
|
||||||
|
|
||||||
private lateinit var world: GameWorld
|
private lateinit var world: GameWorld
|
||||||
private lateinit var params: WorldgenParams
|
lateinit var params: WorldgenParams
|
||||||
|
private set
|
||||||
|
|
||||||
private val threadLock = java.lang.Object()
|
private val threadLock = java.lang.Object()
|
||||||
|
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ class LuaComputerVM(val display: MDA) {
|
|||||||
if (sine > 0.79) sine = 0.79
|
if (sine > 0.79) sine = 0.79
|
||||||
else if (sine < -0.79) sine = -0.79
|
else if (sine < -0.79) sine = -0.79
|
||||||
audioData.put(
|
audioData.put(
|
||||||
(0.5 + 0.5 * sine).times(0xFF).roundInt().toByte()
|
(0.5 + 0.5 * sine).times(0xFF).roundToInt().toByte()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -377,7 +377,7 @@ class LuaComputerVM(val display: MDA) {
|
|||||||
sine += Math.sin(Math.PI * 2 * (2*k - 1) * chopSize * x) / (2*k - 1)
|
sine += Math.sin(Math.PI * 2 * (2*k - 1) * chopSize * x) / (2*k - 1)
|
||||||
}
|
}
|
||||||
audioData.put(
|
audioData.put(
|
||||||
(0.5 + 0.5 * sine).times(0xFF).roundInt().toByte()
|
(0.5 + 0.5 * sine).times(0xFF).roundToInt().toByte()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|||||||
@@ -509,7 +509,7 @@ class TerrarumComputerOldOld(peripheralSlots: Int) {
|
|||||||
if (sine > 0.79) sine = 0.79
|
if (sine > 0.79) sine = 0.79
|
||||||
else if (sine < -0.79) sine = -0.79
|
else if (sine < -0.79) sine = -0.79
|
||||||
audioData.put(
|
audioData.put(
|
||||||
(0.5 + 0.5 * sine).times(0xFF).roundInt().toByte()
|
(0.5 + 0.5 * sine).times(0xFF).roundToInt().toByte()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -520,7 +520,7 @@ class TerrarumComputerOldOld(peripheralSlots: Int) {
|
|||||||
sine += Math.sin(Math.PI * 2 * (2*k - 1) * chopSize * x) / (2*k - 1)
|
sine += Math.sin(Math.PI * 2 * (2*k - 1) * chopSize * x) / (2*k - 1)
|
||||||
}
|
}
|
||||||
audioData.put(
|
audioData.put(
|
||||||
(0.5 + 0.5 * sine).times(0xFF).roundInt().toByte()
|
(0.5 + 0.5 * sine).times(0xFF).roundToInt().toByte()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ import net.torvald.terrarum.gameactors.Actor
|
|||||||
import net.torvald.terrarum.gameitem.GameItem
|
import net.torvald.terrarum.gameitem.GameItem
|
||||||
import net.torvald.terrarum.itemproperties.ItemCodex
|
import net.torvald.terrarum.itemproperties.ItemCodex
|
||||||
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.*
|
import net.torvald.terrarum.modulecomputers.virtualcomputer.tvd.*
|
||||||
import net.torvald.terrarum.roundInt
|
|
||||||
import net.torvald.terrarum.utils.JsonWriter.getJsonBuilder
|
import net.torvald.terrarum.utils.JsonWriter.getJsonBuilder
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2018-10-03.
|
* Created by minjaesong on 2018-10-03.
|
||||||
@@ -26,7 +26,7 @@ object SavegameWriter {
|
|||||||
|
|
||||||
operator fun invoke(pnameOverride: String? = null): Boolean {
|
operator fun invoke(pnameOverride: String? = null): Boolean {
|
||||||
playerName = pnameOverride ?: "${Terrarum.ingame!!.actorGamer!!.actorValue[AVKey.NAME]}"
|
playerName = pnameOverride ?: "${Terrarum.ingame!!.actorGamer!!.actorValue[AVKey.NAME]}"
|
||||||
if (playerName.isEmpty()) playerName = "Test subject ${Math.random().times(0x7FFFFFFF).roundInt()}"
|
if (playerName.isEmpty()) playerName = "Test subject ${Math.random().times(0x7FFFFFFF).roundToInt()}"
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val diskImage = generateNewDiskImage()
|
val diskImage = generateNewDiskImage()
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package net.torvald.terrarum.serialise
|
package net.torvald.terrarum.serialise
|
||||||
|
|
||||||
import net.torvald.terrarum.modulebasegame.weather.WeatherMixer
|
import net.torvald.terrarum.modulebasegame.worldgenerator.Worldgen
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.WorldGenerator
|
|
||||||
import net.torvald.terrarum.modulebasegame.worldgenerator.RoguelikeRandomiser
|
|
||||||
import java.nio.charset.Charset
|
import java.nio.charset.Charset
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,7 +16,7 @@ internal object WriteMeta {
|
|||||||
|
|
||||||
val BYTE_NULL: Byte = 0
|
val BYTE_NULL: Byte = 0
|
||||||
|
|
||||||
val terraseed: Long = WorldGenerator.SEED
|
val terraseed: Long = Worldgen.params.seed
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -19,12 +19,13 @@ import com.sudoplay.joise.module.ModuleScaleOffset
|
|||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
import net.torvald.terrarum.AppLoader
|
import net.torvald.terrarum.AppLoader
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.concurrent.BlockingThreadPool
|
import net.torvald.terrarum.concurrent.ThreadExecutor
|
||||||
import net.torvald.terrarum.concurrent.sliceEvenly
|
import net.torvald.terrarum.concurrent.sliceEvenly
|
||||||
import net.torvald.terrarum.inUse
|
import net.torvald.terrarum.inUse
|
||||||
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
import net.torvald.terrarum.modulebasegame.TerrarumIngame
|
||||||
import net.torvald.terrarum.roundInt
|
import java.util.concurrent.Callable
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2018-12-14.
|
* Created by minjaesong on 2018-12-14.
|
||||||
@@ -67,32 +68,34 @@ class NoiseGenerator : ScreenAdapter() {
|
|||||||
get() = (IMAGE_SIZE * IMAGE_SIZE) / pixelsInSingleJob
|
get() = (IMAGE_SIZE * IMAGE_SIZE) / pixelsInSingleJob
|
||||||
private val rawPixelsList: List<IntProgression>
|
private val rawPixelsList: List<IntProgression>
|
||||||
get() = (0 until IMAGE_SIZE * IMAGE_SIZE).sliceEvenly(jobsCount)
|
get() = (0 until IMAGE_SIZE * IMAGE_SIZE).sliceEvenly(jobsCount)
|
||||||
private fun makeGenFun(seed: Long, index: Int) = { //i: Int ->
|
private fun makeGenFun(seed: Long, index: Int) = object : Callable<Unit> { //i: Int ->
|
||||||
val module = ModuleFractal()
|
override fun call() {
|
||||||
module.setType(ModuleFractal.FractalType.BILLOW)
|
val module = ModuleFractal()
|
||||||
module.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
module.setType(ModuleFractal.FractalType.BILLOW)
|
||||||
module.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
module.setAllSourceBasisTypes(ModuleBasisFunction.BasisType.GRADIENT)
|
||||||
module.setNumOctaves(10)
|
module.setAllSourceInterpolationTypes(ModuleBasisFunction.InterpolationType.QUINTIC)
|
||||||
module.setFrequency(8.0)
|
module.setNumOctaves(10)
|
||||||
module.seed = seed
|
module.setFrequency(8.0)
|
||||||
|
module.seed = seed
|
||||||
|
|
||||||
val moduleScale = ModuleScaleOffset()
|
val moduleScale = ModuleScaleOffset()
|
||||||
moduleScale.setSource(module)
|
moduleScale.setSource(module)
|
||||||
moduleScale.setScale(0.5)
|
moduleScale.setScale(0.5)
|
||||||
moduleScale.setOffset(0.0)
|
moduleScale.setOffset(0.0)
|
||||||
|
|
||||||
val noiseModule = Joise(moduleScale)
|
val noiseModule = Joise(moduleScale)
|
||||||
|
|
||||||
for (c in rawPixelsList[index]) {
|
for (c in rawPixelsList[index]) {
|
||||||
val x = c % IMAGE_SIZE
|
val x = c % IMAGE_SIZE
|
||||||
val y = c / IMAGE_SIZE
|
val y = c / IMAGE_SIZE
|
||||||
val uvX = x / IMAGE_SIZED
|
val uvX = x / IMAGE_SIZED
|
||||||
val uvY = y / IMAGE_SIZED
|
val uvY = y / IMAGE_SIZED
|
||||||
|
|
||||||
val noiseValue = noiseModule.get(uvX, uvY).absoluteValue
|
val noiseValue = noiseModule.get(uvX, uvY).absoluteValue
|
||||||
val rgb = (noiseValue * 255.0).roundInt()
|
val rgb = (noiseValue * 255.0).roundToInt()
|
||||||
|
|
||||||
pixmap.drawPixel(x, y, (rgb shl 24) or (rgb shl 16) or (rgb shl 8) or 0xFF)
|
pixmap.drawPixel(x, y, (rgb shl 24) or (rgb shl 16) or (rgb shl 8) or 0xFF)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,13 +110,13 @@ class NoiseGenerator : ScreenAdapter() {
|
|||||||
|
|
||||||
|
|
||||||
// regen
|
// regen
|
||||||
if (timerFired && BlockingThreadPool.allFinished()) {
|
if (timerFired && ThreadExecutor.allFinished) {
|
||||||
timerFired = false
|
timerFired = false
|
||||||
|
|
||||||
totalTestsDone += 1
|
totalTestsDone += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
if (regenerate && BlockingThreadPool.allFinished()) {
|
if (regenerate && ThreadExecutor.allFinished) {
|
||||||
//printdbg(this, "Reticulating splines...")
|
//printdbg(this, "Reticulating splines...")
|
||||||
|
|
||||||
regenerate = false
|
regenerate = false
|
||||||
@@ -124,8 +127,9 @@ class NoiseGenerator : ScreenAdapter() {
|
|||||||
|
|
||||||
val seed = RNG.nextLong()
|
val seed = RNG.nextLong()
|
||||||
val jobs = List(jobsCount) { makeGenFun(seed, it) }
|
val jobs = List(jobsCount) { makeGenFun(seed, it) }
|
||||||
BlockingThreadPool.setTasks(jobs, "")
|
ThreadExecutor.renew()
|
||||||
BlockingThreadPool.startAllWaitForDie()
|
ThreadExecutor.submitAll(jobs)
|
||||||
|
ThreadExecutor.join()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -192,7 +196,7 @@ class NoiseGenerator : ScreenAdapter() {
|
|||||||
System.exit(0)
|
System.exit(0)
|
||||||
}
|
}
|
||||||
// time to construct a new test
|
// time to construct a new test
|
||||||
if (totalTestsDone % samplingCount == 0 && BlockingThreadPool.allFinished()) {
|
if (totalTestsDone % samplingCount == 0 && ThreadExecutor.allFinished) {
|
||||||
pixelsInSingleJob = (IMAGE_SIZE * IMAGE_SIZE) / testSets[totalTestsDone / samplingCount]
|
pixelsInSingleJob = (IMAGE_SIZE * IMAGE_SIZE) / testSets[totalTestsDone / samplingCount]
|
||||||
|
|
||||||
|
|
||||||
@@ -213,7 +217,7 @@ class NoiseGenerator : ScreenAdapter() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// auto-press SPACE
|
// auto-press SPACE
|
||||||
if (BlockingThreadPool.allFinished()) {
|
if (ThreadExecutor.allFinished) {
|
||||||
regenerate = true
|
regenerate = true
|
||||||
constructOnce = false
|
constructOnce = false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,8 +21,8 @@ import net.torvald.terrarum.concurrent.ThreadParallel
|
|||||||
import net.torvald.terrarum.concurrent.ThreadableFun
|
import net.torvald.terrarum.concurrent.ThreadableFun
|
||||||
import net.torvald.terrarum.concurrent.sliceEvenly
|
import net.torvald.terrarum.concurrent.sliceEvenly
|
||||||
import net.torvald.terrarum.inUse
|
import net.torvald.terrarum.inUse
|
||||||
import net.torvald.terrarum.roundInt
|
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
|
import kotlin.math.roundToInt
|
||||||
import kotlin.system.measureNanoTime
|
import kotlin.system.measureNanoTime
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -124,7 +124,7 @@ class ThreadParallelTester : ApplicationAdapter() {
|
|||||||
val uvY = y / IMAGE_SIZED
|
val uvY = y / IMAGE_SIZED
|
||||||
|
|
||||||
val noiseValue = noiseModule.get(uvX, uvY).absoluteValue
|
val noiseValue = noiseModule.get(uvX, uvY).absoluteValue
|
||||||
val rgb = (noiseValue * 255.0).roundInt()
|
val rgb = (noiseValue * 255.0).roundToInt()
|
||||||
|
|
||||||
pixmap.drawPixel(x, y, (rgb shl 24) or (rgb shl 16) or (rgb shl 8) or 0xFF)
|
pixmap.drawPixel(x, y, (rgb shl 24) or (rgb shl 16) or (rgb shl 8) or 0xFF)
|
||||||
}
|
}
|
||||||
@@ -217,7 +217,7 @@ class BasicDebugInfoWindow : UICanvas() {
|
|||||||
// memory pressure
|
// memory pressure
|
||||||
AppLoader.fontSmallNumbers.draw(batch, "${ccY}MEM ", (AppLoader.screenW - 23 * TinyAlphNum.W - 2).toFloat(), line(1))
|
AppLoader.fontSmallNumbers.draw(batch, "${ccY}MEM ", (AppLoader.screenW - 23 * TinyAlphNum.W - 2).toFloat(), line(1))
|
||||||
// thread count
|
// thread count
|
||||||
AppLoader.fontSmallNumbers.draw(batch, "${ccY}CPUs${if (AppLoader.MULTITHREAD) ccG else ccR}${AppLoader.THREADS.toString().padStart(2, ' ')}",
|
AppLoader.fontSmallNumbers.draw(batch, "${ccY}CPUs${if (AppLoader.MULTITHREAD) ccG else ccR}${AppLoader.THREAD_COUNT.toString().padStart(2, ' ')}",
|
||||||
(AppLoader.screenW - 2 - 8 * TinyAlphNum.W).toFloat(), line(2))
|
(AppLoader.screenW - 2 - 8 * TinyAlphNum.W).toFloat(), line(2))
|
||||||
|
|
||||||
// memory texts
|
// memory texts
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import com.badlogic.gdx.utils.Disposable
|
|||||||
import net.torvald.terrarum.AppLoader
|
import net.torvald.terrarum.AppLoader
|
||||||
import net.torvald.terrarum.Second
|
import net.torvald.terrarum.Second
|
||||||
import net.torvald.terrarum.Terrarum
|
import net.torvald.terrarum.Terrarum
|
||||||
import net.torvald.terrarum.roundInt
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -309,22 +309,22 @@ abstract class UICanvas(
|
|||||||
ui.handler.openCloseCounter / openCloseTime,
|
ui.handler.openCloseCounter / openCloseTime,
|
||||||
-ui.width.toFloat(),
|
-ui.width.toFloat(),
|
||||||
0f
|
0f
|
||||||
).roundInt()
|
).roundToInt()
|
||||||
Position.TOP -> ui.handler.posY = Movement.fastPullOut(
|
Position.TOP -> ui.handler.posY = Movement.fastPullOut(
|
||||||
ui.handler.openCloseCounter / openCloseTime,
|
ui.handler.openCloseCounter / openCloseTime,
|
||||||
-ui.height.toFloat(),
|
-ui.height.toFloat(),
|
||||||
0f
|
0f
|
||||||
).roundInt()
|
).roundToInt()
|
||||||
Position.RIGHT -> ui.handler.posX = Movement.fastPullOut(
|
Position.RIGHT -> ui.handler.posX = Movement.fastPullOut(
|
||||||
ui.handler.openCloseCounter / openCloseTime,
|
ui.handler.openCloseCounter / openCloseTime,
|
||||||
AppLoader.screenWf,
|
AppLoader.screenWf,
|
||||||
AppLoader.screenW - ui.width.toFloat()
|
AppLoader.screenW - ui.width.toFloat()
|
||||||
).roundInt()
|
).roundToInt()
|
||||||
Position.BOTTOM -> ui.handler.posY = Movement.fastPullOut(
|
Position.BOTTOM -> ui.handler.posY = Movement.fastPullOut(
|
||||||
ui.handler.openCloseCounter / openCloseTime,
|
ui.handler.openCloseCounter / openCloseTime,
|
||||||
AppLoader.screenHf,
|
AppLoader.screenHf,
|
||||||
AppLoader.screenH - ui.height.toFloat()
|
AppLoader.screenH - ui.height.toFloat()
|
||||||
).roundInt()
|
).roundToInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun doClosingPopOut(ui: UICanvas, openCloseTime: Second, position: Position) {
|
fun doClosingPopOut(ui: UICanvas, openCloseTime: Second, position: Position) {
|
||||||
@@ -333,22 +333,22 @@ abstract class UICanvas(
|
|||||||
ui.handler.openCloseCounter / openCloseTime,
|
ui.handler.openCloseCounter / openCloseTime,
|
||||||
0f,
|
0f,
|
||||||
-ui.width.toFloat()
|
-ui.width.toFloat()
|
||||||
).roundInt()
|
).roundToInt()
|
||||||
Position.TOP -> ui.handler.posY = Movement.fastPullOut(
|
Position.TOP -> ui.handler.posY = Movement.fastPullOut(
|
||||||
ui.handler.openCloseCounter / openCloseTime,
|
ui.handler.openCloseCounter / openCloseTime,
|
||||||
0f,
|
0f,
|
||||||
-ui.height.toFloat()
|
-ui.height.toFloat()
|
||||||
).roundInt()
|
).roundToInt()
|
||||||
Position.RIGHT -> ui.handler.posX = Movement.fastPullOut(
|
Position.RIGHT -> ui.handler.posX = Movement.fastPullOut(
|
||||||
ui.handler.openCloseCounter / openCloseTime,
|
ui.handler.openCloseCounter / openCloseTime,
|
||||||
AppLoader.screenW - ui.width.toFloat(),
|
AppLoader.screenW - ui.width.toFloat(),
|
||||||
AppLoader.screenWf
|
AppLoader.screenWf
|
||||||
).roundInt()
|
).roundToInt()
|
||||||
Position.BOTTOM -> ui.handler.posY = Movement.fastPullOut(
|
Position.BOTTOM -> ui.handler.posY = Movement.fastPullOut(
|
||||||
ui.handler.openCloseCounter / openCloseTime,
|
ui.handler.openCloseCounter / openCloseTime,
|
||||||
AppLoader.screenH - ui.height.toFloat(),
|
AppLoader.screenH - ui.height.toFloat(),
|
||||||
AppLoader.screenHf
|
AppLoader.screenHf
|
||||||
).roundInt()
|
).roundToInt()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fun endOpeningPopOut(ui: UICanvas, position: Position) {
|
fun endOpeningPopOut(ui: UICanvas, position: Position) {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ package net.torvald.terrarum.ui
|
|||||||
import com.badlogic.gdx.graphics.Camera
|
import com.badlogic.gdx.graphics.Camera
|
||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import net.torvald.terrarum.roundInt
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Image gallery. Images will be equally spaced, counted from top-left to bottom-right.
|
* Image gallery. Images will be equally spaced, counted from top-left to bottom-right.
|
||||||
@@ -31,13 +31,13 @@ class UIItemImageGallery(
|
|||||||
val gutter = (height - imageList[i].height.times(imageList.size)).toFloat().div(
|
val gutter = (height - imageList[i].height.times(imageList.size)).toFloat().div(
|
||||||
imageList.size + 1f
|
imageList.size + 1f
|
||||||
)
|
)
|
||||||
return row((gutter * i.plus(1) + imageList[i].height * i).roundInt())
|
return row((gutter * i.plus(1) + imageList[i].height * i).roundToInt())
|
||||||
}
|
}
|
||||||
|
|
||||||
imageList.forEachIndexed { i, image ->
|
imageList.forEachIndexed { i, image ->
|
||||||
Toolkit.drawCentered(batch, image,
|
Toolkit.drawCentered(batch, image,
|
||||||
imagePosY(i),
|
imagePosY(i),
|
||||||
width.toFloat().div(column).times(column(i).plus(1)).roundInt(),
|
width.toFloat().div(column).times(column(i).plus(1)).roundToInt(),
|
||||||
posX, posY
|
posX, posY
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import com.badlogic.gdx.graphics.Color
|
|||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
|
import kotlin.math.roundToInt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2017-03-13.
|
* Created by minjaesong on 2017-03-13.
|
||||||
@@ -74,7 +75,7 @@ class UIItemTextButtonList(
|
|||||||
val h = height.toFloat()
|
val h = height.toFloat()
|
||||||
val ss = labelsList.size.toFloat()
|
val ss = labelsList.size.toFloat()
|
||||||
val lh = itemHitboxSize
|
val lh = itemHitboxSize
|
||||||
val vertOff = (h/ss * i + (h/ss - lh) / 2f).roundInt()
|
val vertOff = (h/ss * i + (h/ss - lh) / 2f).roundToInt()
|
||||||
|
|
||||||
if (!kinematic) {
|
if (!kinematic) {
|
||||||
UIItemTextButton(
|
UIItemTextButton(
|
||||||
|
|||||||
@@ -372,7 +372,7 @@ internal object BlocksDrawer {
|
|||||||
|
|
||||||
val breakage = if (mode == TERRAIN) world.getTerrainDamage(x, y) else world.getWallDamage(x, y)
|
val breakage = if (mode == TERRAIN) world.getTerrainDamage(x, y) else world.getWallDamage(x, y)
|
||||||
val maxHealth = BlockCodex[world.getTileFromTerrain(x, y)].strength
|
val maxHealth = BlockCodex[world.getTileFromTerrain(x, y)].strength
|
||||||
val breakingStage = (breakage / maxHealth).times(BREAKAGE_STEPS).roundInt()
|
val breakingStage = (breakage / maxHealth).times(BREAKAGE_STEPS).roundToInt()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -503,7 +503,7 @@ object BlocksDrawerOLD {
|
|||||||
if (mode == TERRAIN || mode == WALL) {
|
if (mode == TERRAIN || mode == WALL) {
|
||||||
val breakage = if (mode == TERRAIN) world.getTerrainDamage(x, y) else world.getWallDamage(x, y)
|
val breakage = if (mode == TERRAIN) world.getTerrainDamage(x, y) else world.getWallDamage(x, y)
|
||||||
val maxHealth = BlockCodex[world.getTileFromTerrain(x, y)].strength
|
val maxHealth = BlockCodex[world.getTileFromTerrain(x, y)].strength
|
||||||
val stage = (breakage / maxHealth).times(breakAnimSteps).roundInt()
|
val stage = (breakage / maxHealth).times(breakAnimSteps).roundToInt()
|
||||||
// actual drawing
|
// actual drawing
|
||||||
if (stage > 0) {
|
if (stage > 0) {
|
||||||
batch.color = color
|
batch.color = color
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ package net.torvald.terrarum.worlddrawer
|
|||||||
import com.badlogic.gdx.graphics.Color
|
import com.badlogic.gdx.graphics.Color
|
||||||
import com.badlogic.gdx.graphics.Pixmap
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
import com.badlogic.gdx.graphics.glutils.ShaderProgram
|
|
||||||
import com.jme3.math.FastMath
|
|
||||||
import net.torvald.gdx.graphics.Cvec
|
import net.torvald.gdx.graphics.Cvec
|
||||||
import net.torvald.gdx.graphics.UnsafeCvecArray
|
import net.torvald.gdx.graphics.UnsafeCvecArray
|
||||||
import net.torvald.terrarum.*
|
import net.torvald.terrarum.*
|
||||||
@@ -12,7 +10,6 @@ import net.torvald.terrarum.AppLoader.printdbg
|
|||||||
import net.torvald.terrarum.blockproperties.Block
|
import net.torvald.terrarum.blockproperties.Block
|
||||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||||
import net.torvald.terrarum.blockproperties.Fluid
|
import net.torvald.terrarum.blockproperties.Fluid
|
||||||
import net.torvald.terrarum.concurrent.sliceEvenly
|
|
||||||
import net.torvald.terrarum.gameactors.ActorWithBody
|
import net.torvald.terrarum.gameactors.ActorWithBody
|
||||||
import net.torvald.terrarum.gameactors.Luminous
|
import net.torvald.terrarum.gameactors.Luminous
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
@@ -41,7 +38,7 @@ object LightmapRenderer {
|
|||||||
/** World change is managed by IngameRenderer.setWorld() */
|
/** World change is managed by IngameRenderer.setWorld() */
|
||||||
private var world: GameWorld = GameWorld.makeNullWorld()
|
private var world: GameWorld = GameWorld.makeNullWorld()
|
||||||
|
|
||||||
private lateinit var lightCalcShader: ShaderProgram
|
//private lateinit var lightCalcShader: ShaderProgram
|
||||||
//private val SHADER_LIGHTING = AppLoader.getConfigBoolean("gpulightcalc")
|
//private val SHADER_LIGHTING = AppLoader.getConfigBoolean("gpulightcalc")
|
||||||
|
|
||||||
/** do not call this yourself! Let your game renderer handle this! */
|
/** do not call this yourself! Let your game renderer handle this! */
|
||||||
@@ -54,8 +51,6 @@ object LightmapRenderer {
|
|||||||
_mapLightLevelThis.zerofill()
|
_mapLightLevelThis.zerofill()
|
||||||
_mapThisTileOpacity.zerofill()
|
_mapThisTileOpacity.zerofill()
|
||||||
_mapThisTileOpacity2.zerofill()
|
_mapThisTileOpacity2.zerofill()
|
||||||
|
|
||||||
makeUpdateTaskList()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (e: UninitializedPropertyAccessException) {
|
catch (e: UninitializedPropertyAccessException) {
|
||||||
@@ -71,10 +66,10 @@ object LightmapRenderer {
|
|||||||
const val overscan_open: Int = 40
|
const val overscan_open: Int = 40
|
||||||
const val overscan_opaque: Int = 10
|
const val overscan_opaque: Int = 10
|
||||||
|
|
||||||
var LIGHTMAP_WIDTH = (Terrarum.ingame?.ZOOM_MINIMUM ?: 1f).inv().times(AppLoader.screenW).div(TILE_SIZE).ceil() + overscan_open * 2 + 3
|
private var LIGHTMAP_WIDTH: Int = (Terrarum.ingame?.ZOOM_MINIMUM ?: 1f).inv().times(AppLoader.screenW).div(TILE_SIZE).ceilInt() + overscan_open * 2 + 3
|
||||||
var LIGHTMAP_HEIGHT = (Terrarum.ingame?.ZOOM_MINIMUM ?: 1f).inv().times(AppLoader.screenH).div(TILE_SIZE).ceil() + overscan_open * 2 + 3
|
private var LIGHTMAP_HEIGHT: Int = (Terrarum.ingame?.ZOOM_MINIMUM ?: 1f).inv().times(AppLoader.screenH).div(TILE_SIZE).ceilInt() + overscan_open * 2 + 3
|
||||||
|
|
||||||
private val noopMask = HashSet<Point2i>((LIGHTMAP_WIDTH + LIGHTMAP_HEIGHT) * 2)
|
//private val noopMask = HashSet<Point2i>((LIGHTMAP_WIDTH + LIGHTMAP_HEIGHT) * 2)
|
||||||
|
|
||||||
private val lanternMap = HashMap<BlockAddress, Cvec>((Terrarum.ingame?.ACTORCONTAINER_INITIAL_SIZE ?: 2) * 4)
|
private val lanternMap = HashMap<BlockAddress, Cvec>((Terrarum.ingame?.ACTORCONTAINER_INITIAL_SIZE ?: 2) * 4)
|
||||||
/**
|
/**
|
||||||
@@ -135,14 +130,14 @@ object LightmapRenderer {
|
|||||||
* @param y world tile coord
|
* @param y world tile coord
|
||||||
*/
|
*/
|
||||||
internal fun getLight(x: Int, y: Int): Cvec? {
|
internal fun getLight(x: Int, y: Int): Cvec? {
|
||||||
if (!inBounds(x, y)) {
|
return if (!inBounds(x, y)) {
|
||||||
return null
|
null
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val x = x.convX()
|
val x = x.convX()
|
||||||
val y = y.convY()
|
val y = y.convY()
|
||||||
|
|
||||||
return Cvec(
|
Cvec(
|
||||||
lightmap.getR(x, y) * MUL_FLOAT,
|
lightmap.getR(x, y) * MUL_FLOAT,
|
||||||
lightmap.getG(x, y) * MUL_FLOAT,
|
lightmap.getG(x, y) * MUL_FLOAT,
|
||||||
lightmap.getB(x, y) * MUL_FLOAT,
|
lightmap.getB(x, y) * MUL_FLOAT,
|
||||||
@@ -205,10 +200,10 @@ object LightmapRenderer {
|
|||||||
sunLight.set(world.globalLight); sunLight.mul(DIV_FLOAT)
|
sunLight.set(world.globalLight); sunLight.mul(DIV_FLOAT)
|
||||||
|
|
||||||
// set no-op mask from solidity of the block
|
// set no-op mask from solidity of the block
|
||||||
AppLoader.measureDebugTime("Renderer.LightNoOpMask") {
|
/*AppLoader.measureDebugTime("Renderer.LightNoOpMask") {
|
||||||
noopMask.clear()
|
noopMask.clear()
|
||||||
buildNoopMask()
|
buildNoopMask()
|
||||||
}
|
}*/
|
||||||
|
|
||||||
// wipe out lightmap
|
// wipe out lightmap
|
||||||
AppLoader.measureDebugTime("Renderer.LightPrecalc") {
|
AppLoader.measureDebugTime("Renderer.LightPrecalc") {
|
||||||
@@ -224,9 +219,10 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// YE OLDE LIGHT UPDATER
|
||||||
// O((5*9)n where n is a size of the map.
|
// O((5*9)n where n is a size of the map.
|
||||||
// Because of inevitable overlaps on the area, it only works with MAX blend
|
// Because of inevitable overlaps on the area, it only works with MAX blend
|
||||||
|
|
||||||
/*fun or1() {
|
/*fun or1() {
|
||||||
// Round 1
|
// Round 1
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
for (y in for_y_start - overscan_open..for_y_end) {
|
||||||
@@ -260,6 +256,7 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
// 'NEWLIGHT2' LIGHT SWIPER
|
||||||
// O((8*2)n) where n is a size of the map.
|
// O((8*2)n) where n is a size of the map.
|
||||||
fun r1() {
|
fun r1() {
|
||||||
// TODO test non-parallel
|
// TODO test non-parallel
|
||||||
@@ -366,11 +363,11 @@ object LightmapRenderer {
|
|||||||
|
|
||||||
// To save you from pains:
|
// To save you from pains:
|
||||||
// - Per-channel light updating is actually slower
|
// - Per-channel light updating is actually slower
|
||||||
|
// BELOW NOTES DOES NOT APPLY TO 'NEWLIGHT2' LIGHT SWIPER
|
||||||
// - It seems 5-pass lighting is needed to resonably eliminate the dark spot (of which I have zero idea
|
// - It seems 5-pass lighting is needed to resonably eliminate the dark spot (of which I have zero idea
|
||||||
// why dark spots appear in the first place)
|
// why dark spots appear in the first place)
|
||||||
// - Multithreading? I have absolutely no idea.
|
// - Multithreading? I have absolutely no idea.
|
||||||
// - If you naively slice the screen (job area) to multithread, the seam will appear.
|
// - If you naively slice the screen (job area) to multithread, the seam will appear.
|
||||||
|
|
||||||
//r3();r4();r1();r2();r3();
|
//r3();r4();r1();r2();r3();
|
||||||
|
|
||||||
r1();r2();r3();r4()
|
r1();r2();r3();r4()
|
||||||
@@ -384,56 +381,11 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO re-init at every resize
|
|
||||||
private lateinit var updateMessages: List<Array<ThreadedLightmapUpdateMessage>>
|
|
||||||
|
|
||||||
private fun makeUpdateTaskList() {
|
|
||||||
val lightTaskArr = ArrayList<ThreadedLightmapUpdateMessage>()
|
|
||||||
|
|
||||||
val for_x_start = overscan_open
|
|
||||||
val for_y_start = overscan_open
|
|
||||||
val for_x_end = for_x_start + WorldCamera.width / TILE_SIZE + 3
|
|
||||||
val for_y_end = for_y_start + WorldCamera.height / TILE_SIZE + 3 // same fix as above
|
|
||||||
|
|
||||||
// Round 2
|
|
||||||
for (y in for_y_end + overscan_open downTo for_y_start) {
|
|
||||||
for (x in for_x_start - overscan_open..for_x_end) {
|
|
||||||
lightTaskArr.add(ThreadedLightmapUpdateMessage(x, y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Round 3
|
|
||||||
for (y in for_y_end + overscan_open downTo for_y_start) {
|
|
||||||
for (x in for_x_end + overscan_open downTo for_x_start) {
|
|
||||||
lightTaskArr.add(ThreadedLightmapUpdateMessage(x, y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Round 4
|
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
|
||||||
for (x in for_x_end + overscan_open downTo for_x_start) {
|
|
||||||
lightTaskArr.add(ThreadedLightmapUpdateMessage(x, y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Round 1
|
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
|
||||||
for (x in for_x_start - overscan_open..for_x_end) {
|
|
||||||
lightTaskArr.add(ThreadedLightmapUpdateMessage(x, y))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
updateMessages = lightTaskArr.toTypedArray().sliceEvenly(AppLoader.THREADS)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal data class ThreadedLightmapUpdateMessage(val x: Int, val y: Int)
|
|
||||||
|
|
||||||
|
|
||||||
private fun buildLanternmap(actorContainers: Array<out List<ActorWithBody>?>) {
|
private fun buildLanternmap(actorContainers: Array<out List<ActorWithBody>?>) {
|
||||||
lanternMap.clear()
|
lanternMap.clear()
|
||||||
actorContainers.forEach { actorContainer ->
|
actorContainers.forEach { actorContainer ->
|
||||||
actorContainer?.forEach {
|
actorContainer?.forEach {
|
||||||
if (it is Luminous && it is ActorWithBody) {
|
if (it is Luminous) {
|
||||||
// put lanterns to the area the luminantBox is occupying
|
// put lanterns to the area the luminantBox is occupying
|
||||||
for (lightBox in it.lightBoxList) {
|
for (lightBox in it.lightBoxList) {
|
||||||
val lightBoxX = it.hitbox.startX + lightBox.startX
|
val lightBoxX = it.hitbox.startX + lightBox.startX
|
||||||
@@ -456,7 +408,7 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun buildNoopMask() {
|
/*private fun buildNoopMask() {
|
||||||
fun isShaded(x: Int, y: Int) = try {
|
fun isShaded(x: Int, y: Int) = try {
|
||||||
BlockCodex[world.getTileFromTerrain(x, y)].isSolid
|
BlockCodex[world.getTileFromTerrain(x, y)].isSolid
|
||||||
}
|
}
|
||||||
@@ -491,8 +443,7 @@ object LightmapRenderer {
|
|||||||
if (isShaded(for_x_start, y)) noopMask.add(Point2i(for_x_start, y))
|
if (isShaded(for_x_start, y)) noopMask.add(Point2i(for_x_start, y))
|
||||||
if (isShaded(for_x_end, y)) noopMask.add(Point2i(for_x_end, y))
|
if (isShaded(for_x_end, y)) noopMask.add(Point2i(for_x_end, y))
|
||||||
}
|
}
|
||||||
|
}*/
|
||||||
}
|
|
||||||
|
|
||||||
// local variables that are made static
|
// local variables that are made static
|
||||||
private val sunLight = Cvec(0)
|
private val sunLight = Cvec(0)
|
||||||
@@ -576,7 +527,7 @@ object LightmapRenderer {
|
|||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
private val inNoopMaskp = Point2i(0,0)
|
/*private val inNoopMaskp = Point2i(0,0)
|
||||||
|
|
||||||
private fun inNoopMask(x: Int, y: Int): Boolean {
|
private fun inNoopMask(x: Int, y: Int): Boolean {
|
||||||
if (x in for_x_start..for_x_end) {
|
if (x in for_x_start..for_x_end) {
|
||||||
@@ -620,7 +571,7 @@ object LightmapRenderer {
|
|||||||
|
|
||||||
// if your IDE error out that you need return statement, AND it's "fixed" by removing 'else' before 'return false',
|
// if your IDE error out that you need return statement, AND it's "fixed" by removing 'else' before 'return false',
|
||||||
// you're doing it wrong, the IF and return statements must be inclusive.
|
// you're doing it wrong, the IF and return statements must be inclusive.
|
||||||
}
|
}*/
|
||||||
|
|
||||||
private var swipeX = -1
|
private var swipeX = -1
|
||||||
private var swipeY = -1
|
private var swipeY = -1
|
||||||
@@ -673,10 +624,10 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/** Another YE OLDE light simulator
|
||||||
* Calculates the light simulation, using main lightmap as one of the input.
|
* Calculates the light simulation, using main lightmap as one of the input.
|
||||||
*/
|
*/
|
||||||
private fun calculateAndAssign(lightmap: UnsafeCvecArray, worldX: Int, worldY: Int) {
|
/*private fun calculateAndAssign(lightmap: UnsafeCvecArray, worldX: Int, worldY: Int) {
|
||||||
|
|
||||||
//if (inNoopMask(worldX, worldY)) return
|
//if (inNoopMask(worldX, worldY)) return
|
||||||
|
|
||||||
@@ -724,7 +675,7 @@ object LightmapRenderer {
|
|||||||
/* * */_ambientAccumulator.maxAndAssign(darkenColoured(x + 1, y, _thisTileOpacity))
|
/* * */_ambientAccumulator.maxAndAssign(darkenColoured(x + 1, y, _thisTileOpacity))
|
||||||
|
|
||||||
lightmap.setVec(x, y, _ambientAccumulator)
|
lightmap.setVec(x, y, _ambientAccumulator)
|
||||||
}
|
}*/
|
||||||
|
|
||||||
private fun isSolid(x: Int, y: Int): Float? { // ...so that they wouldn't appear too dark
|
private fun isSolid(x: Int, y: Int): Float? { // ...so that they wouldn't appear too dark
|
||||||
if (!inBounds(x, y)) return null
|
if (!inBounds(x, y)) return null
|
||||||
@@ -760,9 +711,9 @@ object LightmapRenderer {
|
|||||||
// write to colour buffer
|
// write to colour buffer
|
||||||
for (y in this_y_start..this_y_end) {
|
for (y in this_y_start..this_y_end) {
|
||||||
//println("y: $y, this_y_start: $this_y_start")
|
//println("y: $y, this_y_start: $this_y_start")
|
||||||
if (y == this_y_start && this_y_start == 0) {
|
//if (y == this_y_start && this_y_start == 0) {
|
||||||
//throw Error("Fuck hits again...")
|
// throw Error("Fuck hits again...")
|
||||||
}
|
//}
|
||||||
|
|
||||||
for (x in this_x_start..this_x_end) {
|
for (x in this_x_start..this_x_end) {
|
||||||
|
|
||||||
@@ -854,11 +805,6 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Float.inv() = 1f / this
|
private fun Float.inv() = 1f / this
|
||||||
fun Float.floor() = FastMath.floor(this)
|
|
||||||
fun Double.floorInt() = Math.floor(this).toInt()
|
|
||||||
fun Float.round(): Int = Math.round(this)
|
|
||||||
fun Double.round(): Int = Math.round(this).toInt()
|
|
||||||
fun Float.ceil() = FastMath.ceil(this)
|
|
||||||
fun Int.even(): Boolean = this and 1 == 0
|
fun Int.even(): Boolean = this and 1 == 0
|
||||||
fun Int.odd(): Boolean = this and 1 == 1
|
fun Int.odd(): Boolean = this and 1 == 1
|
||||||
|
|
||||||
@@ -892,8 +838,8 @@ object LightmapRenderer {
|
|||||||
val tilesInHorizontal = (AppLoader.screenWf / TILE_SIZE).ceilInt() + 1
|
val tilesInHorizontal = (AppLoader.screenWf / TILE_SIZE).ceilInt() + 1
|
||||||
val tilesInVertical = (AppLoader.screenHf / TILE_SIZE).ceilInt() + 1
|
val tilesInVertical = (AppLoader.screenHf / TILE_SIZE).ceilInt() + 1
|
||||||
|
|
||||||
LIGHTMAP_WIDTH = (Terrarum.ingame?.ZOOM_MINIMUM ?: 1f).inv().times(AppLoader.screenW).div(TILE_SIZE).ceil() + overscan_open * 2 + 3
|
LIGHTMAP_WIDTH = (Terrarum.ingame?.ZOOM_MINIMUM ?: 1f).inv().times(AppLoader.screenW).div(TILE_SIZE).ceilInt() + overscan_open * 2 + 3
|
||||||
LIGHTMAP_HEIGHT = (Terrarum.ingame?.ZOOM_MINIMUM ?: 1f).inv().times(AppLoader.screenH).div(TILE_SIZE).ceil() + overscan_open * 2 + 3
|
LIGHTMAP_HEIGHT = (Terrarum.ingame?.ZOOM_MINIMUM ?: 1f).inv().times(AppLoader.screenH).div(TILE_SIZE).ceilInt() + overscan_open * 2 + 3
|
||||||
|
|
||||||
if (_init) {
|
if (_init) {
|
||||||
lightBuffer.dispose()
|
lightBuffer.dispose()
|
||||||
|
|||||||
Reference in New Issue
Block a user