DEADSOFTWARE

92eeab9eae5dcb239746a19c66e7139fd0e54ca9
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / objects / container / Furnace.kt
1 package ru.deadsoftware.cavedroid.game.objects.container
3 import com.badlogic.gdx.Gdx
4 import com.badlogic.gdx.math.MathUtils
5 import com.badlogic.gdx.utils.TimeUtils
6 import ru.deadsoftware.cavedroid.game.GameItemsHolder
7 import ru.deadsoftware.cavedroid.game.model.dto.SaveDataDto
8 import ru.deadsoftware.cavedroid.game.model.item.InventoryItem
9 import ru.deadsoftware.cavedroid.game.model.item.InventoryItem.Companion.isNoneOrNull
10 import ru.deadsoftware.cavedroid.game.model.item.Item
11 import ru.deadsoftware.cavedroid.misc.Saveable
13 class Furnace @JvmOverloads constructor(
14 gameItemsHolder: GameItemsHolder,
15 initialItems: List<InventoryItem>? = null
16 ) : Container(SIZE, gameItemsHolder, initialItems), Saveable {
18 var fuel: InventoryItem
19 get() = items[FUEL_INDEX]
20 set(value) {
21 items[FUEL_INDEX] = value
22 }
24 var input: InventoryItem
25 get() = items[INPUT_INDEX]
26 set(value) {
27 items[INPUT_INDEX] = value
28 }
30 var result: InventoryItem
31 get() = items[RESULT_INDEX]
32 set(value) {
33 items[RESULT_INDEX] = value
34 }
36 val isActive: Boolean get() = currentFuel != null
38 @Transient
39 var currentFuel: Item? = null
40 set(value) {
41 currentFuelKey = value?.params?.key
42 field = value
43 }
45 var currentFuelKey: String? = null
47 private var startBurnTimeMs = 0L
48 private var smeltStarTimeMs = 0L
50 var burnProgress = 0f
51 private set(value) {
52 field = MathUtils.clamp(value, 0f, 1f)
53 }
54 var smeltProgress = 0f
55 private set(value) {
56 field = MathUtils.clamp(value, 0f, 1f)
57 }
59 fun init(gameItemsHolder: GameItemsHolder) {
60 currentFuel = currentFuelKey?.let { gameItemsHolder.getItem(it) }
61 items.forEach { it.init(gameItemsHolder) }
62 }
64 fun canSmelt(): Boolean {
65 return (result.isNoneOrNull() || (result.item.params.key == input.item.params.smeltProductKey)) &&
66 !input.isNoneOrNull() && input.item.params.smeltProductKey != null &&
67 (!fuel.isNoneOrNull() || burnProgress > 0f)
68 }
70 private fun startBurning(gameItemsHolder: GameItemsHolder) {
71 requireNotNull(fuel.item.params.burningTimeMs) { "Cant start burning without fuel" }
72 currentFuel = fuel.item
73 fuel.subtract()
74 if (fuel.amount <= 0) {
75 fuel = gameItemsHolder.fallbackItem.toInventoryItem()
76 }
77 startBurnTimeMs = TimeUtils.millis()
78 burnProgress = 0f
79 }
81 override fun update(gameItemsHolder: GameItemsHolder) {
82 if (currentFuel?.isNone() == true) {
83 currentFuel = null
84 }
86 currentFuel?.let { curFuel ->
87 val burningTimeMs = curFuel.params.burningTimeMs ?: run {
88 Gdx.app.error(TAG, "Burning item has no burning time. Item : ${curFuel.params.key}")
89 return
90 }
92 if (TimeUtils.timeSinceMillis(startBurnTimeMs).toDouble() / burningTimeMs >= 0.01) {
93 burnProgress += 0.01f
94 startBurnTimeMs = TimeUtils.millis()
95 }
97 }
99 if (currentFuel?.isNone() == false && burnProgress >= 1f) {
100 if (canSmelt()) {
101 startBurning(gameItemsHolder)
102 } else {
103 currentFuel = null
104 burnProgress = 0f
105 smeltProgress = 0f
109 if (!canSmelt()) {
110 return
112 if (currentFuel == null && !fuel.isNoneOrNull()) {
113 startBurning(gameItemsHolder)
114 smeltStarTimeMs = startBurnTimeMs
115 smeltProgress = 0f
118 if ((TimeUtils.timeSinceMillis(smeltStarTimeMs).toDouble() / SMELTING_TIME_MS) >= 0.01) {
119 smeltProgress += 0.01f
120 smeltStarTimeMs = TimeUtils.millis()
123 if (isActive && smeltProgress >= 1f) {
124 val productKey = requireNotNull(input.item.params.smeltProductKey)
125 val res = gameItemsHolder.getItem(productKey)
126 if (result.isNoneOrNull()) {
127 result = res.toInventoryItem()
128 } else {
129 result.add()
131 input.subtract()
132 if (input.amount <= 0) {
133 input = gameItemsHolder.fallbackItem.toInventoryItem()
135 smeltStarTimeMs = TimeUtils.millis()
136 smeltProgress = 0f
140 override fun getSaveData(): SaveDataDto.FurnaceSaveData {
141 return SaveDataDto.FurnaceSaveData(
142 version = SAVE_DATA_VERSION,
143 size = size,
144 currentFuelItemKey = currentFuelKey,
145 items = items.map(InventoryItem::getSaveData),
146 startBurnTimeMs = startBurnTimeMs,
147 startSmeltTimeMs = smeltStarTimeMs,
148 burnProgress = burnProgress,
149 smeltProgress = smeltProgress,
153 companion object {
154 private const val SAVE_DATA_VERSION = 1
155 private const val SIZE = 3
156 private const val TAG = "Furnace"
158 const val FUEL_INDEX = 0
159 const val INPUT_INDEX = 1
160 const val RESULT_INDEX = 2
162 const val SMELTING_TIME_MS = 10000L
164 fun fromSaveData(saveData: SaveDataDto.FurnaceSaveData, gameItemsHolder: GameItemsHolder): Furnace {
165 saveData.verifyVersion(SAVE_DATA_VERSION)
167 return Furnace(
168 gameItemsHolder = gameItemsHolder,
169 initialItems = saveData.items.map { item ->
170 InventoryItem.fromSaveData(item, gameItemsHolder)
172 ).apply {
173 currentFuelKey = saveData.currentFuelItemKey
174 startBurnTimeMs = saveData.startSmeltTimeMs
175 smeltStarTimeMs = saveData.startSmeltTimeMs
176 burnProgress = saveData.burnProgress
177 smeltProgress = saveData.smeltProgress