code cleanup

This commit is contained in:
minjaesong
2020-11-11 10:40:10 +09:00
parent 4db5bc1623
commit ab780fd246
36 changed files with 274 additions and 716 deletions

View File

@@ -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);
} }

View File

@@ -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"
) )

View File

@@ -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

View File

@@ -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(

View File

@@ -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()
} }

View 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
}
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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)
} }

View File

@@ -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

View File

@@ -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)

View File

@@ -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
} }

View File

@@ -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)
} }

View File

@@ -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

View File

@@ -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
}

View File

@@ -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
}
}
}

View File

@@ -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
}
}
}

View File

@@ -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
}
}
}

View File

@@ -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
}
}
}

View File

@@ -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
}
}

View File

@@ -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)
}
}
}
}
}
}
}

View File

@@ -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
) )
) )

View File

@@ -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()

View File

@@ -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()
) )
} }
}*/ }*/

View File

@@ -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()
) )
} }
}*/ }*/

View File

@@ -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()

View File

@@ -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
/** /**

View File

@@ -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
} }

View File

@@ -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)
} }

View File

@@ -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

View File

@@ -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) {

View File

@@ -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
) )
} }

View File

@@ -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(

View File

@@ -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()

View File

@@ -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

View File

@@ -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()