fixture pickup and mining works except for the dropping of a mined fixture

This commit is contained in:
minjaesong
2022-01-21 14:01:37 +09:00
parent 48e68137d6
commit 75afcaede3
13 changed files with 107 additions and 50 deletions

View File

@@ -126,6 +126,11 @@ open class IngameInstance(val batch: SpriteBatch, val isMultiplayer: Boolean = f
val actorContainerActive = SortedArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
val actorContainerInactive = SortedArrayList<Actor>(ACTORCONTAINER_INITIAL_SIZE)
/**
* ## BIG NOTE: Calculated actor distance is the **Euclidean distance SQUARED**
*
* But when a function does not take the distance (e.g. `actorsRTree.find()`) you must not square the numbers
*/
var actorsRTree: PRTree<ActorWithBody> = PRTree(actorMBRConverter, 24) // no lateinit!
protected set
@@ -450,7 +455,7 @@ open class IngameInstance(val batch: SpriteBatch, val isMultiplayer: Boolean = f
/** Will use centre point of the actors
* HOPEFULLY sorted by the distance...?
* @return List of DistanceResult, list may be empty */
* @return List of DistanceResult (the actor and the distance SQUARED from the actor), list may be empty */
fun findKNearestActors(from: ActorWithBody, maxHits: Int, nodeFilter: (ActorWithBody) -> Boolean): List<DistanceResult<ActorWithBody>> {
return actorsRTree.nearestNeighbour(actorDistanceCalculator, nodeFilter, maxHits, object : PointND {
override fun getDimensions(): Int = 2
@@ -462,7 +467,7 @@ open class IngameInstance(val batch: SpriteBatch, val isMultiplayer: Boolean = f
})
}
/** Will use centre point of the actors
* @return Pair of: the actor, distance from the actor; null if none found */
* @return Pair of: the actor, distance SQUARED from the actor; null if none found */
fun findNearestActor(from: ActorWithBody, nodeFilter: (ActorWithBody) -> Boolean): DistanceResult<ActorWithBody>? {
val t = findKNearestActors(from, 1, nodeFilter)
return if (t.isNotEmpty())

View File

@@ -12,8 +12,10 @@ import net.torvald.terrarum.gameitems.GameItem
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.CanBeAnItem
import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
import net.torvald.terrarum.worlddrawer.BlocksDrawer
import java.util.*
import kotlin.collections.HashMap
/**
* ItemCodex holds information of every item in the game, including blocks despite the 'item' naming
@@ -34,6 +36,11 @@ class ItemCodex {
internal constructor()
/**
* Pair of <Fully Qualified class name for the Fixture, Corresponding ItemID of the spawner Item>
*/
@Transient val fixtureToSpawnerItemID = HashMap<String, ItemID>()
fun clear() {
itemCodex.clear()
dynamicItemDescription.clear()
@@ -84,6 +91,7 @@ class ItemCodex {
}
fun dynamicToStaticID(dynamicID: ItemID) = dynamicToStaticTable[dynamicID]!!
fun fixtureToItemID(fixture: FixtureBase) = fixtureToSpawnerItemID[fixture.javaClass.canonicalName]!!
/**
* Mainly used by GameItemLoader

View File

@@ -53,7 +53,6 @@ import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.util.CircularArray
import org.khelekore.prtree.PRTree
import java.util.*
import java.util.concurrent.locks.ReentrantLock
/**
@@ -590,8 +589,6 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
// bring up the UIs of the fixtures (e.g. crafting menu from a crafting table)
var uiOpened = false
val canPerformBarehandAction = actor.scale * actor.baseHitboxH >= actor.actorValue.getAsDouble(AVKey.BAREHAND_MINHEIGHT) ?: 4294967296.0
// TODO actorsUnderMouse: support ROUNDWORLD
val actorsUnderMouse: List<FixtureBase> = getActorsAt(Terrarum.mouseX, Terrarum.mouseY).filterIsInstance<FixtureBase>()
if (actorsUnderMouse.size > 1) {
@@ -633,7 +630,7 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
(actor as Pocketed).inventory.consumeItem(itemOnGrip)
}
// #3. If I'm not holding any item and I can do barehandaction (size big enough that barehandactionminheight check passes), perform it
else if (itemOnGrip == null && canPerformBarehandAction) {
else if (itemOnGrip == null) {
mouseInInteractableRange(actor) {
performBarehandAction(actor, delta)
true
@@ -772,9 +769,10 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
// determine whether the inactive actor should be activated
wakeDormantActors()
// update NOW; allow one last update for the actors flagged to despawn
updateActors(delta)
// determine whether the actor should keep being activated or be dormant
killOrKnockdownActors()
updateActors(delta)
particlesContainer.forEach { if (!it.flagDespawn) particlesActive++; it.update(delta) }
// TODO thread pool(?)
CollisionSolver.process()
@@ -1218,20 +1216,11 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
particlesContainer.appendHead(particle)
}
private fun insertionSortLastElemAV(arr: ArrayList<ActorWithBody>) { // out-projection doesn't work, duh
ReentrantLock().lock {
var j = arr.lastIndex - 1
val x = arr.last()
while (j >= 0 && arr[j] > x) {
arr[j + 1] = arr[j]
j -= 1
}
arr[j + 1] = x
}
}
fun performBarehandAction(actor: ActorWithBody, delta: Float) {
val canAttackOrDig = actor.scale * actor.baseHitboxH >= actor.actorValue.getAsDouble(AVKey.BAREHAND_MINHEIGHT) ?: 4294967296.0
fun getActorsAtVicinity(worldX: Double, worldY: Double, radius: Double): List<ActorWithBody> {
val outList = java.util.ArrayList<ActorWithBody>()
try {
@@ -1245,14 +1234,50 @@ open class TerrarumIngame(batch: SpriteBatch) : IngameInstance(batch) {
val punchSize = actor.scale * actor.actorValue.getAsDouble(AVKey.BAREHAND_BASE_DIGSIZE)!!
// if there are attackable actor (todo) on the "actor punch hitbox (todo)", attack them (todo)
val actorsUnderMouse: List<ActorWithBody> = getActorsAtVicinity(Terrarum.mouseX, Terrarum.mouseY, punchSize / 2.0).filter { true }
// if there are attackable actor or fixtures
val actorsUnderMouse: List<ActorWithBody> = getActorsAtVicinity(Terrarum.mouseX, Terrarum.mouseY, punchSize / 2.0).sortedBy {
(Terrarum.mouseX - it.hitbox.centeredX).sqr() + (Terrarum.mouseY - it.hitbox.centeredY).sqr()
} // sorted by the distance from the mouse
// prioritise actors
val fixturesUnderHand = ArrayList<FixtureBase>()
val mobsUnderHand = ArrayList<ActorWithBody>()
actorsUnderMouse.forEach {
if (it is FixtureBase && it.mainUI == null)
fixturesUnderHand.add(it)
else if (it is ActorWithBody)
mobsUnderHand.add(it)
}
// pickup a fixture
if (fixturesUnderHand.size > 0) {
val fixture = fixturesUnderHand[0]
val fixtureItem = ItemCodex.fixtureToItemID(fixture)
printdbg(this, "Fixture pickup: ${fixture.javaClass.canonicalName} -> $fixtureItem")
// 1. put the fixture to the inventory
fixture.flagDespawn()
// 2. register this item(fixture) to the quickslot
if (actor is Pocketed) {
actor.inventory.add(fixtureItem)
actor.equipItem(fixtureItem)
actor.inventory.setQuickslotItemAtSelected(fixtureItem)
// 2-1. unregister if other slot has the same item
for (k in 0..9) {
if (actor.inventory.getQuickslotItem(k)?.itm == fixtureItem && k != actor.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL)) {
actor.inventory.setQuickslotItem(k, null)
}
}
}
}
// TODO attack a mob
// else if (mobsUnderHand.size > 0 && canAttackOrDig) {
// }
// else, punch a block
val punchBlockSize = punchSize.div(TILE_SIZED).floorInt()
if (punchBlockSize > 0) {
// println("whack!")
PickaxeCore.startPrimaryUse(actor, delta, null, Terrarum.mouseTileX, Terrarum.mouseTileY, 1.0 / punchBlockSize, punchBlockSize, punchBlockSize, false)
else if (canAttackOrDig) {
val punchBlockSize = punchSize.div(TILE_SIZED).floorInt()
if (punchBlockSize > 0) {
PickaxeCore.startPrimaryUse(actor, delta, null, Terrarum.mouseTileX, Terrarum.mouseTileY, 1.0 / punchBlockSize, punchBlockSize, punchBlockSize, false)
}
}
}

View File

@@ -665,7 +665,7 @@ open class ActorHumanoid : ActorWithBody, Controllable, Pocketed, Factionable, L
// make quickslot work
if (key == AVKey.__PLAYER_QUICKSLOTSEL && value != null) {
// ONLY FOR HAND_GRIPs!!
val quickBarItem = ItemCodex[inventory.getQuickslot(actorValue.getAsInt(key)!!)?.itm]
val quickBarItem = ItemCodex[inventory.getQuickslotItem(actorValue.getAsInt(key)!!)?.itm]
if (quickBarItem != null && quickBarItem.equipPosition == GameItem.EquipPosition.HAND_GRIP) {
equipItem(quickBarItem)

View File

@@ -47,16 +47,22 @@ class ActorInventory() : FixtureInventory() {
actor.unequipItem(existingItem.itm)
// also unequip on the quickslot
actor.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL)?.let {
setQuickBar(it, null)
setQuickslotItem(it, null)
}
}
}
fun setQuickBar(slot: Int, dynamicID: ItemID?) {
fun setQuickslotItem(slot: Int, dynamicID: ItemID?) {
quickSlot[slot] = dynamicID
}
fun getQuickslot(slot: Int): InventoryPair? = invSearchByDynamicID(quickSlot[slot])
fun setQuickslotItemAtSelected(dynamicID: ItemID?) {
actor.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL)?.let {
setQuickslotItem(it, dynamicID)
}
}
fun getQuickslotItem(slot: Int): InventoryPair? = invSearchByDynamicID(quickSlot[slot])
fun consumeItem(item: GameItem) {
val actor = this.actor as Actor
@@ -85,7 +91,7 @@ class ActorInventory() : FixtureInventory() {
// update quickslot designation as the item is being unpacked (e.g. using fresh new pickaxe)
actor.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL)?.let {
setQuickBar(it, newItem.dynamicID)
setQuickslotItem(it, newItem.dynamicID)
}
// FIXME now damage meter (vital) is broken

View File

@@ -9,6 +9,7 @@ import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameactors.PhysProperties
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarum.modulebasegame.gameitems.FixtureItemBase
import net.torvald.terrarum.ui.UICanvas
import org.dyn4j.geometry.Vector2
@@ -36,7 +37,9 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
protected constructor() : super(RenderOrder.BEHIND, PhysProperties.IMMOBILE, null)
constructor(blockBox0: BlockBox,
constructor(
blockBox0: BlockBox,
blockBoxProps: BlockBoxProps = BlockBoxProps(0),
renderOrder: RenderOrder = RenderOrder.MIDDLE,
nameFun: () -> String,
@@ -55,6 +58,7 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
App.disposables.add(mainUI)
}
/**
* Tile-wise position of this fixture when it's placed on the world, top-left origin. Null if it's not on the world
*/
@@ -151,11 +155,11 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
* Removes this instance of the fixture from the world
*/
open fun despawn() {
println("${this.javaClass.simpleName} dispose")
printdbg(this, "despawn ${nameFun()}")
// remove filler block
forEachBlockbox { x, y ->
world!!.setTileTerrain(x, y, Block.AIR, false)
world!!.setTileTerrain(x, y, Block.AIR, true)
}
worldBlockPos = null
@@ -173,7 +177,6 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
}
override fun update(delta: Float) {
super.update(delta)
// if not flagged to despawn and not actually despawned (which sets worldBlockPos as null), always fill up fillerBlock
if (!flagDespawn && worldBlockPos != null) {
// for removal-by-player because player is removing the filler block by pick
@@ -183,9 +186,10 @@ open class FixtureBase : ActorWithBody, CuedByTerrainChange {
}
}
if (flagDespawn) despawn()
}
// actual actor removal is performed by the TerrarumIngame
if (flagDespawn) despawn()
// actual actor removal is performed by the TerrarumIngame.killOrKnockdownActors
super.update(delta)
}
}

View File

@@ -3,6 +3,7 @@ package net.torvald.terrarum.modulebasegame.gameitems
import com.badlogic.gdx.graphics.g2d.TextureRegion
import net.torvald.terrarum.CommonResourcePool
import net.torvald.terrarum.INGAME
import net.torvald.terrarum.ItemCodex
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorWithBody
import net.torvald.terrarum.gameitems.GameItem
@@ -15,7 +16,15 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureBase
/**
* Created by minjaesong on 2021-12-13.
*/
open class FixtureItemBase(originalID: ItemID, val makeFixture: () -> FixtureBase) : GameItem(originalID) {
open class FixtureItemBase(originalID: ItemID, fixtureClassName: String) : GameItem(originalID) {
private val makeFixture: () -> FixtureBase = {
Class.forName(fixtureClassName).getDeclaredConstructor().newInstance() as FixtureBase
}
init {
ItemCodex.fixtureToSpawnerItemID[fixtureClassName] = originalID
}
protected val ghostItem = makeFixture()

View File

@@ -9,7 +9,7 @@ import net.torvald.terrarum.itemproperties.Material
import net.torvald.terrarum.modulebasegame.TerrarumIngame
import net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter
class ItemLogicSignalEmitter(originalID: ItemID) : FixtureItemBase(originalID, { FixtureLogicSignalEmitter() }) {
class ItemLogicSignalEmitter(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureLogicSignalEmitter") {
override var dynamicID: ItemID = originalID
override val originalName = "ITEM_LOGIC_SIGNAL_EMITTER"

View File

@@ -10,7 +10,7 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureTikiTorch
/**
* Created by minjaesong on 2019-07-08.
*/
class ItemStorageChest(originalID: ItemID) : FixtureItemBase(originalID, { FixtureStorageChest() }) {
class ItemStorageChest(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureStorageChest") {
override var dynamicID: ItemID = originalID
override val originalName = "ITEM_STORAGE_CHEST"

View File

@@ -9,7 +9,7 @@ import net.torvald.terrarum.modulebasegame.gameactors.FixtureTikiTorch
/**
* Created by minjaesong on 2019-05-16.
*/
class ItemTikiTorch(originalID: ItemID) : FixtureItemBase(originalID, { FixtureTikiTorch() }) {
class ItemTikiTorch(originalID: ItemID) : FixtureItemBase(originalID, "net.torvald.terrarum.modulebasegame.gameactors.FixtureTikiTorch") {
override var dynamicID: ItemID = originalID
override val originalName = "ITEM_TIKI_TORCH"

View File

@@ -106,10 +106,10 @@ class UIItemInventoryItemGrid(
if (player != null) {
val inventory = player.inventory
val slot = if (keycode == Input.Keys.NUM_0) 9 else keycode - Input.Keys.NUM_1
val currentSlotItem = inventory.getQuickslot(slot)
val currentSlotItem = inventory.getQuickslotItem(slot)
inventory.setQuickBar(
inventory.setQuickslotItem(
slot,
if (currentSlotItem?.itm != item.dynamicID)
item.dynamicID // register
@@ -120,8 +120,8 @@ class UIItemInventoryItemGrid(
// search for duplicates in the quickbar, except mine
// if there is, unregister the other
(0..9).minus(slot).forEach {
if (inventory.getQuickslot(it)?.itm == item.dynamicID) {
inventory.setQuickBar(it, null)
if (inventory.getQuickslotItem(it)?.itm == item.dynamicID) {
inventory.setQuickslotItem(it, null)
}
}
}
@@ -145,7 +145,7 @@ class UIItemInventoryItemGrid(
// also equip on the quickslot
player.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL)?.let {
player.inventory.setQuickBar(it, item.dynamicID)
player.inventory.setQuickslotItem(it, item.dynamicID)
}
}
else { // if not, unequip it
@@ -153,7 +153,7 @@ class UIItemInventoryItemGrid(
// also unequip on the quickslot
player.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL)?.let {
player.inventory.setQuickBar(it, null)
player.inventory.setQuickslotItem(it, null)
}
}
}
@@ -415,7 +415,7 @@ class UIItemInventoryItemGrid(
val ainv = getInventory() as ActorInventory
for (qs in 1..UIQuickslotBar.SLOT_COUNT) {
if (sortListItem.itm == ainv.getQuickslot(qs - 1)?.itm) {
if (sortListItem.itm == ainv.getQuickslotItem(qs - 1)?.itm) {
items[k].quickslot = qs % 10 // 10 -> 0, 1..9 -> 1..9
break
}

View File

@@ -82,7 +82,7 @@ class UIQuickslotBar : UICanvas() {
(Terrarum.ingame!! as TerrarumIngame).actorNowPlaying?.let { actor ->
for (i in 0..SLOT_COUNT - 1) {
val item = ItemCodex[actor.inventory.getQuickslot(i)?.itm]
val item = ItemCodex[actor.inventory.getQuickslotItem(i)?.itm]
val image = if (i == selection)
ItemSlotImageFactory.produceLarge(false, (i + 1) % SLOT_COUNT, item)
@@ -101,7 +101,7 @@ class UIQuickslotBar : UICanvas() {
if (nameShowupAlpha > 0f) {
val selection = actor.actorValue.getAsInt(AVKey.__PLAYER_QUICKSLOTSEL) ?: return
actor.inventory.getQuickslot(selection)?.let {
actor.inventory.getQuickslotItem(selection)?.let {
val item = ItemCodex[it.itm]
val quantity = it.qty
val text = "${item?.name}" + (if (item?.isUnique == true) "" else " ($quantity)")

View File

@@ -65,7 +65,7 @@ class UIQuickslotPie : UICanvas() {
override fun renderUI(batch: SpriteBatch, camera: Camera) {
// draw radial thingies
for (i in 0..slotCount - 1) {
val item = ItemCodex[(Terrarum.ingame!! as TerrarumIngame).actorNowPlaying?.inventory?.getQuickslot(i)?.itm]
val item = ItemCodex[(Terrarum.ingame!! as TerrarumIngame).actorNowPlaying?.inventory?.getQuickslotItem(i)?.itm]
// set position
val angle = Math.PI * 2.0 * (i.toDouble() / slotCount) + Math.PI // 180 deg monitor-wise