DEADSOFTWARE

1fbcd3dbfe8313c8beaccd390b10b89041c01518
[cavedroid.git] / core / src / ru / deadsoftware / cavedroid / game / GameItemsHolder.kt
1 package ru.deadsoftware.cavedroid.game
3 import com.badlogic.gdx.Gdx
4 import kotlinx.serialization.json.Json
5 import ru.deadsoftware.cavedroid.game.model.block.Block
6 import ru.deadsoftware.cavedroid.game.model.dto.BlockDto
7 import ru.deadsoftware.cavedroid.game.model.dto.GameItemsDto
8 import ru.deadsoftware.cavedroid.game.model.dto.ItemDto
9 import ru.deadsoftware.cavedroid.game.model.item.Item
10 import ru.deadsoftware.cavedroid.game.model.mapper.BlockMapper
11 import ru.deadsoftware.cavedroid.game.model.mapper.ItemMapper
12 import ru.deadsoftware.cavedroid.misc.utils.AssetLoader
13 import javax.inject.Inject
15 @GameScope
16 class GameItemsHolder @Inject constructor(
17 private val assetLoader: AssetLoader,
18 private val blockMapper: BlockMapper,
19 private val itemMapper: ItemMapper,
20 ) {
22 private var _initialized: Boolean = false
24 private val blocksMap = LinkedHashMap<String, Block>()
25 private val itemsMap = LinkedHashMap<String, Item>()
27 lateinit var fallbackBlock: Block
28 private set
29 lateinit var fallbackItem: Item
30 private set
32 init {
33 initialize()
34 }
36 private fun loadBlocks(dtoMap: Map<String, BlockDto>) {
37 dtoMap.forEach { (key, dto) ->
38 blocksMap[key] = blockMapper.map(key, dto)
39 .apply(Block::initialize)
40 }
42 fallbackBlock = blocksMap[FALLBACK_BLOCK_KEY]
43 ?: throw IllegalArgumentException("Fallback block key '$FALLBACK_BLOCK_KEY' not found")
44 }
46 private fun loadItems(dtoMap: Map<String, ItemDto>) {
47 if (dtoMap.isNotEmpty() && blocksMap.isEmpty()) {
48 throw IllegalStateException("items should be loaded after blocks")
49 }
51 dtoMap.forEach { (key, dto) ->
52 try {
53 itemsMap[key] = itemMapper.map(
54 key = key,
55 dto = dto,
56 block = blocksMap[key],
57 slabTopBlock = blocksMap[dto.topSlabBlock] as? Block.Slab,
58 slabBottomBlock = blocksMap[dto.bottomSlabBlock] as? Block.Slab
59 )
60 } catch (e: Exception) {
61 Gdx.app.error(TAG, "Failed to map item $key. Reason: ${e.message}")
62 e.printStackTrace()
63 }
64 }
66 fallbackItem = itemsMap[FALLBACK_ITEM_KEY]
67 ?: throw IllegalArgumentException("Fallback item key '$FALLBACK_ITEM_KEY' not found")
68 }
70 fun initialize() {
71 if (_initialized) {
72 Gdx.app.debug(TAG, "Attempted to init when already initialized")
73 return
74 }
76 val jsonString = assetLoader.getAssetHandle("json/game_items.json").readString()
77 val gameItemsDto = JsonFormat.decodeFromString<GameItemsDto>(jsonString)
79 loadBlocks(gameItemsDto.blocks)
80 loadItems(gameItemsDto.items)
82 _initialized = true
83 }
85 private fun <T> Map<String, T>.getOrFallback(key: String, fallback: T, lazyErrorMessage: () -> String): T {
86 if (!_initialized) {
87 throw IllegalStateException("GameItemsHolder was not initialized before use")
88 }
90 val t = this[key] ?: run {
91 Gdx.app.error(TAG, lazyErrorMessage.invoke())
92 return fallback
93 }
94 return t
95 }
97 fun getBlock(key: String): Block {
98 return blocksMap.getOrFallback(key, fallbackBlock) {
99 "No block with key '$key' found. Returning $FALLBACK_BLOCK_KEY"
103 fun getItem(key: String): Item {
104 return itemsMap.getOrFallback(key, fallbackItem) {
105 "No item with key '$key' found. Returning $FALLBACK_BLOCK_KEY"
109 fun getAllItems(): Collection<Item> {
110 return itemsMap.values
113 fun getItemFromCreativeInventory(position: Int): Item {
114 return if (position in itemsMap.values.indices) {
115 itemsMap.values.elementAt(position)
116 } else {
117 fallbackItem
121 fun getMaxCreativeScrollAmount(): Int = itemsMap.size / 8
123 fun <T : Block> getBlocksByType(type: Class<T>): List<T> {
124 return blocksMap.values.filterIsInstance(type)
127 companion object {
128 private const val TAG = "GameItemsHolder"
130 private val JsonFormat = Json { ignoreUnknownKeys = true }
132 const val FALLBACK_BLOCK_KEY = "none"
133 const val FALLBACK_ITEM_KEY = "none"