DEADSOFTWARE

Store block references intead of ids
[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 itemsMap[key] = itemMapper.map(key, dto, blocksMap[key])
53 }
55 fallbackItem = itemsMap[FALLBACK_ITEM_KEY]
56 ?: throw IllegalArgumentException("Fallback item key '$FALLBACK_ITEM_KEY' not found")
57 }
59 fun initialize() {
60 if (_initialized) {
61 Gdx.app.debug(TAG, "Attempted to init when already initialized")
62 return
63 }
65 val jsonString = assetLoader.getAssetHandle("json/game_items.json").readString()
66 val gameItemsDto = JsonFormat.decodeFromString(GameItemsDto.GameItemsDtoJsonSerializer, jsonString)
68 loadBlocks(gameItemsDto.blocks)
69 loadItems(gameItemsDto.items)
71 _initialized = true
72 }
74 private fun <T> Map<String, T>.getOrFallback(key: String, fallback: T, lazyErrorMessage: () -> String): T {
75 if (!_initialized) {
76 throw IllegalStateException("GameItemsHolder was not initialized before use")
77 }
79 val t = this[key] ?: run {
80 Gdx.app.error(TAG, lazyErrorMessage.invoke())
81 return fallback
82 }
83 return t
84 }
86 fun getBlock(key: String): Block {
87 return blocksMap.getOrFallback(key, fallbackBlock) {
88 "No block with key '$key' found. Returning $FALLBACK_BLOCK_KEY"
89 }
90 }
92 fun getItem(key: String): Item {
93 return itemsMap.getOrFallback(key, fallbackItem) {
94 "No item with key '$key' found. Returning $FALLBACK_BLOCK_KEY"
95 }
96 }
98 fun <T : Block> getBlocksByType(type: Class<T>): List<T> {
99 return blocksMap.values.filterIsInstance(type)
102 companion object {
103 private const val TAG = "GameItemsHolder"
105 private val JsonFormat = Json { ignoreUnknownKeys = true }
107 const val FALLBACK_BLOCK_KEY = "none"
108 const val FALLBACK_ITEM_KEY = "none"