diff --git a/assets/mods/basegame/items/itemid.csv b/assets/mods/basegame/items/itemid.csv index 349f52834..6f42519d0 100644 --- a/assets/mods/basegame/items/itemid.csv +++ b/assets/mods/basegame/items/itemid.csv @@ -7,3 +7,5 @@ "7";"net.torvald.terrarum.modulebasegame.gameitems.WireGraphDebugger" "8";"net.torvald.terrarum.modulebasegame.gameitems.ItemLogicSignalEmitter" "9";"net.torvald.terrarum.modulebasegame.gameitems.WireCutterAll" + +"999";"net.torvald.terrarum.modulebasegame.gameitems.ItemTapestry" diff --git a/src/net/torvald/terrarum/CommonResourcePool.kt b/src/net/torvald/terrarum/CommonResourcePool.kt index 992534336..80db29a14 100644 --- a/src/net/torvald/terrarum/CommonResourcePool.kt +++ b/src/net/torvald/terrarum/CommonResourcePool.kt @@ -115,10 +115,14 @@ object CommonResourcePool { return pool[identifier]!! } - fun getOrNull(identifier: String) = pool[identifier] - fun getOrDefault(identifier: String, defaultValue: Any) = pool.getOrDefault(identifier, defaultValue) - fun getOrPut(identifier: String, defaultValue: () -> Any) = pool.getOrPut(identifier, defaultValue) - fun getOrElse(identifier: String, defaultValue: () -> Any) = pool.getOrElse(identifier, defaultValue) + fun getOrNull(name: String) = pool[name] + fun getOrPut(name: String, loadfun: () -> Any) = CommonResourcePool.getOrPut(name, loadfun, null) + fun getOrPut(name: String, loadfun: () -> Any, killfun: ((Any) -> Unit)?): Any { + if (pool.containsKey(name)) return pool[name]!! + pool[name] = loadfun.invoke() + poolKillFun[name] = killfun + return pool[name]!! + } inline fun getAs(identifier: String) = get(identifier) as T fun getAsTextureRegionPack(identifier: String) = getAs(identifier) diff --git a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt index 148364893..287aa54b4 100644 --- a/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt +++ b/src/net/torvald/terrarum/modulebasegame/TerrarumIngame.kt @@ -727,7 +727,7 @@ open class TerrarumIngame(batch: FlippingSpriteBatch) : IngameInstance(batch) { /** RENDER CODE GOES HERE */ measureDebugTime("Ingame.Render") { renderGame() } - val autosaveInterval = App.getConfigInt("autosaveinterval") / 1000f + val autosaveInterval = App.getConfigInt("autosaveinterval").coerceAtLeast(60000) / 1000f if (autosaveTimer >= autosaveInterval) { queueAutosave() autosaveTimer -= autosaveInterval diff --git a/src/net/torvald/terrarum/modulebasegame/console/Inventory.kt b/src/net/torvald/terrarum/modulebasegame/console/Inventory.kt index 4c4c61185..6c8425837 100644 --- a/src/net/torvald/terrarum/modulebasegame/console/Inventory.kt +++ b/src/net/torvald/terrarum/modulebasegame/console/Inventory.kt @@ -14,14 +14,14 @@ import net.torvald.terrarum.modulebasegame.gameactors.Pocketed */ internal object Inventory : ConsoleCommand { - private var targetID: ActorID = PLAYER_REF_ID + private var targetID: ActorID = INGAME.actorNowPlaying?.referenceID ?: PLAYER_REF_ID override fun execute(args: Array) { if (args.size == 1) { printUsage() } else if (args[1] == "target") { - targetID = if (args[2].lowercase() == "player") PLAYER_REF_ID else args[2].toInt() + targetID = if (args[2].lowercase() == "player") (INGAME.actorNowPlaying?.referenceID ?: PLAYER_REF_ID) else args[2].toInt() } else { val actor = getActor() diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/DecodeTapestry.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/DecodeTapestry.kt index d172c3c8a..acfa87edf 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/DecodeTapestry.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/DecodeTapestry.kt @@ -126,7 +126,7 @@ object DecodeTapestry { if (colourModel != FORMAT_16 && colourModel != FORMAT_64) throw RuntimeException("Invalid colour model: $colourModel") - val width = file[7].toUint().shl(8) + file[6].toUint() + val width = file[6].toUint().shl(8) + file[7].toUint() val artNameBytes = ArrayList() val authorNameBytes = ArrayList() diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt index b576d6f9d..a4015a9e1 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureBase.kt @@ -23,6 +23,8 @@ interface Electric { /** * Protip: do not make child classes take any argument, especially no function (function "classes" have no zero-arg constructor) * + * Initialising Fixture after deserialisation: override `reload()` + * * Created by minjaesong on 2016-06-17. */ open class FixtureBase : ActorWithBody, CuedByTerrainChange { @@ -34,7 +36,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { @Transient var mainUI: UICanvas? = null var inventory: FixtureInventory? = null - protected constructor() : super(RenderOrder.BEHIND, PhysProperties.IMMOBILE, null) + private constructor() : super(RenderOrder.BEHIND, PhysProperties.IMMOBILE, null) constructor( @@ -130,7 +132,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { if (hasCollision) return false - printdbg(this, "spawn ${nameFun()}") + printdbg(this, "spawn fixture ${nameFun()}, tilewise dim: (${blockBox.width}, ${blockBox.height})") // set the position of this actor worldBlockPos = Point2i(posX, posY) @@ -161,8 +163,10 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { * Removes this instance of the fixture from the world */ open fun despawn() { - if (canBeDespawned) { + + if (this !is FixtureTapestry && canBeDespawned) { printdbg(this, "despawn at T${INGAME.WORLD_UPDATE_TIMER}: ${nameFun()}") + printStackTrace(this) // remove filler block forEachBlockbox { x, y -> @@ -181,6 +185,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange { } } else { +// printdbg(this, "despawn at T${INGAME.WORLD_UPDATE_TIMER}: ${nameFun()}") printdbg(this, "cannot despawn a fixture with non-empty inventory") } } diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt index d484ff092..013dec75d 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureInventory.kt @@ -105,10 +105,10 @@ open class FixtureInventory() { if (existingItem != null) { // if the item already exists val newCount = existingItem.qty - count - if (newCount < 0) { + /*if (newCount < 0) { throw Error("[${this.javaClass.canonicalName}] Tried to remove $count of $item, but the inventory only contains ${existingItem.qty} of them.") } - else if (newCount > 0) { + else*/ if (newCount > 0) { // decrement count existingItem.qty = newCount } @@ -120,7 +120,7 @@ open class FixtureInventory() { } } else { - throw Error("[${this.javaClass.canonicalName}] Tried to remove $item, but the inventory does not have it.") +// throw Error("[${this.javaClass.canonicalName}] Tried to remove $item, but the inventory does not have it.") } } diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTapestry.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTapestry.kt new file mode 100644 index 000000000..7e27a7f1a --- /dev/null +++ b/src/net/torvald/terrarum/modulebasegame/gameactors/FixtureTapestry.kt @@ -0,0 +1,108 @@ +package net.torvald.terrarum.modulebasegame.gameactors + +import com.badlogic.gdx.graphics.Color +import com.badlogic.gdx.graphics.Pixmap +import com.badlogic.gdx.graphics.Texture +import com.badlogic.gdx.graphics.g2d.SpriteBatch +import net.torvald.terrarum.* +import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE +import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF +import net.torvald.terrarum.blockproperties.Block +import net.torvald.terrarum.gameitems.ItemID +import net.torvald.terrarum.langpack.Lang +import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack + +/** + * Created by minjaesong on 2017-01-07. + */ +internal class FixtureTapestry : FixtureBase { + + var artName = ""; private set + var artAuthor = ""; private set + + val tw = 1 + val th = 1 + + private var rawBytes = ByteArray(tw * th * 256) + private var frameBlock: ItemID = Block.PLANK_NORMAL + + private constructor() : super( + BlockBox(BlockBox.NO_COLLISION, 1, 1), + renderOrder = RenderOrder.BEHIND, + nameFun = { Lang["ITEM_TAPESTRY"] } + ) + + constructor(rawBytes: ByteArray, framingMaterial: ItemID) : super( + BlockBox(BlockBox.NO_COLLISION, 1, 1), + renderOrder = RenderOrder.BEHIND, + nameFun = { Lang["ITEM_TAPESTRY"] } + ) { + this.rawBytes = rawBytes + this.frameBlock = framingMaterial + reload() + } + + override fun reload() { + super.reload() + + val (pixmap, name, author) = DecodeTapestry(rawBytes) + artName = name + artAuthor = author + nameFun = { "$ccW$artAuthor, $ccC$artName" } + + if (pixmap.width % TILE_SIZE != 0 || pixmap.height % TILE_SIZE != 0 || pixmap.width * pixmap.height == 0) { + throw UnsupportedOperationException("Tapestry size not multiple of tile size: (${pixmap.width}x${pixmap.height})") + } + + // draw canvas and frame texture over the pixmap + val tileFilename = "${frameBlock.replace(':','-')}" + val frame = CommonResourcePool.getOrPut("tapestries-common-frame_$tileFilename.tga") { + Pixmap(ModMgr.getGdxFilesFromEveryMod("tapestries/common/frame_$tileFilename.tga").last().second) + } as Pixmap + val canvas = CommonResourcePool.getOrPut("tapestries-common-canvas") { + Pixmap(ModMgr.getGdxFilesFromEveryMod("tapestries/common/canvas.tga").last().second) + } as Pixmap + + val tw = pixmap.width.div(TILE_SIZEF).ceilInt() + val th = pixmap.height.div(TILE_SIZEF).ceilInt() + + // blend canvas texture + for (y in 0 until pixmap.height) { for (x in 0 until pixmap.width) { + val srcCol = canvas.getPixel(x % pixmap.width, y % pixmap.height) + val dstCol = pixmap.getPixel(x, y) +// pixmap.drawPixel(x, y, dstCol rgbamul srcCol) + val col = Color(dstCol) mul Color(srcCol) + pixmap.setColor(col) + pixmap.drawPixel(x, y) + } } + + // draw frame + for (ty in 0 until th) { for (tx in 0 until tw) { + val srcx = TILE_SIZE * (if (tw == 1) 0 else if (tx == 0) 1 else if (tx == tw - 1) 3 else 2) + val srcy = TILE_SIZE * (if (th == 1) 0 else if (ty == 0) 1 else if (ty == th - 1) 3 else 2) + val dstx = tx * TILE_SIZE + val dsty = ty * TILE_SIZE + pixmap.drawPixmap(frame, srcx, srcy, TILE_SIZE, TILE_SIZE, dstx, dsty, TILE_SIZE, TILE_SIZE) + } } + + + val texture = Texture(pixmap) + texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest) + val texturePack = TextureRegionPack(texture, pixmap.width, pixmap.height) + + makeNewSprite(texturePack) + setHitboxDimension(pixmap.width, pixmap.height, 0, 0) + setPosition(Terrarum.mouseX, Terrarum.mouseY) + + // redefine blockbox + this.blockBox = BlockBox(BlockBox.NO_COLLISION, tw, th) + this.renderOrder = RenderOrder.BEHIND + + + pixmap.dispose() + INGAME.disposables.add(texture) + } + + + override var tooltipText: String? = "$artName\n$artAuthor" +} diff --git a/src/net/torvald/terrarum/modulebasegame/gameactors/TapestryObject.kt b/src/net/torvald/terrarum/modulebasegame/gameactors/TapestryObject.kt deleted file mode 100644 index faa93f595..000000000 --- a/src/net/torvald/terrarum/modulebasegame/gameactors/TapestryObject.kt +++ /dev/null @@ -1,108 +0,0 @@ -package net.torvald.terrarum.modulebasegame.gameactors - -import com.badlogic.gdx.graphics.Color -import com.badlogic.gdx.graphics.Pixmap -import com.badlogic.gdx.graphics.Texture -import com.badlogic.gdx.graphics.g2d.SpriteBatch -import net.torvald.terrarum.* -import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE -import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF -import net.torvald.terrarum.blockproperties.Block -import net.torvald.terrarum.gameactors.ActorID -import net.torvald.terrarum.gameitems.ItemID -import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack - -/** - * Created by minjaesong on 2017-01-07. - */ -class TapestryObject : FixtureBase { - - @Transient private var initialised = false - - var artName = ""; private set - var artAuthor = ""; private set - - val tw = 1 - val th = 1 - - private var rawBytes = ByteArray(tw * th * 256) - private var frameBlock: ItemID = Block.PLANK_NORMAL - - private constructor() : super() - - constructor(rawBytes: ByteArray, framingMaterial: ItemID) : super() { - this.artName = artName - this.artAuthor = artAuthor - this.nameFun = { "$ccW$artAuthor, $ccC$artName" } - this.rawBytes = rawBytes - this.frameBlock = framingMaterial - } - - override fun update(delta: Float) { - if (!initialised) { - initialised = true - - - val (pixmap, name, author) = DecodeTapestry(rawBytes) - artName = name - artAuthor = author - - if (pixmap.width % TILE_SIZE != 0 || pixmap.height % TILE_SIZE != 0 || pixmap.width * pixmap.height == 0) { - throw UnsupportedOperationException("Tapestry size not multiple of tile size: (${pixmap.width}x${pixmap.height})") - } - - // draw canvas and frame texture over the pixmap - val tileFilename = "${frameBlock.replace(':','-')}" - val frame = CommonResourcePool.getOrPut("tapestries-common-frame_$tileFilename.tga") { - Pixmap(ModMgr.getGdxFilesFromEveryMod("tapestries/common/frame_$tileFilename.tga").last().second) - } as Pixmap - val canvas = CommonResourcePool.getOrPut("tapestries-common-canvas") { - Pixmap(ModMgr.getGdxFilesFromEveryMod("tapestries/common/canvas.tga").last().second) - } as Pixmap - - val tw = pixmap.width.div(TILE_SIZEF).ceilInt() - val th = pixmap.height.div(TILE_SIZEF).ceilInt() - - // blend canvas texture - for (y in 0 until pixmap.height) { for (x in 0 until pixmap.width) { - val srcCol = canvas.getPixel(x % pixmap.width, y % pixmap.height) - val dstCol = pixmap.getPixel(x, y) - pixmap.drawPixel(x, y, dstCol rgbamul srcCol) - } } - - // draw frame - for (ty in 0 until th) { for (tx in 0 until tw) { - val srcx = TILE_SIZE * (if (tw == 1) 0 else if (tx == 0) 1 else if (tx == tw - 1) 3 else 2) - val srcy = TILE_SIZE * (if (th == 1) 0 else if (ty == 0) 1 else if (tw == th - 1) 3 else 2) - val dstx = tx * TILE_SIZE - val dsty = ty * TILE_SIZE - pixmap.drawPixmap(frame, srcx, srcy, TILE_SIZE, TILE_SIZE, dstx, dsty, TILE_SIZE, TILE_SIZE) - } } - - - val texture = Texture(pixmap) - texture.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest) - val texturePack = TextureRegionPack(texture, texture.width, texture.height) - - makeNewSprite(texturePack) - setHitboxDimension(texture.width, texture.height, 0, 0) - setPosition(Terrarum.mouseX, Terrarum.mouseY) - - // redefine blockbox - this.blockBox = BlockBox(BlockBox.NO_COLLISION, tw, th) - this.renderOrder = RenderOrder.BEHIND - - - pixmap.dispose() - INGAME.disposables.add(texture) - } - - super.update(delta) - } - - override fun drawBody(batch: SpriteBatch) { - super.drawBody(batch) - } - - override var tooltipText: String? = "$artName\n$artAuthor" -} diff --git a/src/net/torvald/terrarum/modulebasegame/gameitems/FixtureItemBase.kt b/src/net/torvald/terrarum/modulebasegame/gameitems/FixtureItemBase.kt index c3e85b732..3e334e004 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameitems/FixtureItemBase.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameitems/FixtureItemBase.kt @@ -1,6 +1,7 @@ package net.torvald.terrarum.modulebasegame.gameitems import com.badlogic.gdx.graphics.g2d.TextureRegion +import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.CommonResourcePool import net.torvald.terrarum.INGAME import net.torvald.terrarum.ItemCodex @@ -16,9 +17,9 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase /** * Created by minjaesong on 2021-12-13. */ -open class FixtureItemBase(originalID: ItemID, fixtureClassName: String) : GameItem(originalID) { +open class FixtureItemBase(originalID: ItemID, val fixtureClassName: String) : GameItem(originalID) { - private val makeFixture: () -> FixtureBase = { + protected open val makeFixture: () -> FixtureBase = { Class.forName(fixtureClassName).getDeclaredConstructor().newInstance() as FixtureBase } @@ -26,7 +27,12 @@ open class FixtureItemBase(originalID: ItemID, fixtureClassName: String) : GameI ItemCodex.fixtureToSpawnerItemID[fixtureClassName] = originalID } - protected val ghostItem = makeFixture() + protected var ghostItem: FixtureBase? = null + get() { + if (field == null) + ghostItem = makeFixture() + return field + } override var dynamicID: ItemID = originalID override val originalName = "FIXTUREBASE" @@ -42,7 +48,7 @@ open class FixtureItemBase(originalID: ItemID, fixtureClassName: String) : GameI override fun effectWhileEquipped(actor: ActorWithBody, delta: Float) { (INGAME as TerrarumIngame).blockMarkingActor.let { - it.setGhost(ghostItem) + it.setGhost(ghostItem!!) it.isVisible = true it.update(delta) it.setGhostColourBlock() @@ -59,7 +65,7 @@ open class FixtureItemBase(originalID: ItemID, fixtureClassName: String) : GameI } override fun startPrimaryUse(actor: ActorWithBody, delta: Float) = mouseInInteractableRange(actor) { - val item = makeFixture() + val item = ghostItem!!//makeFixture() item.spawn(Terrarum.mouseTileX, Terrarum.mouseTileY - item.blockBox.height + 1) // return true when placed, false when cannot be placed diff --git a/src/net/torvald/terrarum/modulebasegame/gameitems/ItemLogicSignalEmitter.kt b/src/net/torvald/terrarum/modulebasegame/gameitems/ItemLogicSignalEmitter.kt index 713b9b002..e8c9a25f5 100644 --- a/src/net/torvald/terrarum/modulebasegame/gameitems/ItemLogicSignalEmitter.kt +++ b/src/net/torvald/terrarum/modulebasegame/gameitems/ItemLogicSignalEmitter.kt @@ -1,7 +1,9 @@ package net.torvald.terrarum.modulebasegame.gameitems +import com.badlogic.gdx.graphics.Texture import com.badlogic.gdx.graphics.g2d.TextureRegion import net.torvald.terrarum.CommonResourcePool +import net.torvald.terrarum.ModMgr import net.torvald.terrarum.Terrarum import net.torvald.terrarum.gameactors.ActorWithBody import net.torvald.terrarum.gameitems.ItemID @@ -20,7 +22,11 @@ class ItemLogicSignalEmitter(originalID: ItemID) : FixtureItemBase(originalID, " override val isDynamic = false override val material = Material() override val itemImage: TextureRegion - get() = CommonResourcePool.getAsTextureRegion("basegame-sprites-fixtures-signal_source.tga") + get() = CommonResourcePool.getOrPut("basegame-sprites-fixtures-signal_source.tga") { + val t = TextureRegion(Texture(ModMgr.getGdxFile("basegame", "sprites/fixtures/signal_source.tga"))) + t.flip(false, false) + /*return*/t + } as TextureRegion override var baseToolSize: Double? = baseMass init { diff --git a/src/net/torvald/terrarum/modulebasegame/gameitems/ItemTapestry.kt b/src/net/torvald/terrarum/modulebasegame/gameitems/ItemTapestry.kt new file mode 100644 index 000000000..09cfc01d6 --- /dev/null +++ b/src/net/torvald/terrarum/modulebasegame/gameitems/ItemTapestry.kt @@ -0,0 +1,40 @@ +package net.torvald.terrarum.modulebasegame.gameitems + +import com.badlogic.gdx.Gdx +import com.badlogic.gdx.graphics.g2d.TextureRegion +import net.torvald.terrarum.CommonResourcePool +import net.torvald.terrarum.blockproperties.Block +import net.torvald.terrarum.gameitems.ItemID +import net.torvald.terrarum.itemproperties.Material +import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase +import net.torvald.terrarum.modulebasegame.gameactors.FixtureTapestry + +/** + * Created by minjaesong on 2022-02-28. + */ +class ItemTapestry(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureTapestry") { + + override var dynamicID: ItemID = originalID + override val originalName = "ITEM_TAPESTRY" + override var baseMass = 6.0 + override var stackable = true + override var inventoryCategory = Category.MISC + override val isUnique = false + override val isDynamic = false + override val material = Material() + override val itemImage: TextureRegion + get() = CommonResourcePool.getAsTextureRegion("itemplaceholder_16") + override var baseToolSize: Double? = baseMass + + init { + equipPosition = EquipPosition.HAND_GRIP + } + + override val makeFixture: () -> FixtureBase = { + FixtureTapestry( + Gdx.files.internal("assets/monkey_island").readBytes(), + Block.PLANK_NORMAL + ) + } + +} \ No newline at end of file