DEADSOFTWARE

New saving fromat and rewrite in kotlin
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / mobs / player / Inventory.kt
index 4469038ba6f7a1632c54297202650085b02e00e0..8f0b90d721a709f3b5c2015d16d82c943ae1e779 100644 (file)
@@ -1,51 +1,85 @@
 package ru.deadsoftware.cavedroid.game.mobs.player
 
 import ru.deadsoftware.cavedroid.game.GameItemsHolder
+import ru.deadsoftware.cavedroid.game.model.dto.SaveDataDto
 import ru.deadsoftware.cavedroid.game.model.item.InventoryItem
 import ru.deadsoftware.cavedroid.game.model.item.Item
-import ru.deadsoftware.cavedroid.game.objects.Drop
+import ru.deadsoftware.cavedroid.game.objects.drop.Drop
+import ru.deadsoftware.cavedroid.game.ui.TooltipManager
+import ru.deadsoftware.cavedroid.misc.Saveable
 import java.io.Serializable
 
-class Inventory(
+class Inventory @JvmOverloads constructor(
     val size: Int,
     val hotbarSize: Int,
-    gameItemsHolder: GameItemsHolder
-) : Serializable {
+    gameItemsHolder: GameItemsHolder,
+    tooltipManager: TooltipManager,
+    initialItems: List<InventoryItem>? = null
+) : Serializable, Saveable {
+
+    @Suppress("UNNECESSARY_LATEINIT")
+    @Transient
+    private lateinit var tooltipManager: TooltipManager
+
+    @Suppress("UNNECESSARY_LATEINIT")
+    @Transient
+    private lateinit var fallbackItem: InventoryItem
+
+    private val _items: Array<InventoryItem>
 
     init {
+        fallbackItem = gameItemsHolder.fallbackItem.toInventoryItem()
+        this.tooltipManager = tooltipManager
+
         if (size < 0 || hotbarSize < 0 || hotbarSize > size) {
             throw IllegalArgumentException("Invalid inventory sizes: hotbarSize=$hotbarSize; size=$size")
         }
-    }
 
-    private val _items = Array(size) { InventoryItem(gameItemsHolder.fallbackItem) }
+        _items = Array(size) { index -> initialItems?.getOrNull(index) ?: InventoryItem(gameItemsHolder.fallbackItem) }
+    }
 
     val items get() = _items.asList() as MutableList<InventoryItem>
 
     val hotbarItems get() = items.subList(0, hotbarSize)
 
-    var activeSlot = 0
+    private var _activeSlot = 0
+
+    var activeSlot
+        get() = _activeSlot
         set(value) {
             if (value in 0 ..< hotbarSize) {
-                field = value
+                _activeSlot = value
+                showCurrentItemTooltip()
             }
         }
 
-    val activeItem get() = items[activeSlot]
+    fun showCurrentItemTooltip() {
+        tooltipManager.showHotbarTooltip(activeItem.item.params.name)
+    }
 
-    fun initItems(gameItemsHolder: GameItemsHolder) {
-        items.forEach { item ->
+    val activeItem get() = _items[activeSlot]
+
+    fun initItems(gameItemsHolder: GameItemsHolder, tooltipManager: TooltipManager) {
+        this.tooltipManager = tooltipManager
+        fallbackItem = gameItemsHolder.fallbackItem.toInventoryItem()
+        _items.forEach { item ->
             item.init(gameItemsHolder)
         }
     }
 
-    private fun getItemPickSlot(item: Item): Int {
-        for (i in items.indices) {
-            val inventoryItem = items[i]
+    private fun getItemPickSlot(drop: Drop): Int {
+        val item = drop.item
+
+        for (i in _items.indices) {
+            val inventoryItem = _items[i]
 
             if (item == inventoryItem.item && inventoryItem.canBeAdded()) {
                 return i
             }
+        }
+
+        for (i in _items.indices) {
+            val inventoryItem = _items[i]
 
             if (inventoryItem.item.isNone()) {
                 return i
@@ -55,19 +89,29 @@ class Inventory(
         return -1
     }
 
-    fun canPickItem(item: Item): Boolean {
-        return getItemPickSlot(item) >= 0
+    fun canPickItem(drop: Drop): Boolean {
+        return getItemPickSlot(drop) >= 0
     }
 
     fun pickDrop(drop: Drop) {
-        val slot = getItemPickSlot(drop.item).takeIf { it >= 0 } ?: return
-        val inventoryItem = items[slot]
+        val slot = getItemPickSlot(drop).takeIf { it >= 0 } ?: return
+        val inventoryItem = _items[slot]
 
         if (inventoryItem.item == drop.item) {
-            inventoryItem.add()
-            drop.pickedUp = true
+            if (inventoryItem.canBeAdded(drop.amount)) {
+                inventoryItem.add(drop.amount)
+                drop.pickedUp = true
+            } else {
+                val addCount = inventoryItem.item.params.maxStack - inventoryItem.amount
+                inventoryItem.add(addCount)
+                drop.subtract(addCount)
+                pickDrop(drop)
+            }
         } else {
-            _items[slot] = drop.item.toInventoryItem()
+            _items[slot] = drop.item.toInventoryItem(drop.amount)
+            if (slot == activeSlot) {
+                showCurrentItemTooltip()
+            }
             drop.pickedUp = true
         }
     }
@@ -81,5 +125,58 @@ class Inventory(
         )
 
         _items[0] = item.toInventoryItem(item.params.maxStack)
+        showCurrentItemTooltip()
+    }
+
+    @JvmOverloads
+    fun decreaseItemAmount(slot: Int, count: Int = 1) {
+        val item = _items[slot]
+        item.subtract(count)
+        if (item.amount <= 0) {
+            _items[slot] = fallbackItem
+        }
+    }
+
+    @JvmOverloads
+    fun decreaseCurrentItemAmount(count: Int = 1) {
+        decreaseItemAmount(activeSlot, count)
+    }
+
+    fun clear() {
+        for (i in _items.indices) {
+            _items[i] = fallbackItem
+        }
+    }
+
+    override fun getSaveData(): SaveDataDto.InventorySaveData {
+        return SaveDataDto.InventorySaveData(
+            version = SAVE_DATA_VERSION,
+            size = size,
+            hotbarSize = hotbarSize,
+            activeSlot = _activeSlot,
+            items = items.map(InventoryItem::getSaveData)
+        )
+    }
+
+    companion object {
+        private const val SAVE_DATA_VERSION = 1
+
+        fun fromSaveData(
+            saveData: SaveDataDto.InventorySaveData,
+            gameItemsHolder: GameItemsHolder,
+            tooltipManager: TooltipManager,
+        ): Inventory {
+            saveData.verifyVersion(SAVE_DATA_VERSION)
+
+            return Inventory(
+                size = saveData.size,
+                hotbarSize = saveData.hotbarSize,
+                gameItemsHolder = gameItemsHolder,
+                tooltipManager = tooltipManager,
+                initialItems = saveData.items.map { item -> InventoryItem.fromSaveData(item, gameItemsHolder) }
+            ).apply {
+                _activeSlot = saveData.activeSlot
+            }
+        }
     }
 }
\ No newline at end of file