diff --git a/.idea/artifacts/MusicPlayer.xml b/.idea/artifacts/MusicPlayer.xml
new file mode 100644
index 000000000..a208ca6b2
--- /dev/null
+++ b/.idea/artifacts/MusicPlayer.xml
@@ -0,0 +1,14 @@
+
+
+ $PROJECT_DIR$/assets/mods/musicplayer
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/libraries/jetbrains_kotlin_test.xml b/.idea/libraries/jetbrains_kotlin_test.xml
index 6842add80..5498430f5 100644
--- a/.idea/libraries/jetbrains_kotlin_test.xml
+++ b/.idea/libraries/jetbrains_kotlin_test.xml
@@ -1,13 +1,30 @@
-
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 5b95ada26..a1395dd85 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -38,7 +38,7 @@
-
+
diff --git a/.idea/modules.xml b/.idea/modules.xml
index beb22c826..a7ecfc7fe 100644
--- a/.idea/modules.xml
+++ b/.idea/modules.xml
@@ -6,6 +6,7 @@
+
diff --git a/.idea/runConfigurations/Terrarum.xml b/.idea/runConfigurations/Terrarum.xml
index 5c788bd00..20659ba90 100644
--- a/.idea/runConfigurations/Terrarum.xml
+++ b/.idea/runConfigurations/Terrarum.xml
@@ -10,6 +10,7 @@
diff --git a/.idea/runConfigurations/Terrarum__no_DEV_MODE_.xml b/.idea/runConfigurations/Terrarum__no_DEV_MODE_.xml
index cbab45e66..31e9198aa 100644
--- a/.idea/runConfigurations/Terrarum__no_DEV_MODE_.xml
+++ b/.idea/runConfigurations/Terrarum__no_DEV_MODE_.xml
@@ -10,6 +10,7 @@
diff --git a/ModuleComputers/ModuleComputers.iml b/ModuleComputers/ModuleComputers.iml
index 020f9564c..38a169981 100644
--- a/ModuleComputers/ModuleComputers.iml
+++ b/ModuleComputers/ModuleComputers.iml
@@ -8,16 +8,15 @@
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/ModuleComputers/lib/TerrarumTSVM.jar b/ModuleComputers/lib/TerrarumTSVM.jar
index e3e47ad26..d6d585208 100644
Binary files a/ModuleComputers/lib/TerrarumTSVM.jar and b/ModuleComputers/lib/TerrarumTSVM.jar differ
diff --git a/MusicPlayer/MusicPlayer.iml b/MusicPlayer/MusicPlayer.iml
new file mode 100644
index 000000000..54a9c69de
--- /dev/null
+++ b/MusicPlayer/MusicPlayer.iml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/MusicPlayer/src/net/torvald/terrarum/musicplayer/EntryPoint.kt b/MusicPlayer/src/net/torvald/terrarum/musicplayer/EntryPoint.kt
new file mode 100644
index 000000000..3f79a4614
--- /dev/null
+++ b/MusicPlayer/src/net/torvald/terrarum/musicplayer/EntryPoint.kt
@@ -0,0 +1,19 @@
+package net.torvald.terrarum.musicplayer
+
+import net.torvald.terrarum.IngameInstance
+import net.torvald.terrarum.ModMgr
+import net.torvald.terrarum.ModuleEntryPoint
+import net.torvald.terrarum.modulebasegame.TerrarumIngame
+import net.torvald.terrarum.musicplayer.gui.MusicPlayer
+
+/**
+ * Created by minjaesong on 2023-12-23.
+ */
+class EntryPoint : ModuleEntryPoint() {
+ override fun invoke() {
+ ModMgr.GameExtraGuiLoader.register { ingame: TerrarumIngame -> MusicPlayer(ingame) }
+ }
+
+ override fun dispose() {
+ }
+}
\ No newline at end of file
diff --git a/MusicPlayer/src/net/torvald/terrarum/musicplayer/gui/MusicPlayer.kt b/MusicPlayer/src/net/torvald/terrarum/musicplayer/gui/MusicPlayer.kt
new file mode 100644
index 000000000..750c82908
--- /dev/null
+++ b/MusicPlayer/src/net/torvald/terrarum/musicplayer/gui/MusicPlayer.kt
@@ -0,0 +1,217 @@
+package net.torvald.terrarum.musicplayer.gui
+
+import com.badlogic.gdx.graphics.Color
+import com.badlogic.gdx.graphics.OrthographicCamera
+import com.badlogic.gdx.graphics.Pixmap
+import com.badlogic.gdx.graphics.g2d.SpriteBatch
+import com.badlogic.gdx.graphics.glutils.FrameBuffer
+import com.jme3.math.FastMath
+import net.torvald.reflection.extortField
+import net.torvald.terrarum.*
+import net.torvald.terrarum.audio.*
+import net.torvald.terrarum.modulebasegame.TerrarumIngame
+import net.torvald.terrarum.ui.BasicDebugInfoWindow
+import net.torvald.terrarum.ui.Toolkit
+import net.torvald.terrarum.ui.UICanvas
+import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
+import kotlin.math.*
+
+/**
+ * Created by minjaesong on 2023-12-23.
+ */
+class MusicPlayer(private val ingame: TerrarumIngame) : UICanvas() {
+
+ override var width = 120
+ override var height = 28
+
+ private var capsuleHeight = 28
+ private var capsuleMosaicSize = capsuleHeight / 2 + 1
+
+ private val maskOffWidth = 8
+
+ private val nameFBO = FrameBuffer(Pixmap.Format.RGBA8888, 400, capsuleHeight, false)
+
+ private val baloonTexture = ModMgr.getGdxFile("musicplayer", "gui/blob.tga").let {
+ TextureRegionPack(it, capsuleMosaicSize, capsuleMosaicSize)
+ }
+ private val textmask = ModMgr.getGdxFile("musicplayer", "gui/textmask.tga").let {
+ TextureRegionPack(it, maskOffWidth, capsuleHeight)
+ }
+
+ private var mode = 0
+ private var modeNext = 0
+ private var transitionAkku = 0f
+
+ private var textScroll = 0f
+
+ private val MODE_IDLE = 0
+ private val MODE_NOW_PLAYING = 1
+ private val MODE_PLAYING = 2
+ private val MODE_MOUSE_UP = 64
+ private val MODE_SHOW_LIST = 128
+
+ private var colourEdge = Color(0xFFFFFF_40.toInt())
+ private val colourBack = Color.BLACK
+
+ private val colourText = Color(0xf0f0f0ff.toInt())
+ private val colourMeter = Color(0xf0f0f0ff.toInt())
+ private val colourMeter2 = Color(0xf0f0f080.toInt())
+
+ init {
+ setAsAlwaysVisible()
+ }
+
+ override fun renderUI(batch: SpriteBatch, camera: OrthographicCamera) {
+ batch.end()
+
+
+ renderNameToFBO(batch, camera, AudioMixer.musicTrack.currentTrack?.name ?: "", 0f..(width - 2*STRIP_W - capsuleHeight + maskOffWidth))
+
+
+
+ batch.begin()
+
+ val posX = ((Toolkit.drawWidth - width) / 2).toFloat()
+ val posY = (App.scr.height - App.scr.tvSafeGraphicsHeight - height).toFloat()
+
+ blendNormalStraightAlpha(batch)
+ drawBaloon(batch, posX, posY, width.toFloat(), height - capsuleHeight.toFloat())
+ drawText(batch, posX, posY)
+ drawFreqMeter(batch, posX + width - 18, posY + height - (capsuleHeight / 2) + 1)
+
+ batch.color = Color.WHITE
+ }
+
+ private fun drawBaloon(batch: SpriteBatch, x: Float, y: Float, width: Float, height: Float) {
+ val x = x - capsuleMosaicSize
+ for (k in 0..3 step 3) {
+ batch.color = if (k == 0) colourEdge else colourBack
+
+ // top left
+ batch.draw(baloonTexture.get(k, 0), x, y)
+ // top
+ batch.draw(baloonTexture.get(k+1, 0), x + capsuleMosaicSize, y, width, capsuleMosaicSize.toFloat())
+ // top right
+ batch.draw(baloonTexture.get(k+2, 0), x + capsuleMosaicSize + width, y)
+ if (height > 0) {
+ // left
+ batch.draw(baloonTexture.get(k, 1), x, y + capsuleMosaicSize)
+ // centre
+ batch.draw(baloonTexture.get(k+1, 1), x + capsuleMosaicSize, y + capsuleMosaicSize, width, height)
+ // right
+ batch.draw(baloonTexture.get(k+2, 1), x + capsuleMosaicSize + width, y + capsuleMosaicSize)
+ }
+ // bottom left
+ batch.draw(baloonTexture.get(k, 2), x, y + capsuleMosaicSize + height)
+ // bottom
+ batch.draw(baloonTexture.get(k+1, 2), x + capsuleMosaicSize, y + capsuleMosaicSize + height, width, capsuleMosaicSize.toFloat())
+ // bottom right
+ batch.draw(baloonTexture.get(k+2, 2), x + capsuleMosaicSize + width, y + capsuleMosaicSize + height)
+ }
+ }
+
+ private fun drawText(batch: SpriteBatch, posX: Float, posY: Float) {
+ batch.color = colourText
+ batch.draw(nameFBO.colorBufferTexture, posX - maskOffWidth, posY - 1)
+ }
+
+ private fun renderNameToFBO(batch: SpriteBatch, camera: OrthographicCamera, str: String, window: ClosedFloatingPointRange) {
+ nameFBO.inAction(camera, batch) {
+ batch.inUse {
+ batch.color = Color.WHITE
+ // draw text
+ gdxClearAndEnableBlend(0f, 0f, 0f, 0f)
+ blendNormalStraightAlpha(batch)
+ App.fontGameFBO.draw(batch, str, maskOffWidth.toFloat() - textScroll, 0f)
+
+ // mask off the area
+ batch.color = Color.WHITE
+ blendAlphaMask(batch)
+ batch.draw(textmask.get(0, 0), window.start, 0f)
+ batch.draw(textmask.get(1, 0), window.start + maskOffWidth, 0f, window.endInclusive - window.start, capsuleHeight.toFloat())
+ batch.draw(textmask.get(2, 0), window.start + window.endInclusive + maskOffWidth, 0f)
+ batch.draw(textmask.get(3, 0), window.start + window.endInclusive + 2 * maskOffWidth, 0f, 1000f, capsuleHeight.toFloat())
+ }
+ }
+ }
+
+ private val FFTSIZE = 1024
+ private val inBuf = Array(2) { FloatArray(FFTSIZE) }
+ private fun sin2(x: Double) = sin(x).pow(2)
+ private val fftWin = FloatArray(FFTSIZE) { sin2(PI * it / FFTSIZE).toFloat() } // hann
+ private val oldFFTmagn = DoubleArray(FFTSIZE / 2) { 0.0 }
+ private val chsum = ComplexArray(FloatArray(FFTSIZE * 2))
+ private val fftOut = ComplexArray(FloatArray(FFTSIZE * 2))
+ private val binHeights = FloatArray(FFTSIZE / 2)
+ private val FFT_SMOOTHING_FACTOR = BasicDebugInfoWindow.getSmoothingFactor(1600)
+ private val lowlim = -36.0f
+ private val STRIP_W = 9f
+
+ private val fftBinIndices = arrayOf(
+ 0..3,
+ 4..12,
+ 13..39,
+ 40..121,
+ 122 until FFTSIZE / 2
+ ) // 60-18000 at 1024 (https://www.desmos.com/calculator/vkxhrzfam3)
+ private val fftBarHeights = FloatArray(5)
+
+ override fun updateUI(delta: Float) {
+ val inbuf = AudioMixer.musicTrack.extortField("processor")!!.extortField>("fout1")!!
+ push(inbuf[0], inBuf[0])
+ push(inbuf[1], inBuf[1])
+ for (i in 0 until FFTSIZE) {
+ chsum.reim[2*i] = (inBuf[0][i] + inBuf[1][i]) * fftWin[i]
+ }
+
+ FFT.fftInto(chsum, fftOut)
+ }
+
+ private fun drawFreqMeter(batch: SpriteBatch, posX: Float, posY: Float) {
+ // apply slope to the fft bins, also converts fullscale to decibels
+ for (bin in binHeights.indices) {
+ val freqR = (TerrarumAudioMixerTrack.SAMPLING_RATED / FFTSIZE) * (bin + 1)
+ val magn0 = fftOut.reim[2 * bin].absoluteValue / FFTSIZE * (freqR / 10.0) // apply slope
+ val magn = FastMath.interpolateLinear(FFT_SMOOTHING_FACTOR, magn0, oldFFTmagn[bin])
+ val magnLog = fullscaleToDecibels(magn)
+
+ val h = (-(magnLog - lowlim) / lowlim * STRIP_W).toFloat().coerceAtLeast(0.5f)
+
+ binHeights[bin] = h
+
+ oldFFTmagn[bin] = magn
+ }
+
+ fftBinIndices.mapIndexed { i, range ->
+ fftBarHeights[i] = binHeights.slice(range).average().toFloat()
+ }
+
+ batch.color = colourMeter2
+ fftBarHeights.forEachIndexed { index, h ->
+ Toolkit.fillArea(batch, posX + index*4f, posY - h, 3f, 2*h + 1)
+ }
+
+ batch.color = colourMeter
+ fftBarHeights.forEachIndexed { index, h ->
+ Toolkit.fillArea(batch, posX + index*4f, posY - h, 2f, 2*h)
+ }
+ }
+
+ override fun dispose() {
+ baloonTexture.dispose()
+ }
+
+
+ private fun push(samples: FloatArray, buf: FloatArray) {
+ if (samples.size >= FFTSIZE) {
+ // overwrite
+ System.arraycopy(samples, samples.size - buf.size, buf, 0, buf.size)
+ }
+ else {
+ // shift samples
+ System.arraycopy(buf, samples.size, buf, 0, buf.size - samples.size)
+ // write to the buf
+ System.arraycopy(samples, 0, buf, buf.size - samples.size, samples.size)
+ }
+ }
+}
\ No newline at end of file
diff --git a/assets/mods/basegame/metadata.properties b/assets/mods/basegame/metadata.properties
index 80c4be0f4..4c8be92c3 100644
--- a/assets/mods/basegame/metadata.properties
+++ b/assets/mods/basegame/metadata.properties
@@ -54,6 +54,7 @@ version=0.4.0
jar=
# Sha256sum of the External JAR, if any
+# The hash will not be checked if the game is running on the development mode
jarhash=
# Modules that must be pre-installed, separated by semicolons (;)
diff --git a/assets/mods/musicplayer/MusicPlayer.jar b/assets/mods/musicplayer/MusicPlayer.jar
new file mode 100644
index 000000000..96ec2e2bc
--- /dev/null
+++ b/assets/mods/musicplayer/MusicPlayer.jar
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:50da851a5d5c61fdfd1ad719ea4162be71d529f0706e4d4b7e97088f92ab9c02
+size 2072631
diff --git a/assets/mods/musicplayer/gui/blob.tga b/assets/mods/musicplayer/gui/blob.tga
new file mode 100644
index 000000000..7645cc546
--- /dev/null
+++ b/assets/mods/musicplayer/gui/blob.tga
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a531c90abf4d715e4b6af03109af50815ac8d4f2a4c28e73ed36ba26b8f0d2e5
+size 16218
diff --git a/assets/mods/musicplayer/gui/textmask.tga b/assets/mods/musicplayer/gui/textmask.tga
new file mode 100644
index 000000000..4a751729a
--- /dev/null
+++ b/assets/mods/musicplayer/gui/textmask.tga
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2bbd1cf9c86c9d80c5daf8fcc0be73cac8eb3c84624d370244bc944d378abc6b
+size 3602
diff --git a/assets/mods/musicplayer/metadata.properties b/assets/mods/musicplayer/metadata.properties
new file mode 100644
index 000000000..31a47789c
--- /dev/null
+++ b/assets/mods/musicplayer/metadata.properties
@@ -0,0 +1,10 @@
+propername=Terrarum Music Player
+description=Simple Music Player Widget
+author=CuriousTo\uA75Bvald
+package=net.torvald.terrarum.musicplayer
+entrypoint=net.torvald.terrarum.musicplayer.EntryPoint
+releasedate=2023-12-31
+version=1.0.0
+jar=MusicPlayer.jar
+jarhash=0
+dependency=basegame 0.4.0
diff --git a/src/net/torvald/terrarum/App.java b/src/net/torvald/terrarum/App.java
index dbdefd2bb..4dd718434 100644
--- a/src/net/torvald/terrarum/App.java
+++ b/src/net/torvald/terrarum/App.java
@@ -481,6 +481,7 @@ public class App implements ApplicationListener {
if (Gdx.app != null) {
Gdx.app.exit();
}
+ e.printStackTrace();
new GameCrashHandler(e);
}
}
diff --git a/src/net/torvald/terrarum/ModMgr.kt b/src/net/torvald/terrarum/ModMgr.kt
index 64c38a62a..5a5abdb14 100644
--- a/src/net/torvald/terrarum/ModMgr.kt
+++ b/src/net/torvald/terrarum/ModMgr.kt
@@ -16,9 +16,11 @@ import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.itemproperties.ItemCodex
import net.torvald.terrarum.itemproperties.MaterialCodex
import net.torvald.terrarum.langpack.Lang
+import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.worldgenerator.OregenParams
import net.torvald.terrarum.modulebasegame.worldgenerator.Worldgen
import net.torvald.terrarum.serialise.Common
+import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.utils.CSVFetcher
import net.torvald.terrarum.utils.JsonFetcher
import net.torvald.terrarum.utils.forEachSiblings
@@ -275,16 +277,16 @@ object ModMgr {
digester.reset()
val hash = digester.digest(File(jarFilePath).readBytes()).joinToString("","","") { it.toInt().and(255).toString(16).uppercase().padStart(2,'0') }
- if (jarHash != hash) {
+ if (!App.IS_DEVELOPMENT_BUILD && jarHash != hash) {
printdbg(this, "Hash expected: $jarHash, got: $hash")
throw IllegalStateException("Module Jarfile hash mismatch")
}
// check for module-info.java
- val moduleInfoPath = cl.getResources("module-info.class").toList().filter { it.toString().contains("$moduleName/$jar!/module-info.class") && it.toString().endsWith("module-info.class")}
+ /*val moduleInfoPath = cl.getResources("module-info.class").toList().filter { it.toString().contains("$moduleName/$jar!/module-info.class") && it.toString().endsWith("module-info.class")}
if (moduleInfoPath.isEmpty()) {
throw IllegalStateException("module-info not found on $moduleName")
- }
+ }*/
newClass = cl.loadClass(entryPoint)
}
@@ -771,6 +773,14 @@ object ModMgr {
}
}
+
+ object GameExtraGuiLoader {
+ internal val guis = ArrayList<(TerrarumIngame) -> UICanvas>()
+
+ @JvmStatic fun register(uiCreationFun: (TerrarumIngame) -> UICanvas) {
+ guis.add(uiCreationFun)
+ }
+ }
}
private class JarFileLoader(urls: Array) : URLClassLoader(urls) {
diff --git a/src/net/torvald/terrarum/Terrarum.kt b/src/net/torvald/terrarum/Terrarum.kt
index 63170f1ab..9fad0322a 100644
--- a/src/net/torvald/terrarum/Terrarum.kt
+++ b/src/net/torvald/terrarum/Terrarum.kt
@@ -472,6 +472,11 @@ fun blendMul(batch: SpriteBatch) {
batch.setBlendFunction(GL20.GL_DST_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA)
}
+fun blendAlphaMask(batch: SpriteBatch) {
+ batch.enableBlending()
+ batch.setBlendFunction(GL20.GL_ZERO, GL20.GL_SRC_ALPHA)
+}
+
/**
* Use demultiplier shader on GL Source (foreground) if source has semitransparency
*/
diff --git a/src/net/torvald/terrarum/audio/dsp/Scope.kt b/src/net/torvald/terrarum/audio/dsp/Scope.kt
index b88f2c65d..f8f9a4283 100644
--- a/src/net/torvald/terrarum/audio/dsp/Scope.kt
+++ b/src/net/torvald/terrarum/audio/dsp/Scope.kt
@@ -12,10 +12,10 @@ import net.torvald.terrarum.ui.Toolkit
import kotlin.math.*
class Scope : TerrarumAudioFilter() {
- val backbufL = Array((4096f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) {
+ val backbufL = Array((6144f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) {
FloatArray(AUDIO_BUFFER_SIZE)
}
- val backbufR = Array((4096f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) {
+ val backbufR = Array((6144f / AUDIO_BUFFER_SIZE).roundToInt().coerceAtLeast(1)) {
FloatArray(AUDIO_BUFFER_SIZE)
}
@@ -64,11 +64,11 @@ class Scope : TerrarumAudioFilter() {
// plot dots
for (i in 0 until TerrarumAudioMixerTrack.AUDIO_BUFFER_SIZE) {
- val y0 = inbuf[0][i] * 0.7
- val x0 = -inbuf[1][i] * 0.7 // rotate the domain by -90 deg
+ val y0 = +inbuf[0][i] * 2f
+ val x0 = -inbuf[1][i] * 2f// rotate the domain by -90 deg
- val x = (+x0*sqrt2p -y0*sqrt2p) * 1.414
- val y = (-x0*sqrt2p -y0*sqrt2p) * 1.414 // further rotate by -45 deg then flip along the y axis
+ val x = (+x0*sqrt2p -y0*sqrt2p) * 1.4142
+ val y = (-x0*sqrt2p -y0*sqrt2p) * 1.4142 // further rotate by -45 deg then flip along the y axis
backbufL[0][i] = x.toFloat()
backbufR[0][i] = y.toFloat()
diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt
index d3404bbce..4df0ba4e7 100644
--- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt
+++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt
@@ -641,7 +641,10 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) {
ingameUpdateThread = ThreadIngameUpdate(this)
updateThreadWrapper = Thread(ingameUpdateThread, "Terrarum UpdateThread")
-
+ // add extra UIs from the other modules
+ ModMgr.GameExtraGuiLoader.guis.forEach {
+ uiContainer.add(it(this))
+ }
// these need to appear on top of any others
uiContainer.add(notifier)
diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt
index 1f8a0246c..50f1118db 100644
--- a/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt
+++ b/src/net/torvald/terrarum/modulebasegame/TerrarumMusicGovernor.kt
@@ -24,7 +24,7 @@ data class MusicContainer(
val name: String,
val file: File,
val gdxMusic: Music,
- val songFinishedHook: (Music) -> Unit
+ internal var songFinishedHook: (Music) -> Unit = {}
) {
val samplingRate: Int
val codec: String
@@ -142,7 +142,9 @@ class TerrarumMusicGovernor : MusicGovernor() {
it.nameWithoutExtension.replace('_', ' ').split(" ").map { it.capitalize() }.joinToString(" "),
it,
Gdx.audio.newMusic(Gdx.files.absolute(it.absolutePath))
- ) { stopMusic() }
+ ).also { muscon ->
+ muscon.songFinishedHook = { stopMusic(muscon) }
+ }
}
catch (e: GdxRuntimeException) {
e.printStackTrace()
@@ -170,7 +172,16 @@ class TerrarumMusicGovernor : MusicGovernor() {
private var ambientsBin: ArrayList = ArrayList(ambients.indices.toList().shuffled())
+ private val musicStartHooks = ArrayList<(MusicContainer) -> Unit>()
+ private val musicStopHooks = ArrayList<(MusicContainer) -> Unit>()
+ fun addMusicStartHook(f: (MusicContainer) -> Unit) {
+ musicStartHooks.add(f)
+ }
+
+ fun addMusicStopHook(f: (MusicContainer) -> Unit) {
+ musicStopHooks.add(f)
+ }
init {
songs.forEach {
@@ -193,18 +204,20 @@ class TerrarumMusicGovernor : MusicGovernor() {
protected var ambState = 0
protected var ambFired = false
- private fun stopMusic() {
+ private fun stopMusic(song: MusicContainer?) {
musicState = STATE_INTERMISSION
intermissionAkku = 0f
intermissionLength = 30f + 30f * Math.random().toFloat() // 30s-60s
musicFired = false
+ musicStopHooks.forEach { if (song != null) { it(song) } }
printdbg(this, "Intermission: $intermissionLength seconds")
}
private fun startMusic(song: MusicContainer) {
AudioMixer.startMusic(song)
printdbg(this, "Now playing: $song")
- INGAME.sendNotification("Now Playing $EMDASH ${song.name}")
+// INGAME.sendNotification("Now Playing $EMDASH ${song.name}")
+ musicStartHooks.forEach { it(song) }
musicState = STATE_PLAYING
}
@@ -220,7 +233,7 @@ class TerrarumMusicGovernor : MusicGovernor() {
private fun startAmbient(song: MusicContainer) {
AudioMixer.startAmb(song)
printdbg(this, "Now playing: $song")
- INGAME.sendNotification("Now Playing $EMDASH ${song.name}")
+// INGAME.sendNotification("Now Playing $EMDASH ${song.name}")
ambState = STATE_PLAYING
}
@@ -285,7 +298,7 @@ class TerrarumMusicGovernor : MusicGovernor() {
override fun dispose() {
AudioMixer.requestFadeOut(AudioMixer.fadeBus, AudioMixer.DEFAULT_FADEOUT_LEN) // explicit call for fade-out when the game instance quits
- stopMusic()
+ stopMusic(AudioMixer.musicTrack.currentTrack)
stopAmbient()
}
}
diff --git a/src/net/torvald/terrarum/modulebasegame/ui/UILoadList.kt b/src/net/torvald/terrarum/modulebasegame/ui/UILoadList.kt
index d698dd8ff..a032fe5fd 100644
--- a/src/net/torvald/terrarum/modulebasegame/ui/UILoadList.kt
+++ b/src/net/torvald/terrarum/modulebasegame/ui/UILoadList.kt
@@ -279,7 +279,7 @@ class UILoadList(val full: UILoadSavegame) : UICanvas() {
}
override fun touchUp(screenX: Int, screenY: Int, pointer: Int, button: Int): Boolean {
- playerCells.forEach { it.touchUp(screenX, screenY, pointer, button) }
+ playerCells.slice(playerCells.indices).forEach { it.touchUp(screenX, screenY, pointer, button) } // to prevent ConcurrentModificationException
return true
}
diff --git a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt
index 4a8f7a087..73df624cc 100644
--- a/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt
+++ b/src/net/torvald/terrarum/ui/BasicDebugInfoWindow.kt
@@ -418,7 +418,7 @@ class BasicDebugInfoWindow : UICanvas() {
fun getSmoothingFactor(sampleCount: Int) = (1.0 - (256.0 / sampleCount))
val PEAK_SMOOTHING_FACTOR = getSmoothingFactor(640)
- val FFT_SMOOTHING_FACTOR = getSmoothingFactor(960)
+ val FFT_SMOOTHING_FACTOR = getSmoothingFactor(1200)
val LAMP_SMOOTHING_FACTOR = getSmoothingFactor(3200)
val RMS_SMOOTHING_FACTOR = getSmoothingFactor(12000)
}