music player widget as a separate module

This commit is contained in:
minjaesong
2023-12-24 03:13:35 +09:00
parent b5312da2f0
commit c4836a3fe2
24 changed files with 370 additions and 33 deletions

View File

@@ -481,6 +481,7 @@ public class App implements ApplicationListener {
if (Gdx.app != null) {
Gdx.app.exit();
}
e.printStackTrace();
new GameCrashHandler(e);
}
}

View File

@@ -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<URL>) : URLClassLoader(urls) {

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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