Skip to content

Commit 49afd16

Browse files
committed
Attempt at adding collection setting codecs
1 parent 7f58d84 commit 49afd16

File tree

29 files changed

+229
-314
lines changed

29 files changed

+229
-314
lines changed

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

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ package com.lambda
1919

2020
import com.google.gson.Gson
2121
import com.google.gson.GsonBuilder
22-
import com.lambda.config.serializer.BlockPosSerializer
23-
import com.lambda.config.serializer.BlockSerializer
22+
import com.lambda.config.serializer.BlockPosCodec
23+
import com.lambda.config.serializer.BlockCodec
2424
import com.lambda.config.serializer.ColorSerializer
25-
import com.lambda.config.serializer.GameProfileSerializer
26-
import com.lambda.config.serializer.ItemStackSerializer
27-
import com.lambda.config.serializer.KeyCodeSerializer
28-
import com.lambda.config.serializer.OptionalSerializer
25+
import com.lambda.config.serializer.GameProfileCodec
26+
import com.lambda.config.serializer.ItemCodec
27+
import com.lambda.config.serializer.ItemStackCodec
28+
import com.lambda.config.serializer.KeyCodeCodec
29+
import com.lambda.config.serializer.OptionalCodec
2930
import com.lambda.core.Loader
3031
import com.lambda.event.events.ClientEvent
3132
import com.lambda.event.listener.UnsafeListener.Companion.listenOnceUnsafe
@@ -37,7 +38,12 @@ import net.fabricmc.api.ClientModInitializer
3738
import net.fabricmc.loader.api.FabricLoader
3839
import net.minecraft.block.Block
3940
import net.minecraft.client.MinecraftClient
41+
import net.minecraft.item.ArrowItem
42+
import net.minecraft.item.BlockItem
43+
import net.minecraft.item.Item
4044
import net.minecraft.item.ItemStack
45+
import net.minecraft.item.PotionItem
46+
import net.minecraft.item.RangedWeaponItem
4147
import net.minecraft.registry.DynamicRegistryManager
4248
import net.minecraft.text.Text
4349
import net.minecraft.util.math.BlockPos
@@ -66,14 +72,20 @@ object Lambda : ClientModInitializer {
6672

6773
val gson: Gson = GsonBuilder()
6874
.setPrettyPrinting()
69-
.registerTypeAdapter(KeyCode::class.java, KeyCodeSerializer)
75+
.registerTypeAdapter(KeyCode::class.java, KeyCodeCodec)
7076
.registerTypeAdapter(Color::class.java, ColorSerializer)
71-
.registerTypeAdapter(BlockPos::class.java, BlockPosSerializer)
72-
.registerTypeAdapter(Block::class.java, BlockSerializer)
73-
.registerTypeAdapter(GameProfile::class.java, GameProfileSerializer)
74-
.registerTypeAdapter(Optional::class.java, OptionalSerializer)
75-
.registerTypeAdapter(ItemStack::class.java, ItemStackSerializer)
77+
.registerTypeAdapter(BlockPos::class.java, BlockPosCodec)
78+
.registerTypeAdapter(Block::class.java, BlockCodec)
79+
.registerTypeAdapter(GameProfile::class.java, GameProfileCodec)
80+
.registerTypeAdapter(Optional::class.java, OptionalCodec)
81+
.registerTypeAdapter(ItemStack::class.java, ItemStackCodec)
7682
.registerTypeAdapter(Text::class.java, Text.Serializer(DynamicRegistryManager.EMPTY))
83+
// We have to add all item sub classes :/. I probably missed some
84+
.registerTypeAdapter(Item::class.java, ItemCodec)
85+
.registerTypeAdapter(BlockItem::class.java, ItemCodec)
86+
.registerTypeAdapter(ArrowItem::class.java, ItemCodec)
87+
.registerTypeAdapter(PotionItem::class.java, ItemCodec)
88+
.registerTypeAdapter(RangedWeaponItem::class.java, ItemCodec)
7789
.create()
7890

7991
override fun onInitializeClient() {} // nop
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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
19+
20+
import com.google.gson.JsonDeserializer
21+
import com.google.gson.JsonSerializer
22+
23+
interface Stringifiable<T> { fun stringify(value: T): String }
24+
25+
interface Codec<T> : JsonSerializer<T>, JsonDeserializer<T>

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

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,8 @@ import com.lambda.Lambda.LOG
2424
import com.lambda.config.settings.CharSetting
2525
import com.lambda.config.settings.FunctionSetting
2626
import com.lambda.config.settings.StringSetting
27-
import com.lambda.config.settings.collections.ListSetting
27+
import com.lambda.config.settings.collections.CollectionSettings
2828
import com.lambda.config.settings.collections.MapSetting
29-
import com.lambda.config.settings.collections.SetSetting
3029
import com.lambda.config.settings.comparable.BooleanSetting
3130
import com.lambda.config.settings.comparable.EnumSetting
3231
import com.lambda.config.settings.complex.Bind
@@ -123,21 +122,41 @@ abstract class Configurable(
123122
visibility: () -> Boolean = { true },
124123
) = StringSetting(name, defaultValue, multiline, flags, description, visibility).register()
125124

125+
inline fun <reified T : Any> setting(
126+
name: String,
127+
immutableList: Collection<T>,
128+
defaultValue: Collection<T> = immutableList,
129+
description: String = "",
130+
serializer: Stringifiable<T>,
131+
noinline visibility: () -> Boolean = { true },
132+
) = CollectionSettings(
133+
name,
134+
immutableList,
135+
defaultValue.toMutableList(),
136+
TypeToken.getParameterized(MutableList::class.java, T::class.java).type,
137+
description,
138+
serializer,
139+
visibility,
140+
).register()
141+
126142
inline fun <reified T : Any> setting(
127143
name: String,
128-
immutableList: List<T>,
129-
defaultValue: List<T>,
144+
immutableList: Collection<T>,
145+
defaultValue: Collection<T> = immutableList,
130146
description: String = "",
147+
crossinline serializer: (T) -> String = { if (it::class.java.isPrimitive) it.toString() else it::class.java.simpleName },
131148
noinline visibility: () -> Boolean = { true },
132-
) = ListSetting(
149+
) = CollectionSettings(
133150
name,
134151
immutableList,
135152
defaultValue.toMutableList(),
136-
TypeToken.getParameterized(MutableList::class.java, T::class.java).type,
153+
TypeToken.getParameterized(Collection::class.java, T::class.java).type,
137154
description,
155+
object : Stringifiable<T> { override fun stringify(value: T) = serializer(value) },
138156
visibility,
139157
).register()
140158

159+
// ToDo: Actually implement maps
141160
inline fun <reified K : Any, reified V : Any> setting(
142161
name: String,
143162
defaultValue: Map<K, V>,
@@ -151,21 +170,6 @@ abstract class Configurable(
151170
visibility
152171
).register()
153172

154-
inline fun <reified T : Any> setting(
155-
name: String,
156-
immutableList: Set<T>,
157-
defaultValue: Set<T> = immutableList,
158-
description: String = "",
159-
noinline visibility: () -> Boolean = { true },
160-
) = SetSetting(
161-
name,
162-
immutableList,
163-
defaultValue.toMutableSet(),
164-
TypeToken.getParameterized(MutableSet::class.java, T::class.java).type,
165-
description,
166-
visibility,
167-
).register()
168-
169173
fun setting(
170174
name: String,
171175
defaultValue: Double,

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818
package com.lambda.config
1919

2020
import com.lambda.config.configurations.UserAutomationConfigs
21+
import com.lambda.config.serializer.ItemCodec
22+
import com.lambda.module.Module
2123
import com.lambda.module.ModuleRegistry.moduleNameMap
2224

2325
class UserAutomationConfig(override val name: String) : AutomationConfig(name, UserAutomationConfigs) {
24-
val linkedModules = setting("Linked Modules", moduleNameMap.filter { it.value.defaultAutomationConfig != Companion.DEFAULT }.keys, emptySet())
26+
val linkedModules = setting<String>("Linked Modules", moduleNameMap.filter { it.value.defaultAutomationConfig != Companion.DEFAULT }.keys, emptySet(), serializer = { it })
2527
.onSelect { module -> moduleNameMap[module]?.automationConfig = this@UserAutomationConfig }
2628
.onDeselect { module ->
2729
moduleNameMap[module]?.let { module ->

src/main/kotlin/com/lambda/config/groups/ActionConfig.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import com.lambda.util.NamedEnum
2323

2424
interface ActionConfig {
2525
val sorter: SortMode
26-
val tickStageMask: Set<TickEvent>
26+
val tickStageMask: Collection<TickEvent>
2727

2828
enum class SortMode(
2929
override val displayName: String,

src/main/kotlin/com/lambda/config/groups/EatConfig.kt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,19 +31,19 @@ import net.minecraft.item.ItemStack
3131
interface EatConfig {
3232
val eatOnHunger: Boolean
3333
val minFoodLevel: Int
34-
val nutritiousFood: List<Item>
34+
val nutritiousFood: Collection<Item>
3535
val saturated: Saturation
3636

3737
val eatOnFire: Boolean
38-
val resistanceFood: List<Item>
38+
val resistanceFood: Collection<Item>
3939

4040
val eatOnDamage: Boolean
4141
val minDamage: Int
42-
val regenerationFood: List<Item>
42+
val regenerationFood: Collection<Item>
4343

4444
val selectionPriority: SelectionPriority
4545
val ignoreBadFood: Boolean
46-
val badFood: List<Item>
46+
val badFood: Collection<Item>
4747

4848
enum class Saturation(
4949
override val displayName: String,

src/main/kotlin/com/lambda/config/groups/EatSettings.kt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@ package com.lambda.config.groups
1919

2020
import com.lambda.config.Configurable
2121
import com.lambda.config.SettingGroup
22+
import com.lambda.config.serializer.ItemCodec
2223
import com.lambda.util.NamedEnum
24+
import net.minecraft.item.Item
2325
import net.minecraft.item.Items
2426

2527
class EatSettings(
@@ -34,13 +36,13 @@ class EatSettings(
3436
override val eatOnHunger by c.setting("Eat On Hunger", true, "Whether to eat when hungry").group(baseGroup).index()
3537
override val minFoodLevel by c.setting("Minimum Food Level", 6, 0..20, 1, "The minimum food level to eat food", " food level") { eatOnHunger }.group(baseGroup).index()
3638
override val saturated by c.setting("Saturated", EatConfig.Saturation.EatSmart, "When to stop eating") { eatOnHunger }.group(baseGroup).index()
37-
override val nutritiousFood by c.setting("Nutritious Food", nutritiousFoodDefaults, nutritiousFoodDefaults, "Items that are be considered nutritious") { eatOnHunger }.group(baseGroup).index()
39+
override val nutritiousFood by c.setting<Item>("Nutritious Food", nutritiousFoodDefaults, nutritiousFoodDefaults, "Items that are be considered nutritious", ItemCodec) { eatOnHunger }.group(baseGroup).index()
3840
override val selectionPriority by c.setting("Selection Priority", EatConfig.SelectionPriority.MostNutritious, "The priority for selecting food items") { eatOnHunger }.group(baseGroup).index()
3941
override val eatOnFire by c.setting("Eat On Fire", true, "Whether to eat when on fire").group(baseGroup).index()
40-
override val resistanceFood by c.setting("Resistance Food", resistanceFoodDefaults, resistanceFoodDefaults, "Items that give Fire Resistance") { eatOnFire }.group(baseGroup).index()
42+
override val resistanceFood by c.setting<Item>("Resistance Food", resistanceFoodDefaults, resistanceFoodDefaults, "Items that give Fire Resistance", ItemCodec) { eatOnFire }.group(baseGroup).index()
4143
override val eatOnDamage by c.setting("Eat On Damage", true, "Whether to eat when damaged").group(baseGroup).index()
4244
override val minDamage by c.setting("Minimum Damage", 10, 0..20, 1, "The minimum damage threshold to trigger eating") { eatOnDamage }.group(baseGroup).index()
43-
override val regenerationFood by c.setting("Regeneration Food", regenerationFoodDefaults, regenerationFoodDefaults, "Items that give Regeneration") { eatOnDamage }.group(baseGroup).index()
45+
override val regenerationFood by c.setting<Item>("Regeneration Food", regenerationFoodDefaults, regenerationFoodDefaults, "Items that give Regeneration", ItemCodec) { eatOnDamage }.group(baseGroup).index()
4446
override val ignoreBadFood by c.setting("Ignore Bad Food", true, "Whether to eat when the food is bad").group(baseGroup).index()
45-
override val badFood by c.setting("Bad Food", negativeFoodDefaults, negativeFoodDefaults, "Items that are considered bad food") { ignoreBadFood }.group(baseGroup).index()
47+
override val badFood by c.setting<Item>("Bad Food", negativeFoodDefaults, negativeFoodDefaults, "Items that are considered bad food", ItemCodec) { ignoreBadFood }.group(baseGroup).index()
4648
}

src/main/kotlin/com/lambda/config/serializer/BlockSerializer.kt renamed to src/main/kotlin/com/lambda/config/serializer/BlockCodec.kt

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,16 @@
1818
package com.lambda.config.serializer
1919

2020
import com.google.gson.JsonDeserializationContext
21-
import com.google.gson.JsonDeserializer
2221
import com.google.gson.JsonElement
2322
import com.google.gson.JsonSerializationContext
24-
import com.google.gson.JsonSerializer
23+
import com.lambda.config.Codec
24+
import com.lambda.config.Stringifiable
2525
import com.mojang.serialization.JsonOps
2626
import net.minecraft.block.Block
2727
import net.minecraft.registry.Registries
2828
import java.lang.reflect.Type
2929

30-
object BlockSerializer : JsonSerializer<Block>, JsonDeserializer<Block> {
30+
object BlockCodec : Codec<Block>, Stringifiable<Block> {
3131
override fun serialize(
3232
src: Block,
3333
typeOfSrc: Type,
@@ -43,4 +43,6 @@ object BlockSerializer : JsonSerializer<Block>, JsonDeserializer<Block> {
4343
): Block =
4444
Registries.BLOCK.codec.parse(JsonOps.INSTANCE, json)
4545
.orThrow
46+
47+
override fun stringify(value: Block) = Registries.BLOCK.getId(value).path.replaceFirstChar { it.uppercase() }
4648
}

src/main/kotlin/com/lambda/config/serializer/BlockPosSerializer.kt renamed to src/main/kotlin/com/lambda/config/serializer/BlockPosCodec.kt

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,15 @@ import com.google.gson.JsonDeserializer
2222
import com.google.gson.JsonElement
2323
import com.google.gson.JsonSerializationContext
2424
import com.google.gson.JsonSerializer
25+
import com.lambda.config.Codec
26+
import com.lambda.config.Stringifiable
27+
import com.lambda.util.Formatting.format
2528
import com.mojang.serialization.JsonOps
2629
import net.minecraft.util.math.BlockPos
2730
import java.lang.reflect.Type
2831
import kotlin.jvm.optionals.getOrElse
2932

30-
object BlockPosSerializer : JsonSerializer<BlockPos>, JsonDeserializer<BlockPos> {
33+
object BlockPosCodec : Codec<BlockPos>, Stringifiable<BlockPos> {
3134
override fun serialize(
3235
src: BlockPos,
3336
typeOfSrc: Type,
@@ -44,4 +47,6 @@ object BlockPosSerializer : JsonSerializer<BlockPos>, JsonDeserializer<BlockPos>
4447
BlockPos.CODEC.parse(JsonOps.INSTANCE, json)
4548
.result()
4649
.getOrElse { BlockPos.ORIGIN }
50+
51+
override fun stringify(value: BlockPos) = value.format()
4752
}

src/main/kotlin/com/lambda/config/serializer/ColorSerializer.kt

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,36 +18,35 @@
1818
package com.lambda.config.serializer
1919

2020
import com.google.gson.JsonDeserializationContext
21-
import com.google.gson.JsonDeserializer
2221
import com.google.gson.JsonElement
23-
import com.google.gson.JsonNull
2422
import com.google.gson.JsonParseException
2523
import com.google.gson.JsonPrimitive
2624
import com.google.gson.JsonSerializationContext
27-
import com.google.gson.JsonSerializer
25+
import com.lambda.config.Codec
26+
import com.lambda.config.Stringifiable
2827
import java.awt.Color
2928
import java.lang.reflect.Type
3029

31-
object ColorSerializer : JsonSerializer<Color>, JsonDeserializer<Color> {
30+
object ColorSerializer : Codec<Color>, Stringifiable<Color> {
3231
override fun serialize(
33-
src: Color?,
34-
typeOfSrc: Type?,
32+
src: Color,
33+
typeOfSrc: Type,
3534
context: JsonSerializationContext?,
3635
): JsonElement =
37-
src?.let {
38-
JsonPrimitive("${it.red},${it.green},${it.blue},${it.alpha}")
39-
} ?: JsonNull.INSTANCE
36+
JsonPrimitive("${src.red},${src.green},${src.blue},${src.alpha}")
4037

4138
override fun deserialize(
42-
json: JsonElement?,
43-
typeOfT: Type?,
39+
json: JsonElement,
40+
typeOfT: Type,
4441
context: JsonDeserializationContext?,
4542
): Color =
46-
json?.asString?.split(",")?.let {
43+
json.asString.split(",").let {
4744
when (it.size) {
4845
3 -> Color(it[0].toInt(), it[1].toInt(), it[2].toInt())
4946
4 -> Color(it[0].toInt(), it[1].toInt(), it[2].toInt(), it[3].toInt())
5047
else -> throw JsonParseException("Invalid color format")
5148
}
52-
} ?: throw JsonParseException("Invalid color format")
49+
}
50+
51+
override fun stringify(value: Color) = "${value.red},${value.green},${value.blue},${value.alpha}"
5352
}

0 commit comments

Comments
 (0)