DEADSOFTWARE

Refactor window controls
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / model / item / InventoryItem.kt
1 package ru.deadsoftware.cavedroid.game.model.item
3 import com.badlogic.gdx.graphics.Color
4 import com.badlogic.gdx.graphics.g2d.SpriteBatch
5 import com.badlogic.gdx.graphics.glutils.ShapeRenderer
6 import ru.deadsoftware.cavedroid.game.GameItemsHolder
7 import ru.deadsoftware.cavedroid.game.mobs.player.Inventory
8 import ru.deadsoftware.cavedroid.misc.Assets
9 import ru.deadsoftware.cavedroid.misc.utils.drawSprite
10 import ru.deadsoftware.cavedroid.misc.utils.drawString
11 import ru.deadsoftware.cavedroid.misc.utils.px
12 import java.io.Serializable
13 import kotlin.contracts.ExperimentalContracts
14 import kotlin.contracts.contract
16 class InventoryItem @JvmOverloads constructor(
17 val itemKey: String,
18 _amount: Int = 1,
19 ) : Serializable {
21 var amount = _amount
22 set(value) {
23 field = if (value < 0) {
24 0
25 } else {
26 value
27 }
28 }
30 @Transient
31 lateinit var item: Item
32 private set
34 @JvmOverloads
35 constructor(_item: Item, amount: Int = 1) : this(_item.params.key, amount) {
36 item = _item
37 }
39 fun init(gameItemsHolder: GameItemsHolder) {
40 if (this::item.isInitialized) {
41 return
42 }
43 item = gameItemsHolder.getItem(itemKey)
44 }
46 @JvmOverloads
47 fun add(count: Int = 1) {
48 if (count > 0 && Int.MAX_VALUE - count < amount) {
49 throw IllegalArgumentException("$amount + $count exceeds Int.MAX_VALUE")
50 }
52 amount += count
53 }
55 @JvmOverloads
56 fun subtract(count: Int = 1) {
57 if (count < 0) {
58 throw IllegalArgumentException("Can't subtract negative amount")
59 }
61 add(-count)
62 }
64 @JvmOverloads
65 fun canBeAdded(count: Int = 1): Boolean {
66 return amount + count <= item.params.maxStack
67 }
69 private fun drawAmountText(spriteBatch: SpriteBatch, text: String, x: Float, y: Float) {
70 spriteBatch.drawString(text, x + 1, y + 1, Color.BLACK)
71 spriteBatch.drawString(text, x, y, Color.WHITE)
72 }
74 fun drawSelected(spriteBatch: SpriteBatch, x: Float, y: Float) {
75 if (item.isNone()) {
76 return
77 }
79 val sprite = item.sprite
80 val amountString = amount.toString()
81 spriteBatch.drawSprite(sprite, x - 10f, y - 10f, rotation = 0f, width = 20f, height = 20f)
82 drawAmountText(
83 spriteBatch = spriteBatch,
84 text = amountString,
85 x = x + 10f - Assets.getStringWidth(amountString) + 1f,
86 y = y + 10f - Assets.getStringHeight(amountString) + 1f
87 )
88 }
90 fun draw(spriteBatch: SpriteBatch, shapeRenderer: ShapeRenderer, x: Float, y: Float) {
91 if (item.isNone()) {
92 return
93 }
95 val sprite = item.sprite
96 val placeableMarginTop = (item as? Item.Placeable)?.block?.params?.spriteMargins?.top ?: 0
97 val placeableMarginLeft = (item as? Item.Placeable)?.block?.params?.spriteMargins?.left ?: 0
98 spriteBatch.drawSprite(sprite, x + placeableMarginLeft, y + placeableMarginTop)
100 if (amount < 2) {
101 return
104 if (item.isTool()) {
105 spriteBatch.end()
106 shapeRenderer.begin(ShapeRenderer.ShapeType.Filled)
107 shapeRenderer.color = Color.GREEN
108 shapeRenderer.rect(
109 /* x = */ x,
110 /* y = */ y + 1.px - 2,
111 /* width = */ 1.px * (amount.toFloat() / item.params.maxStack.toFloat()),
112 /* height = */ 2f
114 shapeRenderer.end()
115 spriteBatch.begin()
116 } else {
117 val amountString = amount.toString()
118 drawAmountText(
119 spriteBatch = spriteBatch,
120 text = amountString,
121 x = x + 1.px - Assets.getStringWidth(amountString),
122 y = y + 1.px - Assets.getStringHeight(amountString)
127 companion object {
129 @OptIn(ExperimentalContracts::class)
130 fun InventoryItem?.isNoneOrNull(): Boolean {
131 contract { returns(false) implies(this@isNoneOrNull != null) }
132 return this?.item == null || this.item.isNone()