Skip to content

Commit 1a4d86b

Browse files
committed
Fixed config loading; Better collection settings
1 parent 342b9da commit 1a4d86b

File tree

7 files changed

+120
-43
lines changed

7 files changed

+120
-43
lines changed

src/main/kotlin/com/lambda/Lambda.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ object Lambda : ClientModInitializer {
8080
.registerTypeAdapter(Optional::class.java, OptionalCodec)
8181
.registerTypeAdapter(ItemStack::class.java, ItemStackCodec)
8282
.registerTypeAdapter(Text::class.java, Text.Serializer(DynamicRegistryManager.EMPTY))
83-
// We have to add all item sub classes :/. I probably missed some
8483
.registerTypeAdapter(Item::class.java, ItemCodec)
8584
.registerTypeAdapter(BlockItem::class.java, ItemCodec)
8685
.registerTypeAdapter(ArrowItem::class.java, ItemCodec)

src/main/kotlin/com/lambda/config/Configuration.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -135,16 +135,18 @@ abstract class Configuration : Jsonable, Loadable {
135135
LOG.info(message)
136136
info(message)
137137
}
138-
.onFailure {
139-
var message: String
138+
.onFailure { primaryError ->
139+
throw primaryError
140+
LOG.error(primaryError)
141+
140142
runCatching { load(backup) }
141143
.onSuccess {
142-
message = "${configName.capitalize()} config loaded from backup"
144+
val message = "${configName.capitalize()} config loaded from backup"
143145
LOG.info(message)
144146
info(message)
145147
}
146148
.onFailure { error ->
147-
message = "Failed to load ${configName.capitalize()} config from backup, unrecoverable error"
149+
val message = "Failed to load ${configName.capitalize()} config from backup, unrecoverable error"
148150
LOG.error(message, error)
149151
logError(message)
150152
}

src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
package com.lambda.config.settings.collections
1919

20+
import com.google.gson.JsonElement
2021
import com.google.gson.reflect.TypeToken
22+
import com.lambda.Lambda.gson
2123
import com.lambda.config.serializer.BlockCodec
2224
import com.lambda.gui.dsl.ImGuiBuilder
2325
import imgui.flag.ImGuiSelectableFlags.DontClosePopups
@@ -68,4 +70,11 @@ class BlockCollectionSetting(
6870
}
6971
}
7072
}
73+
74+
override fun toJson(): JsonElement = gson.toJsonTree(value, type)
75+
76+
override fun loadFromJson(serialized: JsonElement) {
77+
value = gson.fromJson<Collection<Block>>(serialized, type)
78+
.toMutableList()
79+
}
7180
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
/*
2+
* Copyright 2025 Lambda
3+
*
4+
* This program is free software: you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License as published by
6+
* the Free Software Foundation, either version 3 of the License, or
7+
* (at your option) any later version.
8+
*
9+
* This program is distributed in the hope that it will be useful,
10+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
* GNU General Public License for more details.
13+
*
14+
* You should have received a copy of the GNU General Public License
15+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
16+
*/
17+
18+
package com.lambda.config.settings.collections
19+
20+
import com.google.gson.JsonElement
21+
import com.google.gson.reflect.TypeToken
22+
import com.lambda.Lambda.gson
23+
import com.lambda.gui.dsl.ImGuiBuilder
24+
import imgui.flag.ImGuiSelectableFlags.DontClosePopups
25+
26+
/**
27+
* @see [com.lambda.config.settings.collections.CollectionSettings]
28+
* @see [com.lambda.config.Configurable]
29+
*/
30+
class ClassCollectionSetting<T : Any>(
31+
override var name: String,
32+
private val immutableCollection: Collection<T>,
33+
defaultValue: MutableCollection<T>,
34+
description: String,
35+
visibility: () -> Boolean,
36+
) : CollectionSetting<T>(
37+
name,
38+
immutableCollection,
39+
defaultValue,
40+
TypeToken.getParameterized(Collection::class.java, Any::class.java).type,
41+
description,
42+
visibility,
43+
) {
44+
override fun ImGuiBuilder.buildLayout() {
45+
combo("##$name", "$name: ${value.size} item(s)") {
46+
immutableCollection
47+
.forEach {
48+
val isSelected = value.contains(it)
49+
50+
selectable(
51+
label = it.className,
52+
selected = isSelected,
53+
flags = DontClosePopups,
54+
) {
55+
if (isSelected) value.remove(it)
56+
else value.add(it)
57+
}
58+
}
59+
}
60+
}
61+
62+
val Any.className: String get() = this::class.java.name
63+
.substringAfter("${this::class.java.packageName}.")
64+
.replace('$', '.')
65+
66+
// When serializing the list to json we do not want to serialize the elements' classes, but their stringified representation.
67+
// If we do serialize the classes we'll run into missing type adapters errors by Gson.
68+
// This is intended behaviour. If you wish your collection settings to display something else then you must extend this class.
69+
override fun toJson(): JsonElement = gson.toJsonTree(value.map { it.className })
70+
71+
override fun loadFromJson(serialized: JsonElement) {
72+
val strList = gson.fromJson<MutableList<String>>(serialized, type)
73+
.mapNotNull { str -> immutableCollection.find { it.className == str } }
74+
.toMutableList()
75+
76+
value = strList
77+
}
78+
}

src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package com.lambda.config.settings.collections
1919

2020
import com.google.gson.JsonElement
21+
import com.google.gson.reflect.TypeToken
2122
import com.lambda.Lambda.gson
2223
import com.lambda.config.AbstractSetting
2324
import com.lambda.config.SettingEditorDsl
@@ -28,6 +29,13 @@ import imgui.flag.ImGuiSelectableFlags.DontClosePopups
2829
import java.lang.reflect.Type
2930

3031
/**
32+
* This generic collection settings handles all [Comparable] values (i.e not classes) and serialize
33+
* their values by calling [Any.toString] and loads them by comparing what's in the [immutableCollection].
34+
* This behaviour is by design. If you wish to store collections of non-comparable values you must use [ClassCollectionSetting].
35+
*
36+
* If you wish to use a different codec or simply display values differently you must create your own
37+
* collection setting.
38+
*
3139
* @see [com.lambda.config.Configurable]
3240
*/
3341
open class CollectionSetting<T : Any>(
@@ -44,6 +52,9 @@ open class CollectionSetting<T : Any>(
4452
description,
4553
visibility
4654
) {
55+
private val strListType =
56+
TypeToken.getParameterized(Collection::class.java, String::class.java).type
57+
4758
private val selectListeners = mutableListOf<SafeContext.(T) -> Unit>()
4859
private val deselectListeners = mutableListOf<SafeContext.(T) -> Unit>()
4960

@@ -73,9 +84,15 @@ open class CollectionSetting<T : Any>(
7384
}
7485
}
7586

87+
override fun toJson(): JsonElement =
88+
gson.toJsonTree(value.map { it.toString() })
89+
7690
override fun loadFromJson(serialized: JsonElement) {
77-
value = gson.fromJson<Collection<T>>(serialized, type)
91+
val strList = gson.fromJson<Collection<String>>(serialized, strListType)
92+
.mapNotNull { str -> immutableCollection.find { it.toString() == str } }
7893
.toMutableList()
94+
95+
value = strList
7996
}
8097

8198
companion object {

src/main/kotlin/com/lambda/config/settings/collections/EventCollectionSetting.kt

Lines changed: 0 additions & 37 deletions
This file was deleted.

src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
package com.lambda.config.settings.collections
1919

20+
import com.google.gson.JsonElement
2021
import com.google.gson.reflect.TypeToken
22+
import com.lambda.Lambda.gson
2123
import com.lambda.config.serializer.ItemCodec
2224
import com.lambda.gui.dsl.ImGuiBuilder
2325
import imgui.flag.ImGuiSelectableFlags.DontClosePopups
@@ -68,4 +70,11 @@ class ItemCollectionSetting(
6870
}
6971
}
7072
}
73+
74+
override fun toJson(): JsonElement = gson.toJsonTree(value, type)
75+
76+
override fun loadFromJson(serialized: JsonElement) {
77+
value = gson.fromJson<Collection<Item>>(serialized, type)
78+
.toMutableList()
79+
}
7180
}

0 commit comments

Comments
 (0)