signal switches

This commit is contained in:
minjaesong
2024-03-01 01:58:16 +09:00
parent 902a086a4f
commit 6c3ec20b3d
25 changed files with 222 additions and 33 deletions

View File

@@ -561,7 +561,9 @@ object ModMgr {
))
}
}
Terrarum.wireCodex.fromModule(module, "wires/")
Terrarum.wireCodex.fromModule(module, "wires/") { wire ->
}
}
private fun makeNewItemObj(tile: BlockProp, isWall: Boolean) = object : GameItem(

View File

@@ -53,7 +53,7 @@ class OreCodex {
private fun setProp(modname: String, key: Int, record: CSVRecord) {
val prop = OreProp()
prop.id = "ores@$modname:$key"
prop.tags = record.get("tags").split(',').map { it.trim() }.toHashSet()
prop.tags = record.get("tags").split(',').map { it.trim().toUpperCase() }.toHashSet()
prop.item = record.get("item").let { if (it == null) "" else if (it.contains(':')) it else "$modname:$it" }
oreProps[prop.id] = prop

View File

@@ -39,15 +39,15 @@ class WireCodex {
* @param module name of the module
* @param path to the "wires" directory, not path to the CSV; must end with a slash!
*/
fun fromModule(module: String, path: String) {
fun fromModule(module: String, path: String, blockRegisterHook: (WireProp) -> Unit) {
printdbg(this, "Building wire properties table for module $module")
try {
register(module, path, CSVFetcher.readFromModule(module, path + "wires.csv"))
register(module, path, CSVFetcher.readFromModule(module, path + "wires.csv"), blockRegisterHook)
}
catch (e: IOException) { e.printStackTrace() }
}
fun fromCSV(module: String, path: String, csvString: String) {
fun fromCSV(module: String, path: String, csvString: String, blockRegisterHook: (WireProp) -> Unit) {
printdbg(this, "Building wire properties table for module $module")
val csvParser = org.apache.commons.csv.CSVParser.parse(
@@ -57,10 +57,10 @@ class WireCodex {
val csvRecordList = csvParser.records
csvParser.close()
register(module, path, csvRecordList)
register(module, path, csvRecordList, blockRegisterHook)
}
private fun register(module: String, path: String, records: List<CSVRecord>) {
private fun register(module: String, path: String, records: List<CSVRecord>, blockRegisterHook: (WireProp) -> Unit) {
records.forEach {
setProp(module, it.intVal("id"), it)
}
@@ -73,9 +73,12 @@ class WireCodex {
val t = TextureRegionPack(ModMgr.getGdxFile(module, "$path$wireid.tga"), TILE_SIZE, TILE_SIZE)
/*return*/t
}
wireProps[id]?.let(blockRegisterHook)
}
CommonResourcePool.loadAll()
}
fun getAll() = wireProps.values
@@ -134,6 +137,7 @@ class WireCodex {
prop.inputType = record.get("inputtype") ?: prop.accepts
prop.outputType = record.get("outputtype") ?: prop.accepts
prop.canBranch = record.boolVal("branching")
prop.tags = record.get("tags").split(',').map { it.trim().toUpperCase() }.toHashSet()
wireProps[prop.id] = prop

View File

@@ -24,4 +24,18 @@ class WireProp {
* Mainly intended to be used by third-party modules
*/
val extra = Codex()
@Transient var tags = HashSet<String>()
fun hasTag(s: String) = tags.contains(s)
fun hasAnyTagOf(vararg s: String) = s.any { hasTag(it) }
fun hasAnyTag(s: Collection<String>) = s.any { hasTag(it) }
fun hasAnyTag(s: Array<String>) = s.any { hasTag(it) }
fun hasAllTagOf(vararg s: String) = s.all { hasTag(it) }
fun hasAllTag(s: Collection<String>) = s.all { hasTag(it) }
fun hasAllTag(s: Array<String>) = s.all { hasTag(it) }
fun hasNoTagOf(vararg s: String) = s.none { hasTag(it) }
fun hasNoTag(s: Collection<String>) = s.none { hasTag(it) }
fun hasNoTag(s: Array<String>) = s.none { hasTag(it) }
}

View File

@@ -443,7 +443,7 @@ open class ActorWithBody : Actor {
fun setPosition(pos: Point2d) = setPosition(pos.x, pos.y)
fun setPosition(pos: Vector2) = setPosition(pos.x, pos.y)
fun setPositionFromCentrePoint(pos: Vector2) = setPosition(pos.x, pos.y + (hitbox.height) / 2)
/**
* ONLY FOR INITIAL SETUP

View File

@@ -786,7 +786,7 @@ object IngameRenderer : Disposable {
if (c > 0) Toolkit.fillArea(
batch,
throwPos.x.toFloat(),
throwPos.y.toFloat() - cubeSize.toFloat() / 2f,
throwPos.y.toFloat(),
2f,
2f
)
@@ -801,11 +801,19 @@ object IngameRenderer : Disposable {
// break if colliding with a tile
if (BlockCodex[world.getTileFromTerrain(
throwPos.x.div(TILE_SIZED).toInt(),
(throwPos.y - cubeSize / 2).div(TILE_SIZED).toInt()
)].isSolid
)
val hitSolid = listOf(
throwPos + Vector2(-cubeSize/2, -cubeSize/2),
throwPos + Vector2(-cubeSize/2, +cubeSize/2),
throwPos + Vector2(+cubeSize/2, +cubeSize/2),
throwPos + Vector2(+cubeSize/2, -cubeSize/2),
).any {
val wx = (it.x / TILE_SIZED).toInt()
val wy = (it.y / TILE_SIZED).toInt()
val tile = world.getTileFromTerrain(wx, wy)
BlockCodex[tile].isSolid
}
if (hitSolid)
break
c++

View File

@@ -332,6 +332,10 @@ class InventoryPair : Comparable<InventoryPair> {
operator fun component2() = qty
override fun compareTo(other: InventoryPair) = this.itm.compareTo(other.itm)
override fun toString(): String {
return if (qty == -1L) "$itm" else "$itm ($qty)"
}
}
class InventoryTransactionFailedError(msg: String) : Error(msg)

View File

@@ -7,6 +7,9 @@ import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import org.dyn4j.geometry.Vector2
/**
* Created by minjaesong on 2021-08-08.
*/
class FixtureLogicSignalEmitter : Electric {
@Transient override val spawnNeedsFloor = false

View File

@@ -0,0 +1,71 @@
package net.torvald.terrarum.modulebasegame.gameactors
import net.torvald.spriteanimation.SheetSpriteAnimation
import net.torvald.terrarum.App
import net.torvald.terrarum.TerrarumAppConfiguration
import net.torvald.terrarum.gameactors.AVKey
import net.torvald.terrarum.langpack.Lang
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarum.toInt
import net.torvald.terrarum.ui.MouseLatch
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import org.dyn4j.geometry.Vector2
/**
* Created by minjaesong on 2024-03-01.
*/
class FixtureSignalSwitchManual : Electric {
@Transient override val spawnNeedsFloor = false
constructor() : super(
BlockBox(BlockBox.NO_COLLISION, 1, 1),
nameFun = { Lang["ITEM_LOGIC_SIGNAL_SWITCH"] }
)
private val variant = (Math.random() * 8).toInt()
private var state = false // false = off
init {
val itemImage = FixtureItemBase.getItemImageFromSingleImage("basegame", "sprites/fixtures/signal_switch.tga")
density = 1400.0
setHitboxDimension(TerrarumAppConfiguration.TILE_SIZE, TerrarumAppConfiguration.TILE_SIZE, 0, 1)
makeNewSprite(TextureRegionPack(itemImage.texture, TerrarumAppConfiguration.TILE_SIZE, TerrarumAppConfiguration.TILE_SIZE)).let {
it.setRowsAndFrames(2,8)
it.currentFrame = variant
it.delays = floatArrayOf(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY)
}
actorValue[AVKey.BASEMASS] = FixtureLogicSignalEmitter.MASS
setWireEmitterAt(0, 0, "digital_bit")
}
override fun reload() {
super.reload()
(sprite as SheetSpriteAnimation).currentFrame = variant
(sprite as SheetSpriteAnimation).currentRow = state.toInt()
setWireEmissionAt(0, 0, Vector2(state.toInt().toDouble(), 0.0))
}
@Transient private val clickLatch = MouseLatch(listOf(App.getConfigInt("config_mousesecondary")))
override fun updateImpl(delta: Float) {
super.updateImpl(delta)
// right click
if (mouseUp) {
clickLatch.latch {
state = !state
(sprite as SheetSpriteAnimation).currentRow = state.toInt()
setWireEmissionAt(0, 0, Vector2(state.toInt().toDouble(), 0.0))
}
}
}
}

View File

@@ -8,6 +8,9 @@ import net.torvald.terrarum.itemproperties.Material
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter
/**
* Created by minjaesong on 2021-08-08.
*/
class ItemLogicSignalEmitter(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter") {
override var dynamicID: ItemID = originalID

View File

@@ -0,0 +1,37 @@
package net.torvald.terrarum.modulebasegame.gameitems
import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter
/**
* Created by minjaesong on 2024-03-01.
*/
class ItemSignalSwitchManual(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureSignalSwitchManual") {
override var dynamicID: ItemID = originalID
override var baseMass = FixtureLogicSignalEmitter.MASS
override val canBeDynamic = false
override val materialId = ""
override val itemImage: TextureRegion
get() = CommonResourcePool.getAsItemSheet("basegame.items").get(8, 3)
override var baseToolSize: Double? = baseMass
override var originalName = "ITEM_LOGIC_SIGNAL_SWITCH"
override var inventoryCategory = Category.MISC
override fun effectWhileEquipped(actor: ActorWithBody, delta: Float) {
super.effectWhileEquipped(actor, delta)
(Terrarum.ingame!! as TerrarumIngame).selectedWireRenderClass = "signal"
}
override fun effectOnUnequip(actor: ActorWithBody) {
super.effectOnUnequip(actor)
(Terrarum.ingame!! as TerrarumIngame).selectedWireRenderClass = ""
}
}

View File

@@ -34,7 +34,7 @@ open class ItemThrowable(originalID: ItemID, private val throwableActorClassName
val (throwPos, throwForce) = getThrowPosAndVector(actor)
val lobbed = Class.forName(throwableActorClassName).getDeclaredConstructor().newInstance() as ActorWithBody
lobbed.setPosition(throwPos)
lobbed.setPositionFromCentrePoint(throwPos)
lobbed.externalV.set(throwForce)
setupLobbedActor(lobbed)

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum.modulebasegame.gameitems
import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.WireCodex
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID
@@ -26,6 +27,7 @@ class WirePieceSignalWire(originalID: ItemID, private val atlasID: String, priva
init {
equipPosition = GameItem.EquipPosition.HAND_GRIP
originalName = "ITEM_WIRE"
tags.addAll(WireCodex[originalID].tags)
}
override fun startPrimaryUse(actor: ActorWithBody, delta: Float): Long {

View File

@@ -21,7 +21,6 @@ import net.torvald.terrarum.modulebasegame.ui.UITemplateHalfInventory.Companion.
import net.torvald.terrarum.ui.*
import net.torvald.terrarum.ui.UIItemCatBar.Companion.FILTER_CAT_ALL
import net.torvald.unicode.getKeycapPC
import kotlin.math.ceil
/**
* This UI has inventory, but it's just there to display all craftable items and should not be serialised.
@@ -251,7 +250,7 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas(
recipeClicked = recipe
// printdbg(this, "Recipe selected: $recipe")
recipe?.ingredients?.forEach { ingredient ->
val selectedItem = getItemForIngredient(playerInventory, ingredient)
val selectedItem = resolveIngredientKey(playerInventory, ingredient, recipe.product)
selectedItems.add(selectedItem)
ingredients.add(selectedItem, ingredient.qty)
}
@@ -357,7 +356,7 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas(
else {
val items = recipe.ingredients.flatMap {
getItemCandidatesForIngredient(getPlayerInventory(), it).map { it.itm }
}.sorted()
}.filter { it != recipe.product }.sorted() // filter out the product itself from the ingredient
val filterFun = { pair: InventoryPair ->
items.binarySearch(pair.itm) >= 0
@@ -561,10 +560,13 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas(
}
}
fun getItemForIngredient(inventory: FixtureInventory, ingredient: CraftingCodex.CraftingIngredients): ItemID {
val candidate = getItemCandidatesForIngredient(inventory, ingredient)
fun resolveIngredientKey(inventory: FixtureInventory, ingredient: CraftingCodex.CraftingIngredients, product: ItemID): ItemID {
val candidate = getItemCandidatesForIngredient(inventory, ingredient).filter { it.itm != product }
printdbg(this, "resolveIngredientKey product=$product, candidate=$candidate")
return if (ingredient.keyMode == CraftingCodex.CraftingItemKeyMode.TAG) {
// filter out the product itself from the ingredient
candidate.maxByOrNull { it.qty }?.itm ?: (
(ItemCodex.itemCodex.firstNotNullOfOrNull { if (it.value.hasTag(ingredient.key)) it.key else null }) ?:
throw NullPointerException("Item with tag '${ingredient.key}' not found. Possible cause: game or a module not updated or installed (ingredient: $ingredient)")
@@ -581,7 +583,7 @@ class UICrafting(val full: UIInventoryFull?) : UICanvas(
fun recipeToIngredientRecord(inventory: FixtureInventory, recipe: CraftingCodex.CraftingRecipe, nearbyCraftingStations: List<String>): List<RecipeIngredientRecord> {
val hasStation = if (recipe.workbench.isBlank()) true else nearbyCraftingStations.containsAll(recipe.workbench.split(','))
return recipe.ingredients.map { ingredient ->
val selectedItem = getItemForIngredient(inventory, ingredient)
val selectedItem = resolveIngredientKey(inventory, ingredient, recipe.product)
val howManyPlayerHas = inventory.searchByID(selectedItem)?.qty ?: 0L
val howManyTheRecipeWants = ingredient.qty