WIP inventory implementation

Former-commit-id: ce7d2125209c2c4f49b7d755b068ce72387f5e8f
Former-commit-id: f413b2699ee7448f3d3b70775ca7b679ade66475
This commit is contained in:
Song Minjae
2016-12-12 23:29:13 +09:00
parent 01f3d10379
commit 58ca0d006a
10 changed files with 157 additions and 52 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@@ -18,7 +18,7 @@ class CodexEdictis : ConsoleCommand {
} }
else { else {
try { try {
val commandObj = CommandDict.get(args[1].toLowerCase()) val commandObj = CommandDict[args[1].toLowerCase()]
commandObj.printUsage() commandObj.printUsage()
} }
catch (e: NullPointerException) { catch (e: NullPointerException) {

View File

@@ -40,6 +40,7 @@ object CommandDict {
Pair("seed", Seed()), Pair("seed", Seed()),
Pair("testgetlight", TestGetLight()), Pair("testgetlight", TestGetLight()),
Pair("println", EchoConsole()), Pair("println", EchoConsole()),
Pair("inventory", Inventory()),
// Test codes // Test codes
Pair("bulletintest", SetBulletin()), Pair("bulletintest", SetBulletin()),

View File

@@ -0,0 +1,65 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameactors.ActorInventory
import net.torvald.terrarum.gameactors.Player
import net.torvald.terrarum.gameactors.Pocketed
import net.torvald.terrarum.itemproperties.ItemPropCodex
/**
* Created by SKYHi14 on 2016-12-12.
*/
class Inventory : ConsoleCommand {
private var target: ActorInventory = Terrarum.ingame.player.inventory
override fun execute(args: Array<String>) {
if (args.size == 1) {
printUsage()
} else {
when (args[1]) {
"list" -> listInventory()
"add" -> addItem(args[2].toInt(), args[3].toInt())
"target" -> setTarget(args[2].toInt())
"assign" -> assignQuickBar(args[2].toInt(), args[3].toInt())
else -> printUsage()
}
}
}
private fun listInventory() {
if (target.getTotalUniqueCount() == 0) {
Echo().execute("(inventory empty)")
} else {
target.forEach { refId, amount ->
if (amount == 0) {
Error().execute("Unexpected zero-amounted item: ID $refId")
}
Echo().execute("ID $refId${if (amount > 1) " ($amount)" else ""}")
}
}
}
private fun setTarget(actorRefId: Int = Player.PLAYER_REF_ID) {
val actor = Terrarum.ingame.getActorByID(actorRefId)
if (actor !is Pocketed) {
Error().execute("Cannot edit inventory of incompatible actor: $actor")
} else {
target = actor.inventory
}
}
private fun addItem(refId: Int, amount: Int = 1) {
target.add(ItemPropCodex.getProp(refId), amount)
}
private fun assignQuickBar(refId: Int, index: Int) {
}
override fun printUsage() {
Echo().execute("Usage: inventory command arguments")
Echo().execute("Available commands:")
Echo().execute("list | assign slot | add itemid [amount] | target [actorid]")
}
}

View File

@@ -1,5 +1,6 @@
package net.torvald.terrarum.gameactors package net.torvald.terrarum.gameactors
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameitem.InventoryItem import net.torvald.terrarum.gameitem.InventoryItem
import net.torvald.terrarum.itemproperties.ItemPropCodex import net.torvald.terrarum.itemproperties.ItemPropCodex
import java.util.* import java.util.*
@@ -21,7 +22,7 @@ class ActorInventory() {
private var capacityMode: Int private var capacityMode: Int
/** /**
* HashMap&lt;ReferenceID, Amounts&gt; * HashMap<ReferenceID, Amounts>
*/ */
private val itemList: HashMap<Int, Int> = HashMap() private val itemList: HashMap<Int, Int> = HashMap()
@@ -78,6 +79,8 @@ class ActorInventory() {
return itemList return itemList
} }
fun forEach(consumer: (Int, Int) -> Unit) = itemList.forEach(consumer)
/** /**
* Get clone of the itemList * Get clone of the itemList
* @return * @return
@@ -97,6 +100,9 @@ class ActorInventory() {
return weight return weight
} }
/**
* Real amount
*/
fun getTotalCount(): Int { fun getTotalCount(): Int {
var count = 0 var count = 0
@@ -107,26 +113,26 @@ class ActorInventory() {
return count return count
} }
/**
* Unique amount, multiple items are calculated as one
*/
fun getTotalUniqueCount(): Int { fun getTotalUniqueCount(): Int {
return itemList.entries.size return itemList.entries.size
} }
fun appendToPocket(item: InventoryItem) { fun add(item: InventoryItem) {
appendToPocket(item, 1) add(item, 1)
} }
fun appendToPocket(item: InventoryItem, count: Int) { fun add(item: InventoryItem, count: Int) {
val key = item.itemID val key = item.itemID
// if (key == Player.PLAYER_REF_ID) if (key == Player.PLAYER_REF_ID || key == Terrarum.ingame.player.referenceID)
// throw new IllegalArgumentException("Attempted to put player into the inventory."); throw IllegalArgumentException("Attempted to put active player or human player into the inventory.")
if (itemList.containsKey(key)) // If we already have the item, increment the amount
// increment amount if it already has specified item // If not, add item with specified amount
itemList.put(key, itemList[key]!! + count) itemList.put(key, itemList[key] ?: 0 + count)
else
// add new entry if it does not have specified item
itemList.put(key, count)
} }
/** /**

View File

@@ -2,6 +2,7 @@ package net.torvald.terrarum.gameactors
import net.torvald.terrarum.gameactors.ActorHumanoid import net.torvald.terrarum.gameactors.ActorHumanoid
import net.torvald.terrarum.gameitem.InventoryItem import net.torvald.terrarum.gameitem.InventoryItem
import net.torvald.terrarum.gameitem.InventoryItemAdapter
import org.luaj.vm2.Globals import org.luaj.vm2.Globals
import org.luaj.vm2.LoadState import org.luaj.vm2.LoadState
import org.luaj.vm2.LuaError import org.luaj.vm2.LuaError
@@ -39,7 +40,7 @@ open class HumanoidNPC(aiFile: String, born: GameDate) : ActorHumanoid(born), AI
} }
// we're having InventoryItem data so that this class could be somewhat universal // we're having InventoryItem data so that this class could be somewhat universal
override var itemData: InventoryItem = object : InventoryItem { override var itemData: InventoryItem = object : InventoryItemAdapter() {
override var itemID = referenceID override var itemID = referenceID
override var mass: Double override var mass: Double
@@ -54,30 +55,9 @@ open class HumanoidNPC(aiFile: String, born: GameDate) : ActorHumanoid(born), AI
actorValue[AVKey.SCALE] = value actorValue[AVKey.SCALE] = value
} }
override fun effectWhileInPocket(gc: GameContainer, delta: Int) {
}
override fun effectWhenPickedUp(gc: GameContainer, delta: Int) {
}
override fun primaryUse(gc: GameContainer, delta: Int) {
// TODO do not allow primary_use
}
override fun secondaryUse(gc: GameContainer, delta: Int) { override fun secondaryUse(gc: GameContainer, delta: Int) {
// TODO place this Actor to the world // TODO place this Actor to the world
} }
override fun effectWhenThrown(gc: GameContainer, delta: Int) {
}
override fun effectWhenTakenOut(gc: GameContainer, delta: Int) {
}
override fun worldActorEffect(gc: GameContainer, delta: Int) {
}
} }
override fun getItemWeight(): Double { override fun getItemWeight(): Double {

View File

@@ -55,7 +55,7 @@ object PlayerBuilderSigrid {
p.actorValue[AVKey.INTELLIGENT] = true p.actorValue[AVKey.INTELLIGENT] = true
p.actorValue[AVKey.LUMINOSITY] = 0//95487100 p.actorValue[AVKey.LUMINOSITY] = 95487100
p.actorValue[AVKey.BASEDEFENCE] = 141 p.actorValue[AVKey.BASEDEFENCE] = 141
@@ -71,6 +71,14 @@ object PlayerBuilderSigrid {
p.faction.add(FactionFactory.create("FactionSigrid.json")) p.faction.add(FactionFactory.create("FactionSigrid.json"))
// Test fill up inventory
return p return p
} }
} }

View File

@@ -8,20 +8,21 @@ import org.newdawn.slick.GameContainer
interface InventoryItem { interface InventoryItem {
/** /**
* Internal ID of an Item, Long * Internal ID of an Item, Long
* 0-4096: Tiles * 0-4095: Tiles
* 4097-32767: Static items * 4096-32767: Static items
* 32768-16777215: Dynamic items * 32768-16777215: Dynamic items
* >= 16777216: Actor RefID * >= 16777216: Actor RefID
*/ */
val itemID: Int val itemID: Int
/** /**
* Weight of the item * Base mass of the item. Real mass must be calculated from
* mass * scale^3
*/ */
var mass: Double var mass: Double
/** /**
* Scale of the item. Real mass: mass * (scale^3) * Scale of the item.
* *
* For static item, it must be 1.0. If you tinkered the item to be bigger, * For static item, it must be 1.0. If you tinkered the item to be bigger,
* it must be re-assigned as Dynamic Item * it must be re-assigned as Dynamic Item
@@ -57,10 +58,4 @@ interface InventoryItem {
* Effects applied (continuously or not) while thrown to the world * Effects applied (continuously or not) while thrown to the world
*/ */
fun effectWhenTakenOut(gc: GameContainer, delta: Int) fun effectWhenTakenOut(gc: GameContainer, delta: Int)
/**
* Effects applied (continuously or not) while thrown to the world,
* called by the proxy Actor
*/
fun worldActorEffect(gc: GameContainer, delta: Int)
} }

View File

@@ -0,0 +1,30 @@
package net.torvald.terrarum.gameitem
import org.newdawn.slick.GameContainer
/**
* Created by SKYHi14 on 2016-12-12.
*/
abstract class InventoryItemAdapter : InventoryItem {
override abstract val itemID: Int
override abstract var mass: Double
override abstract var scale: Double
override fun effectWhileInPocket(gc: GameContainer, delta: Int) {
}
override fun effectWhenPickedUp(gc: GameContainer, delta: Int) {
}
override fun primaryUse(gc: GameContainer, delta: Int) {
}
override fun secondaryUse(gc: GameContainer, delta: Int) {
}
override fun effectWhenThrown(gc: GameContainer, delta: Int) {
}
override fun effectWhenTakenOut(gc: GameContainer, delta: Int) {
}
}

View File

@@ -5,7 +5,11 @@ import net.torvald.terrarum.KVHashMap
import net.torvald.terrarum.gameactors.CanBeAnItem import net.torvald.terrarum.gameactors.CanBeAnItem
import net.torvald.terrarum.gameitem.InventoryItem import net.torvald.terrarum.gameitem.InventoryItem
import net.torvald.terrarum.Terrarum import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.gameitem.InventoryItemAdapter
import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.tileproperties.TileProp
import net.torvald.terrarum.tileproperties.TilePropCodex
import org.apache.commons.csv.CSVRecord
import org.newdawn.slick.GameContainer import org.newdawn.slick.GameContainer
import java.util.* import java.util.*
@@ -14,23 +18,39 @@ import java.util.*
*/ */
object ItemPropCodex { object ItemPropCodex {
val CSV_PATH = "./src/com/torvald/terrarum/itemproperties/itemprop.csv"
/** /**
* <ItemID or RefID for Actor, TheItem> * <ItemID or RefID for Actor, TheItem>
* Will return corresponding Actor if ID >= 16777216 * Will return corresponding Actor if ID >= 16777216
*/ */
private val itemCodex = ArrayList<InventoryItem>() private val itemCodex = HashMap<Int, InventoryItem>()
private val dynamicItemDescription = HashMap<Int, KVHashMap>() private val dynamicItemDescription = HashMap<Int, KVHashMap>()
val ITEM_TILE_MAX = GameWorld.TILES_SUPPORTED val ITEM_TILE_MAX = GameWorld.TILES_SUPPORTED - 1 // 4095
val ITEM_COUNT_MAX = 16777216 val ITEM_COUNT_MAX = 16777216
val ITEM_DYNAMIC_MAX = ITEM_COUNT_MAX - 1 val ITEM_DYNAMIC_MAX = ITEM_COUNT_MAX - 1
val ITEM_STATIC_MAX = 32767 val ITEM_STATIC_MAX = 32767
val ITEM_DYNAMIC_MIN = ITEM_STATIC_MAX + 1 val ITEM_DYNAMIC_MIN = ITEM_STATIC_MAX + 1
val ITEM_STATIC_MIN = ITEM_TILE_MAX val ITEM_STATIC_MIN = ITEM_TILE_MAX + 1 // 4096
init { init {
// tile items
for (i in 0..ITEM_TILE_MAX) {
itemCodex[i] = object : InventoryItemAdapter() {
override val itemID: Int = i
override var mass: Double = TilePropCodex.getProp(i).density / 1000.0
// no need to set setter as scale would not change
override var scale: Double = 1.0
override fun primaryUse(gc: GameContainer, delta: Int) {
// TODO base punch attack
}
override fun secondaryUse(gc: GameContainer, delta: Int) {
// TODO place block to the world
}
}
}
// read prop in csv and fill itemCodex // read prop in csv and fill itemCodex
// read from save (if applicable) and fill dynamicItemDescription // read from save (if applicable) and fill dynamicItemDescription
@@ -38,7 +58,7 @@ object ItemPropCodex {
fun getProp(code: Int): InventoryItem { fun getProp(code: Int): InventoryItem {
if (code < ITEM_STATIC_MAX) // generic item if (code < ITEM_STATIC_MAX) // generic item
return itemCodex[code] // from CSV return itemCodex[code]!! // from CSV
else if (code < ITEM_DYNAMIC_MAX) { else if (code < ITEM_DYNAMIC_MAX) {
TODO("read from dynamicitem description (JSON)") TODO("read from dynamicitem description (JSON)")
} }