diff --git a/assets/mods/basegame/crafting/fixtures.json b/assets/mods/basegame/crafting/fixtures.json index 7fd5a7199..1703011f0 100644 --- a/assets/mods/basegame/crafting/fixtures.json +++ b/assets/mods/basegame/crafting/fixtures.json @@ -62,5 +62,12 @@ "ingredients": [ [1, 20, "$WOOD"] /* 1 chest = 20 wood */ ] + }, + + "item@basegame:30": { /* turntable */ + "workbench": "basiccrafting", + "ingredients": [ + [1, 4, "item@basegame:144", 14, "$WOOD", 10, "item@basegame:113"] /* 1 turntable = 4 quartz, 14 wood, 10 iron */ + ] } } \ No newline at end of file diff --git a/assets/mods/basegame/items/itemid.csv b/assets/mods/basegame/items/itemid.csv index 726946e80..7704d21cb 100644 --- a/assets/mods/basegame/items/itemid.csv +++ b/assets/mods/basegame/items/itemid.csv @@ -28,6 +28,7 @@ id;classname;tags 27;net.torvald.terrarum.modulebasegame.gameitems.ItemFurnaceAndAnvil;FIXTURE,CRAFTING 28;net.torvald.terrarum.modulebasegame.gameitems.ItemJukebox;FIXTURE,MUSIC 29;net.torvald.terrarum.modulebasegame.gameitems.ItemCharcoal;COMBUSTIBLE +30;net.torvald.terrarum.modulebasegame.gameitems.ItemMusicalTurntable;FIXTURE,MUSIC # ingots 26;net.torvald.terrarum.modulebasegame.gameitems.IngotSteel;INGOT @@ -78,15 +79,15 @@ id;classname;tags # data storage (discs; 256) # 32768 is a reserved number for a blank disc -32769;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc01;MUSIC -32770;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc02;MUSIC -32771;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc03;MUSIC -32772;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc04;MUSIC -32773;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc05;MUSIC -32774;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc06;MUSIC -32775;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc07;MUSIC -32776;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc08;MUSIC -32777;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc09;MUSIC +32769;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc01;MUSIC,PHONO +32770;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc02;MUSIC,PHONO +32771;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc03;MUSIC,PHONO +32772;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc04;MUSIC,PHONO +32773;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc05;MUSIC,PHONO +32774;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc06;MUSIC,PHONO +32775;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc07;MUSIC,PHONO +32776;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc08;MUSIC,PHONO +32777;net.torvald.terrarum.modulebasegame.gameitems.MusicDisc09;MUSIC,PHONO # data storage (tapestries; 256) #33023;net.torvald.terrarum.modulebasegame.gameitems.ItemTapestry;FIXTURE diff --git a/assets/mods/basegame/items/items.tga b/assets/mods/basegame/items/items.tga index 90518ab83..5d8247f84 100644 --- a/assets/mods/basegame/items/items.tga +++ b/assets/mods/basegame/items/items.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e62409fc2fb24b70f68d1192803f4f9a2da9ff72c966865ead05c26ee16594bb +oid sha256:31be701c2aabd51ac0e2b9b2f95d75086f5f2a86e02e61aea5477a5d415eab68 size 2408466 diff --git a/assets/mods/basegame/locales/en/items.json b/assets/mods/basegame/locales/en/items.json index 22b21c9cd..9b354c1bb 100644 --- a/assets/mods/basegame/locales/en/items.json +++ b/assets/mods/basegame/locales/en/items.json @@ -62,6 +62,7 @@ "ITEM_SMELTER_SMALL": "Small Smelter", "ITEM_STORAGE_CHEST": "Storage Chest", "ITEM_TIKI_TORCH": "Tiki Torch", + "ITEM_TURNTABLE": "Turntable", "ITEM_TYPEWRITER": "Typewriter", "ITEM_WIRE": "Wire", "ITEM_WIRE_CUTTER": "Wire Cutter", diff --git a/assets/mods/basegame/locales/koKR/items.json b/assets/mods/basegame/locales/koKR/items.json index efdf2ea6f..bd9889c9c 100644 --- a/assets/mods/basegame/locales/koKR/items.json +++ b/assets/mods/basegame/locales/koKR/items.json @@ -62,6 +62,7 @@ "ITEM_SMELTER_SMALL": "소형 고로", "ITEM_STORAGE_CHEST": "보관상자", "ITEM_TIKI_TORCH": "티키 토치", + "ITEM_TURNTABLE": "전축", "ITEM_TYPEWRITER": "타자기", "ITEM_WIRE": "전선", "ITEM_WIRE_CUTTER": "전선 절단기", diff --git a/assets/mods/basegame/sprites/fixtures/turntable.tga b/assets/mods/basegame/sprites/fixtures/turntable.tga new file mode 100644 index 000000000..0af3dd59d --- /dev/null +++ b/assets/mods/basegame/sprites/fixtures/turntable.tga @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:aebafc17465d04c77fbb9b90c929a14f5fbd429a86918a7c184821fffe7f454c +size 4114 diff --git a/src/net/torvald/terrarum/audio/dsp/LoFi.kt b/src/net/torvald/terrarum/audio/dsp/LoFi.kt index d6f9a99c5..900461543 100644 --- a/src/net/torvald/terrarum/audio/dsp/LoFi.kt +++ b/src/net/torvald/terrarum/audio/dsp/LoFi.kt @@ -24,7 +24,7 @@ import kotlin.math.tanh open class LoFi( staticModule: String, staticPath: String, irModule: String, irPath: String, - val crossfeed: Float, gain: Float = 1f / 256f + val crossfeed: Float, gain: Float = 1f / 256f, saturationLim: Float = 1f ): TerrarumAudioFilter(), DspCompressor { override val downForce = arrayOf(1.0f, 1.0f) @@ -72,8 +72,9 @@ open class LoFi( * Default function is `tanh(x)` */ open fun saturate(v: Float): Float { - return tanh(v) + return K * tanh(v / K) } + private val K = saturationLim.coerceIn(0f, 1f) override fun drawDebugView(batch: SpriteBatch, x: Int, y: Int) { convolver.drawDebugView(batch, x, y) diff --git a/src/net/torvald/terrarum/audio/dsp/Phono.kt b/src/net/torvald/terrarum/audio/dsp/Phono.kt index 8f4f5524a..8d3a10d70 100644 --- a/src/net/torvald/terrarum/audio/dsp/Phono.kt +++ b/src/net/torvald/terrarum/audio/dsp/Phono.kt @@ -7,9 +7,9 @@ import net.torvald.terrarum.ModMgr * * Created by minjaesong on 2024-01-24. */ -class Phono(irModule: String, irPath: String, crossfeed: Float, gain: Float) : LoFi( +class Phono(irModule: String, irPath: String, crossfeed: Float, gain: Float, saturationLim: Float) : LoFi( "basegame", "audio/effects/static/phono_pops.ogg", - irModule, irPath, crossfeed, gain + irModule, irPath, crossfeed, gain, saturationLim ) /** @@ -17,9 +17,9 @@ class Phono(irModule: String, irPath: String, crossfeed: Float, gain: Float) : L * * Created by minjaesong on 2024-01-24. */ -class Tape(irModule: String, irPath: String, crossfeed: Float, gain: Float) : LoFi( +class Tape(irModule: String, irPath: String, crossfeed: Float, gain: Float, saturationLim: Float) : LoFi( "basegame", "audio/effects/static/tape_hiss.ogg", - irModule, irPath, crossfeed, gain + irModule, irPath, crossfeed, gain, saturationLim ) /** @@ -29,7 +29,7 @@ class Tape(irModule: String, irPath: String, crossfeed: Float, gain: Float) : Lo * * Created by minjaesong on 2024-01-24. */ -class Holo(irModule: String, irPath: String, crossfeed: Float, gain: Float) : LoFi( +class Holo(irModule: String, irPath: String, crossfeed: Float, gain: Float, saturationLim: Float) : LoFi( "basegame", "audio/effects/static/film_pops_lowpass.ogg", - irModule, irPath, crossfeed, gain + irModule, irPath, crossfeed, gain, saturationLim ) \ No newline at end of file diff --git a/src/net/torvald/terrarum/gameitems/GameItem.kt b/src/net/torvald/terrarum/gameitems/GameItem.kt index 5afd740d7..0d00e016f 100644 --- a/src/net/torvald/terrarum/gameitems/GameItem.kt +++ b/src/net/torvald/terrarum/gameitems/GameItem.kt @@ -379,6 +379,7 @@ abstract class GameItem(val originalID: ItemID) : Comparable, Cloneabl fun hasTag(s: String) = tags.contains(s) fun hasAllTags(s: List) = tags.containsAll(s) + fun hasAllTagOf(vararg s: String) = s.all { hasTag(it) } companion object { diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt index 498b0a5b0..6f559822b 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureJukebox.kt @@ -18,6 +18,7 @@ import net.torvald.terrarum.audio.dsp.LoFi import net.torvald.terrarum.audio.dsp.NullFilter import net.torvald.terrarum.audio.dsp.Phono import net.torvald.terrarum.gameactors.AVKey +import net.torvald.terrarum.gameactors.Actor import net.torvald.terrarum.gameactors.Hitbox import net.torvald.terrarum.gameactors.Lightbox import net.torvald.terrarum.gameitems.ItemID @@ -217,19 +218,11 @@ class FixtureJukebox : Electric, PlaysMusic { } private fun loadConvolver(it: TerrarumAudioMixerTrack?) { - it?.filters?.set(filterIndex, Phono( - "basegame", - "audio/convolution/Soundwoofer - large_speaker_Marshall JVM 205C SM57 A 0 0 1.bin", - 0f, 5f / 16f - )) + Companion.loadConvolver(filterIndex, it, "basegame", "audio/convolution/Soundwoofer - large_speaker_Marshall JVM 205C SM57 A 0 0 1.bin") } private fun unloadConvolver(music: MusicContainer?) { - if (music != null) { - musicTracks[music]?.let { - it.filters[filterIndex] = NullFilter - } - } + Companion.unloadConvolver(this, filterIndex, music) } override fun reload() { @@ -242,8 +235,25 @@ class FixtureJukebox : Electric, PlaysMusic { override fun dispose() { App.audioMixerReloadHooks.remove(this) super.dispose() -// testMusic.gdxMusic.dispose() // no need to dispose of backlamp and playmech: they share the same texture with the main sprite } + + companion object { + fun loadConvolver(filterIndex: Int, it: TerrarumAudioMixerTrack?, module: String, path: String, gain: Float = 5f / 16f, satLim: Float = 1f) { + it?.filters?.set(filterIndex, Phono( + module, + path, + 0f, gain, satLim + )) + } + + fun unloadConvolver(actor: Actor, filterIndex: Int, music: MusicContainer?) { + if (music != null) { + actor.musicTracks[music]?.let { + it.filters[filterIndex] = NullFilter + } + } + } + } } \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMusicalTurntable.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMusicalTurntable.kt new file mode 100644 index 000000000..cbe4dee6c --- /dev/null +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureMusicalTurntable.kt @@ -0,0 +1,181 @@ +package net.torvald.terrarum.modulebasegame.gameactors + +import com.badlogic.gdx.Gdx +import net.torvald.spriteanimation.SheetSpriteAnimation +import net.torvald.terrarum.* +import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE +import net.torvald.terrarum.audio.AudioMixer +import net.torvald.terrarum.audio.TerrarumAudioMixerTrack +import net.torvald.terrarum.gameactors.AVKey +import net.torvald.terrarum.gameitems.GameItem +import net.torvald.terrarum.gameitems.ItemID +import net.torvald.terrarum.langpack.Lang +import net.torvald.terrarum.modulebasegame.MusicContainer +import net.torvald.terrarum.modulebasegame.TerrarumMusicGovernor +import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase +import net.torvald.terrarum.modulebasegame.gameitems.ItemFileRef +import net.torvald.terrarum.modulebasegame.gameitems.MusicDiscHelper +import net.torvald.terrarum.modulebasegame.gameitems.PickaxeCore +import net.torvald.terrarum.ui.MouseLatch +import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack +import org.dyn4j.geometry.Vector2 + +/** + * Created by minjaesong on 2024-02-07. + */ +class FixtureMusicalTurntable : Electric, PlaysMusic { + + constructor() : super( + BlockBox(BlockBox.NO_COLLISION, 1, 1), + nameFun = { Lang["ITEM_TURNTABLE"] } + ) + + @Transient var musicNowPlaying: MusicContainer? = null; private set + + @Transient private val filterIndex = 0 + + val musicIsPlaying: Boolean + get() = musicNowPlaying != null + + init { + val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/turntable.tga") + density = 1400.0 + setHitboxDimension(TILE_SIZE * 1, TILE_SIZE * 1, 0, 0) + + makeNewSprite(TextureRegionPack(itemImage.texture, TILE_SIZE * 1, TILE_SIZE * 1)).let { + it.setRowsAndFrames(2,2) + it.currentRow = 1 + } + + actorValue[AVKey.BASEMASS] = 20.0 + + + setWireSinkAt(0, 0, "appliance_power") + setWireConsumptionAt(0, 2, Vector2(80.0, 0.0)) + + + App.audioMixerReloadHooks[this] = { + loadConvolver(musicTracks[musicNowPlaying]) + } + + despawnHook = { + stopGracefully() + } + } + + internal var disc: ItemID? = null + + @Transient private val clickLatch = MouseLatch(listOf(App.getConfigInt("config_mousesecondary"))) + + override val canBeDespawned: Boolean + get() = disc == null + + override fun update(delta: Float) { + super.update(delta) + + // right click + if (mouseUp) { + clickLatch.latch { + if (disc == null) { + if (INGAME.actorNowPlaying != null) { + val itemOnGrip = + INGAME.actorNowPlaying!!.inventory.itemEquipped.get(GameItem.EquipPosition.HAND_GRIP) + val itemProp = ItemCodex[itemOnGrip] + + if (itemProp?.hasAllTagOf("MUSIC", "PHONO") == true) { + disc = itemOnGrip + INGAME.actorNowPlaying!!.removeItem(itemOnGrip!!) + playDisc() + } + } + } + else { + stopGracefully() + PickaxeCore.dropItem( + disc!!, + intTilewiseHitbox.canonicalX.toInt(), + intTilewiseHitbox.canonicalY.toInt() + ) + disc = null + } + } + } + + + // supress the normal background music playback + if (musicIsPlaying && !flagDespawn) { + (INGAME.musicGovernor as TerrarumMusicGovernor).stopMusic(this, true) + } + } + + fun playDisc() { + if (disc == null) return + + App.printdbg(this, "Play disc!") + val musicFile = (ItemCodex[disc] as? ItemFileRef)?.getAsGdxFile() + + if (musicFile != null) { + val (title, artist) = MusicDiscHelper.getMetadata(musicFile) + + App.printdbg(this, "Title: $title, artist: $artist") + + musicNowPlaying = MusicContainer(title, musicFile.file(), Gdx.audio.newMusic(musicFile)) { + unloadConvolver(musicNowPlaying) + musicNowPlaying?.gdxMusic?.tryDispose() + musicNowPlaying = null + + App.printdbg(this, "Stop music $title - $artist") + + // can't call stopDiscPlayback() because of the recursion + + (INGAME.musicGovernor as TerrarumMusicGovernor).stopMusic(this, pauseLen = (INGAME.musicGovernor as TerrarumMusicGovernor).getRandomMusicInterval()) + } + + App.audioMixer.requestFadeOut(App.audioMixer.musicTrack, AudioMixer.DEFAULT_FADEOUT_LEN / 2f) { + startAudio(musicNowPlaying!!) { loadConvolver(it) } + } + + (sprite as SheetSpriteAnimation).currentRow = 0 + } + + } + + /** + * Try to stop the disc being played, and reset the background music cue + */ + fun stopGracefully() { + stopDiscPlayback() + (INGAME.musicGovernor as TerrarumMusicGovernor).stopMusic(this, pauseLen = (INGAME.musicGovernor as TerrarumMusicGovernor).getRandomMusicInterval()) + + } + + private fun stopDiscPlayback() { + musicNowPlaying?.let { + stopAudio(it) + unloadConvolver(it) + } + + (sprite as SheetSpriteAnimation).currentRow = 1 + } + + private fun loadConvolver(it: TerrarumAudioMixerTrack?) { + FixtureJukebox.loadConvolver(filterIndex, it, "basegame", "audio/convolution/Soundwoofer - small_speaker_Gallien Krueger GK 250ML B5 Left A 230 200 320.bin", 3.5f / 16f, 0.8f) + } + + private fun unloadConvolver(music: MusicContainer?) { + FixtureJukebox.unloadConvolver(this, filterIndex, music) + } + + override fun reload() { + super.reload() + // cannot resume playback, just stop the music + musicNowPlaying = null + } + + override fun dispose() { + App.audioMixerReloadHooks.remove(this) + super.dispose() + + // no need to dispose of backlamp and playmech: they share the same texture with the main sprite + } +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/modulebasegame/gameitems/ItemJukebox.kt b/src/net/torvald/terrarum/modulebasegame/gameitems/ItemJukebox.kt index 5a34af476..8ebbaa9f5 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameitems/ItemJukebox.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameitems/ItemJukebox.kt @@ -19,4 +19,21 @@ class ItemJukebox(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald override var baseToolSize: Double? = baseMass override var originalName = "ITEM_JUKEBOX" +} + +/** + * Created by minjaesong on 2024-02-07. + */ +class ItemMusicalTurntable(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureMusicalTurntable") { + + + override var baseMass = 20.0 + override val isDynamic = false + override val materialId = "" + override val itemImage: TextureRegion + get() = CommonResourcePool.getAsItemSheet("basegame.items").get(7,3) + + override var baseToolSize: Double? = baseMass + override var originalName = "ITEM_TURNTABLE" + } \ No newline at end of file diff --git a/src/net/torvald/unsafe/UnsafePtr.kt b/src/net/torvald/unsafe/UnsafePtr.kt index 8f430d597..9495dd76e 100644 --- a/src/net/torvald/unsafe/UnsafePtr.kt +++ b/src/net/torvald/unsafe/UnsafePtr.kt @@ -127,8 +127,8 @@ internal class UnsafePtr(pointer: Long, allocSize: Long) { // appear (e.g. getting garbage values when it fucking shouldn't) // using ifs instead of assertions: inactive assert statements still slows down the app - if (destroyed) { throw DanglingPointerException("The pointer is already destroyed ($this)") } - if (index !in 0 until size) { throw AddressOverflowException("Index: $index; alloc size: $size") } +// if (destroyed) { throw DanglingPointerException("The pointer is already destroyed ($this)") } +// if (index !in 0 until size) { throw AddressOverflowException("Index: $index; alloc size: $size") } } operator fun get(index: Long): Byte { diff --git a/work_files/graphics/items/basegame_items.kra b/work_files/graphics/items/basegame_items.kra index 7d75d81cf..baaae9ef9 100644 --- a/work_files/graphics/items/basegame_items.kra +++ b/work_files/graphics/items/basegame_items.kra @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d54cc8a4bf962dfe61a6fe708e9a0cc0a043b890333a13749487286a47042313 -size 1157742 +oid sha256:5590cdabbe723d3769d966d6172b2811b55cfc86c4ec89b6c39f2204ecdbfb5a +size 1168632 diff --git a/work_files/graphics/sprites/fixtures/turntable.kra b/work_files/graphics/sprites/fixtures/turntable.kra new file mode 100644 index 000000000..15cc7d943 --- /dev/null +++ b/work_files/graphics/sprites/fixtures/turntable.kra @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:3689db97bbf51750c3a685374b79a9c2b1951d141b009162e6de4886928a41d3 +size 130339