diff --git a/src/main/kotlin/com/lambda/Lambda.kt b/src/main/kotlin/com/lambda/Lambda.kt index 72f10c9aa..c8242977d 100644 --- a/src/main/kotlin/com/lambda/Lambda.kt +++ b/src/main/kotlin/com/lambda/Lambda.kt @@ -19,13 +19,14 @@ package com.lambda import com.google.gson.Gson import com.google.gson.GsonBuilder -import com.lambda.config.serializer.BlockPosSerializer -import com.lambda.config.serializer.BlockSerializer +import com.lambda.config.serializer.BlockPosCodec +import com.lambda.config.serializer.BlockCodec import com.lambda.config.serializer.ColorSerializer -import com.lambda.config.serializer.GameProfileSerializer -import com.lambda.config.serializer.ItemStackSerializer -import com.lambda.config.serializer.KeyCodeSerializer -import com.lambda.config.serializer.OptionalSerializer +import com.lambda.config.serializer.GameProfileCodec +import com.lambda.config.serializer.ItemCodec +import com.lambda.config.serializer.ItemStackCodec +import com.lambda.config.serializer.KeyCodeCodec +import com.lambda.config.serializer.OptionalCodec import com.lambda.core.Loader import com.lambda.event.events.ClientEvent import com.lambda.event.listener.UnsafeListener.Companion.listenOnceUnsafe @@ -37,7 +38,12 @@ import net.fabricmc.api.ClientModInitializer import net.fabricmc.loader.api.FabricLoader import net.minecraft.block.Block import net.minecraft.client.MinecraftClient +import net.minecraft.item.ArrowItem +import net.minecraft.item.BlockItem +import net.minecraft.item.Item import net.minecraft.item.ItemStack +import net.minecraft.item.PotionItem +import net.minecraft.item.RangedWeaponItem import net.minecraft.registry.DynamicRegistryManager import net.minecraft.text.Text import net.minecraft.util.math.BlockPos @@ -66,14 +72,19 @@ object Lambda : ClientModInitializer { val gson: Gson = GsonBuilder() .setPrettyPrinting() - .registerTypeAdapter(KeyCode::class.java, KeyCodeSerializer) + .registerTypeAdapter(KeyCode::class.java, KeyCodeCodec) .registerTypeAdapter(Color::class.java, ColorSerializer) - .registerTypeAdapter(BlockPos::class.java, BlockPosSerializer) - .registerTypeAdapter(Block::class.java, BlockSerializer) - .registerTypeAdapter(GameProfile::class.java, GameProfileSerializer) - .registerTypeAdapter(Optional::class.java, OptionalSerializer) - .registerTypeAdapter(ItemStack::class.java, ItemStackSerializer) + .registerTypeAdapter(BlockPos::class.java, BlockPosCodec) + .registerTypeAdapter(Block::class.java, BlockCodec) + .registerTypeAdapter(GameProfile::class.java, GameProfileCodec) + .registerTypeAdapter(Optional::class.java, OptionalCodec) + .registerTypeAdapter(ItemStack::class.java, ItemStackCodec) .registerTypeAdapter(Text::class.java, Text.Serializer(DynamicRegistryManager.EMPTY)) + .registerTypeAdapter(Item::class.java, ItemCodec) + .registerTypeAdapter(BlockItem::class.java, ItemCodec) + .registerTypeAdapter(ArrowItem::class.java, ItemCodec) + .registerTypeAdapter(PotionItem::class.java, ItemCodec) + .registerTypeAdapter(RangedWeaponItem::class.java, ItemCodec) .create() override fun onInitializeClient() {} // nop diff --git a/src/main/kotlin/com/lambda/config/Codec.kt b/src/main/kotlin/com/lambda/config/Codec.kt new file mode 100644 index 000000000..93dc918b9 --- /dev/null +++ b/src/main/kotlin/com/lambda/config/Codec.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2025 Lambda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lambda.config + +import com.google.gson.JsonDeserializer +import com.google.gson.JsonSerializer + +interface Stringifiable { fun stringify(value: T): String } + +interface Codec : JsonSerializer, JsonDeserializer \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/Configurable.kt b/src/main/kotlin/com/lambda/config/Configurable.kt index d137741a7..c0d0a41d7 100644 --- a/src/main/kotlin/com/lambda/config/Configurable.kt +++ b/src/main/kotlin/com/lambda/config/Configurable.kt @@ -24,9 +24,11 @@ import com.lambda.Lambda.LOG import com.lambda.config.settings.CharSetting import com.lambda.config.settings.FunctionSetting import com.lambda.config.settings.StringSetting -import com.lambda.config.settings.collections.ListSetting +import com.lambda.config.settings.collections.BlockCollectionSetting +import com.lambda.config.settings.collections.ClassCollectionSetting +import com.lambda.config.settings.collections.CollectionSetting +import com.lambda.config.settings.collections.ItemCollectionSetting import com.lambda.config.settings.collections.MapSetting -import com.lambda.config.settings.collections.SetSetting import com.lambda.config.settings.comparable.BooleanSetting import com.lambda.config.settings.comparable.EnumSetting import com.lambda.config.settings.complex.Bind @@ -44,6 +46,8 @@ import com.lambda.util.KeyCode import com.lambda.util.Nameable import imgui.flag.ImGuiInputTextFlags import net.minecraft.block.Block +import net.minecraft.item.Item +import net.minecraft.registry.Registries import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Vec3d import java.awt.Color @@ -124,49 +128,76 @@ abstract class Configurable( visibility: () -> Boolean = { true }, ) = StringSetting(name, defaultValue, multiline, flags, description, visibility).register() - inline fun setting( + + fun setting( name: String, - immutableList: List, - defaultValue: List, + defaultValue: Collection, description: String = "", - noinline visibility: () -> Boolean = { true }, - ) = ListSetting( + visibility: () -> Boolean = { true }, + ) = BlockCollectionSetting( name, - immutableList, + Registries.BLOCK.toList(), defaultValue.toMutableList(), - TypeToken.getParameterized(MutableList::class.java, T::class.java).type, description, visibility, ).register() - inline fun setting( + fun setting( name: String, - defaultValue: Map, + defaultValue: Collection, + description: String = "", + visibility: () -> Boolean = { true }, + ) = ItemCollectionSetting( + name, + Registries.ITEM.toList(), + defaultValue.toMutableList(), + description, + visibility, + ).register() + + inline fun > setting( + name: String, + immutableList: Collection, + defaultValue: Collection = immutableList, description: String = "", noinline visibility: () -> Boolean = { true }, - ) = MapSetting( + ) = CollectionSetting( name, - defaultValue.toMutableMap(), - TypeToken.getParameterized(MutableMap::class.java, K::class.java, V::class.java).type, + immutableList, + defaultValue.toMutableList(), + TypeToken.getParameterized(Collection::class.java, T::class.java).type, description, - visibility + visibility, ).register() inline fun setting( name: String, - immutableList: Set, - defaultValue: Set = immutableList, + immutableList: Collection, + defaultValue: Collection = immutableList, description: String = "", noinline visibility: () -> Boolean = { true }, - ) = SetSetting( + ) = ClassCollectionSetting( name, immutableList, - defaultValue.toMutableSet(), - TypeToken.getParameterized(MutableSet::class.java, T::class.java).type, + defaultValue.toMutableList(), description, visibility, ).register() + // ToDo: Actually implement maps + inline fun setting( + name: String, + defaultValue: Map, + description: String = "", + noinline visibility: () -> Boolean = { true }, + ) = MapSetting( + name, + defaultValue.toMutableMap(), + TypeToken.getParameterized(MutableMap::class.java, K::class.java, V::class.java).type, + description, + visibility + ).register() + fun setting( name: String, defaultValue: Double, diff --git a/src/main/kotlin/com/lambda/config/Configuration.kt b/src/main/kotlin/com/lambda/config/Configuration.kt index a668e4580..102924ace 100644 --- a/src/main/kotlin/com/lambda/config/Configuration.kt +++ b/src/main/kotlin/com/lambda/config/Configuration.kt @@ -135,16 +135,17 @@ abstract class Configuration : Jsonable, Loadable { LOG.info(message) info(message) } - .onFailure { - var message: String + .onFailure { primaryError -> + LOG.error(primaryError) + runCatching { load(backup) } .onSuccess { - message = "${configName.capitalize()} config loaded from backup" + val message = "${configName.capitalize()} config loaded from backup" LOG.info(message) info(message) } .onFailure { error -> - message = "Failed to load ${configName.capitalize()} config from backup, unrecoverable error" + val message = "Failed to load ${configName.capitalize()} config from backup, unrecoverable error" LOG.error(message, error) logError(message) } diff --git a/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt index cdf19707e..31c34b7c3 100644 --- a/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt +++ b/src/main/kotlin/com/lambda/config/UserAutomationConfig.kt @@ -21,7 +21,7 @@ import com.lambda.config.configurations.UserAutomationConfigs import com.lambda.module.ModuleRegistry.moduleNameMap class UserAutomationConfig(override val name: String) : AutomationConfig(name, UserAutomationConfigs) { - val linkedModules = setting("Linked Modules", moduleNameMap.filter { it.value.defaultAutomationConfig != Companion.DEFAULT }.keys, emptySet()) + val linkedModules = setting("Linked Modules", moduleNameMap.filter { it.value.defaultAutomationConfig != Companion.DEFAULT }.keys, emptySet()) .onSelect { module -> moduleNameMap[module]?.automationConfig = this@UserAutomationConfig } .onDeselect { module -> moduleNameMap[module]?.let { module -> diff --git a/src/main/kotlin/com/lambda/config/groups/ActionConfig.kt b/src/main/kotlin/com/lambda/config/groups/ActionConfig.kt index 8dff05ea6..8851ac52c 100644 --- a/src/main/kotlin/com/lambda/config/groups/ActionConfig.kt +++ b/src/main/kotlin/com/lambda/config/groups/ActionConfig.kt @@ -23,7 +23,7 @@ import com.lambda.util.NamedEnum interface ActionConfig { val sorter: SortMode - val tickStageMask: Set + val tickStageMask: Collection enum class SortMode( override val displayName: String, diff --git a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt index e02f0c792..e961fb451 100644 --- a/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/BreakSettings.kt @@ -20,6 +20,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable import com.lambda.config.SettingGroup import com.lambda.event.events.TickEvent +import com.lambda.event.events.TickEvent.Companion.ALL_STAGES import com.lambda.interaction.request.breaking.BreakConfig import com.lambda.interaction.request.breaking.BreakConfig.AnimationMode import com.lambda.interaction.request.breaking.BreakConfig.BreakConfirmationMode @@ -56,7 +57,7 @@ open class BreakSettings( override val breakDelay by c.setting("Break Delay", 0, 0..6, 1, "The delay between breaking blocks", " tick(s)").group(baseGroup, Group.General).index() // Timing - override val tickStageMask by c.setting("Break Stage Mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which break actions can be performed").group(baseGroup, Group.General).index() + override val tickStageMask by c.setting("Break Stage Mask", ALL_STAGES.toSet(), setOf(TickEvent.Input.Post), description = "The sub-tick timing at which break actions can be performed").group(baseGroup, Group.General).index() // Swap override val swapMode by c.setting("Swap Mode", BreakConfig.SwapMode.End, "Decides when to swap to the best suited tool when breaking a block").group(baseGroup, Group.General).index() diff --git a/src/main/kotlin/com/lambda/config/groups/EatConfig.kt b/src/main/kotlin/com/lambda/config/groups/EatConfig.kt index 446f0102e..3169a47a4 100644 --- a/src/main/kotlin/com/lambda/config/groups/EatConfig.kt +++ b/src/main/kotlin/com/lambda/config/groups/EatConfig.kt @@ -32,19 +32,19 @@ import net.minecraft.item.ItemStack interface EatConfig : ISettingGroup { val eatOnHunger: Boolean val minFoodLevel: Int - val nutritiousFood: List + val nutritiousFood: Collection val saturated: Saturation val eatOnFire: Boolean - val resistanceFood: List + val resistanceFood: Collection val eatOnDamage: Boolean val minDamage: Int - val regenerationFood: List + val regenerationFood: Collection val selectionPriority: SelectionPriority val ignoreBadFood: Boolean - val badFood: List + val badFood: Collection enum class Saturation( override val displayName: String, diff --git a/src/main/kotlin/com/lambda/config/groups/EatSettings.kt b/src/main/kotlin/com/lambda/config/groups/EatSettings.kt index a59ac07c4..3f21ea757 100644 --- a/src/main/kotlin/com/lambda/config/groups/EatSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/EatSettings.kt @@ -20,6 +20,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable import com.lambda.config.SettingGroup import com.lambda.util.NamedEnum +import net.minecraft.item.Item import net.minecraft.item.Items class EatSettings( @@ -34,13 +35,13 @@ class EatSettings( override val eatOnHunger by c.setting("Eat On Hunger", true, "Whether to eat when hungry").group(baseGroup).index() 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() override val saturated by c.setting("Saturated", EatConfig.Saturation.EatSmart, "When to stop eating") { eatOnHunger }.group(baseGroup).index() - override val nutritiousFood by c.setting("Nutritious Food", nutritiousFoodDefaults, nutritiousFoodDefaults, "Items that are be considered nutritious") { eatOnHunger }.group(baseGroup).index() + override val nutritiousFood by c.setting("Nutritious Food", nutritiousFoodDefaults, description = "Items that are be considered nutritious") { eatOnHunger }.group(baseGroup).index() override val selectionPriority by c.setting("Selection Priority", EatConfig.SelectionPriority.MostNutritious, "The priority for selecting food items") { eatOnHunger }.group(baseGroup).index() override val eatOnFire by c.setting("Eat On Fire", true, "Whether to eat when on fire").group(baseGroup).index() - override val resistanceFood by c.setting("Resistance Food", resistanceFoodDefaults, resistanceFoodDefaults, "Items that give Fire Resistance") { eatOnFire }.group(baseGroup).index() + override val resistanceFood by c.setting("Resistance Food", resistanceFoodDefaults, description = "Items that give Fire Resistance") { eatOnFire }.group(baseGroup).index() override val eatOnDamage by c.setting("Eat On Damage", true, "Whether to eat when damaged").group(baseGroup).index() override val minDamage by c.setting("Minimum Damage", 10, 0..20, 1, "The minimum damage threshold to trigger eating") { eatOnDamage }.group(baseGroup).index() - override val regenerationFood by c.setting("Regeneration Food", regenerationFoodDefaults, regenerationFoodDefaults, "Items that give Regeneration") { eatOnDamage }.group(baseGroup).index() + override val regenerationFood by c.setting("Regeneration Food", regenerationFoodDefaults, description = "Items that give Regeneration") { eatOnDamage }.group(baseGroup).index() override val ignoreBadFood by c.setting("Ignore Bad Food", true, "Whether to eat when the food is bad").group(baseGroup).index() - override val badFood by c.setting("Bad Food", negativeFoodDefaults, negativeFoodDefaults, "Items that are considered bad food") { ignoreBadFood }.group(baseGroup).index() + override val badFood by c.setting("Bad Food", negativeFoodDefaults, description = "Items that are considered bad food") { ignoreBadFood }.group(baseGroup).index() } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt b/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt index be0a39c87..af916a068 100644 --- a/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/HotbarSettings.kt @@ -20,6 +20,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable import com.lambda.config.SettingGroup import com.lambda.event.events.TickEvent +import com.lambda.event.events.TickEvent.Companion.ALL_STAGES import com.lambda.interaction.request.hotbar.HotbarConfig import com.lambda.util.NamedEnum @@ -31,5 +32,5 @@ class HotbarSettings( override val swapDelay by c.setting("Swap Delay", 0, 0..3, 1, "The number of ticks delay before allowing another hotbar selection swap", " ticks").group(baseGroup).index() override val swapsPerTick by c.setting("Swaps Per Tick", 3, 1..10, 1, "The number of hotbar selection swaps that can take place each tick") { swapDelay <= 0 }.group(baseGroup).index() override val swapPause by c.setting("Swap Pause", 0, 0..20, 1, "The delay in ticks to pause actions after switching to the slot", " ticks").group(baseGroup).index() - override val tickStageMask by c.setting("Hotbar Stage Mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which hotbar actions are performed").group(baseGroup).index() + override val tickStageMask by c.setting("Hotbar Stage Mask", ALL_STAGES.toSet(), setOf(TickEvent.Input.Post), description = "The sub-tick timing at which hotbar actions are performed").group(baseGroup).index() } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt b/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt index f85214b2c..b1e599339 100644 --- a/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/InteractSettings.kt @@ -20,6 +20,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable import com.lambda.config.SettingGroup import com.lambda.event.events.TickEvent +import com.lambda.event.events.TickEvent.Companion.ALL_STAGES import com.lambda.interaction.request.interacting.InteractConfig import com.lambda.util.NamedEnum @@ -30,7 +31,7 @@ class InteractSettings( override val rotate by c.setting("Rotate For Interact", true, "Rotates the player to look at the block when interacting").group(baseGroup).index() override val sorter by c.setting("Interact Sorter", ActionConfig.SortMode.Tool, "The order in which interactions are performed").group(baseGroup).index() override val swingHand by c.setting("Swing On Interact", true, "Swings the players hand after interacting").group(baseGroup).index() - override val tickStageMask by c.setting("Interact Stage Mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which interact actions are performed").group(baseGroup).index() + override val tickStageMask by c.setting("Interact Stage Mask", ALL_STAGES.toSet(), setOf(TickEvent.Input.Post), description = "The sub-tick timing at which interact actions are performed").group(baseGroup).index() override val interactSwingType by c.setting("Interact Swing Type", BuildConfig.SwingType.Vanilla, "The style of swing") { swingHand }.group(baseGroup).index() override val interactConfirmationMode by c.setting("Interact Confirmation Mode", InteractConfig.InteractConfirmationMode.InteractThenAwait, "The style of confirmation for interactions").group(baseGroup).index() } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt b/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt index 2b6f30753..8c025002e 100644 --- a/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/InventorySettings.kt @@ -19,7 +19,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable import com.lambda.config.SettingGroup -import com.lambda.event.events.TickEvent +import com.lambda.event.events.TickEvent.Companion.ALL_STAGES import com.lambda.interaction.request.inventory.InventoryConfig import com.lambda.util.NamedEnum import com.lambda.util.item.ItemUtils @@ -35,8 +35,8 @@ class InventorySettings( } override val actionsPerSecond by c.setting("Actions Per Second", 100, 0..100, 1, "How many inventory actions can be performed per tick").group(baseGroup, Group.General).index() - override val tickStageMask by c.setting("Inventory Stage Mask", setOf(TickEvent.Pre, TickEvent.Input.Pre, TickEvent.Input.Post, TickEvent.Player.Post), description = "The sub-tick timing at which inventory actions are performed").group(baseGroup, Group.General).index() - override val disposables by c.setting("Disposables", ItemUtils.defaultDisposables, ItemUtils.defaultDisposables, "Items that will be ignored when checking for a free slot").group(baseGroup, Group.Container).index() + override val tickStageMask by c.setting("Inventory Stage Mask", ALL_STAGES.toSet(), description = "The sub-tick timing at which inventory actions are performed").group(baseGroup, Group.General).index() + override val disposables by c.setting("Disposables", ItemUtils.defaultDisposables, description = "Items that will be ignored when checking for a free slot").group(baseGroup, Group.Container).index() override val swapWithDisposables by c.setting("Swap With Disposables", true, "Swap items with disposable ones").group(baseGroup, Group.Container).index() override val providerPriority by c.setting("Provider Priority", InventoryConfig.Priority.WithMinItems, "What container to prefer when retrieving the item from").group(baseGroup, Group.Container).index() override val storePriority by c.setting("Store Priority", InventoryConfig.Priority.WithMinItems, "What container to prefer when storing the item to").group(baseGroup, Group.Container).index() diff --git a/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt b/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt index 35e1f295d..1b138096a 100644 --- a/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/PlaceSettings.kt @@ -20,6 +20,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable import com.lambda.config.SettingGroup import com.lambda.event.events.TickEvent +import com.lambda.event.events.TickEvent.Companion.ALL_STAGES import com.lambda.interaction.request.placing.PlaceConfig import com.lambda.interaction.request.placing.PlaceConfig.AirPlaceMode import com.lambda.interaction.request.placing.PlaceConfig.PlaceConfirmationMode @@ -33,7 +34,7 @@ class PlaceSettings( override val airPlace by c.setting("Air Place", AirPlaceMode.None, "Allows for placing blocks without adjacent faces").group(baseGroup).index() override val axisRotateSetting by c.setting("Axis Rotate", true, "Overrides the Rotate For Place setting and rotates the player on each axis to air place rotational blocks") { airPlace.isEnabled }.group(baseGroup).index() override val sorter by c.setting("Place Sorter", ActionConfig.SortMode.Tool, "The order in which placements are performed").group(baseGroup).index() - override val tickStageMask by c.setting("Place Stage mask", setOf(TickEvent.Input.Post), description = "The sub-tick timing at which place actions are performed").group(baseGroup).index() + override val tickStageMask by c.setting("Place Stage Mask", ALL_STAGES.toSet(), setOf(TickEvent.Input.Post), description = "The sub-tick timing at which place actions are performed").group(baseGroup).index() override val placeConfirmationMode by c.setting("Place Confirmation", PlaceConfirmationMode.PlaceThenAwait, "Wait for block placement confirmation").group(baseGroup).index() override val maxPendingPlacements by c.setting("Max Pending Placements", 5, 0..30, 1, "The maximum amount of pending placements").group(baseGroup).index() override val placementsPerTick by c.setting("Places Per Tick", 1, 1..30, 1, "Maximum instant block places per tick").group(baseGroup).index() diff --git a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt index 09048839d..c378eab6a 100644 --- a/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt +++ b/src/main/kotlin/com/lambda/config/groups/RotationSettings.kt @@ -19,6 +19,7 @@ package com.lambda.config.groups import com.lambda.config.Configurable import com.lambda.config.SettingGroup +import com.lambda.event.events.TickEvent import com.lambda.event.events.TickEvent.Companion.ALL_STAGES import com.lambda.interaction.request.rotating.RotationConfig import com.lambda.interaction.request.rotating.RotationMode @@ -42,7 +43,7 @@ class RotationSettings( /** How many ticks to wait before resetting the rotation */ override val decayTicks by c.setting("Reset Rotation", 1, 1..10, 1, "Ticks before rotation is reset", " ticks") { rotate }.group(baseGroup).index() - override val tickStageMask = ALL_STAGES.toSet() + override val tickStageMask = ALL_STAGES.subList(0, ALL_STAGES.indexOf(TickEvent.Player.Post)).toSet() /** Whether the rotation is instant */ var instant by c.setting("Instant Rotation", true, "Instantly rotate") { rotate }.group(baseGroup).index() diff --git a/src/main/kotlin/com/lambda/config/serializer/BlockSerializer.kt b/src/main/kotlin/com/lambda/config/serializer/BlockCodec.kt similarity index 85% rename from src/main/kotlin/com/lambda/config/serializer/BlockSerializer.kt rename to src/main/kotlin/com/lambda/config/serializer/BlockCodec.kt index c9b56dddf..caafe6235 100644 --- a/src/main/kotlin/com/lambda/config/serializer/BlockSerializer.kt +++ b/src/main/kotlin/com/lambda/config/serializer/BlockCodec.kt @@ -18,16 +18,16 @@ package com.lambda.config.serializer import com.google.gson.JsonDeserializationContext -import com.google.gson.JsonDeserializer import com.google.gson.JsonElement import com.google.gson.JsonSerializationContext -import com.google.gson.JsonSerializer +import com.lambda.config.Codec +import com.lambda.config.Stringifiable import com.mojang.serialization.JsonOps import net.minecraft.block.Block import net.minecraft.registry.Registries import java.lang.reflect.Type -object BlockSerializer : JsonSerializer, JsonDeserializer { +object BlockCodec : Codec, Stringifiable { override fun serialize( src: Block, typeOfSrc: Type, @@ -43,4 +43,6 @@ object BlockSerializer : JsonSerializer, JsonDeserializer { ): Block = Registries.BLOCK.codec.parse(JsonOps.INSTANCE, json) .orThrow + + override fun stringify(value: Block) = Registries.BLOCK.getId(value).path.replaceFirstChar { it.uppercase() } } diff --git a/src/main/kotlin/com/lambda/config/serializer/BlockPosSerializer.kt b/src/main/kotlin/com/lambda/config/serializer/BlockPosCodec.kt similarity index 86% rename from src/main/kotlin/com/lambda/config/serializer/BlockPosSerializer.kt rename to src/main/kotlin/com/lambda/config/serializer/BlockPosCodec.kt index f7ea8a38f..3e099aaca 100644 --- a/src/main/kotlin/com/lambda/config/serializer/BlockPosSerializer.kt +++ b/src/main/kotlin/com/lambda/config/serializer/BlockPosCodec.kt @@ -22,12 +22,15 @@ import com.google.gson.JsonDeserializer import com.google.gson.JsonElement import com.google.gson.JsonSerializationContext import com.google.gson.JsonSerializer +import com.lambda.config.Codec +import com.lambda.config.Stringifiable +import com.lambda.util.Formatting.format import com.mojang.serialization.JsonOps import net.minecraft.util.math.BlockPos import java.lang.reflect.Type import kotlin.jvm.optionals.getOrElse -object BlockPosSerializer : JsonSerializer, JsonDeserializer { +object BlockPosCodec : Codec, Stringifiable { override fun serialize( src: BlockPos, typeOfSrc: Type, @@ -44,4 +47,6 @@ object BlockPosSerializer : JsonSerializer, JsonDeserializer BlockPos.CODEC.parse(JsonOps.INSTANCE, json) .result() .getOrElse { BlockPos.ORIGIN } + + override fun stringify(value: BlockPos) = value.format() } diff --git a/src/main/kotlin/com/lambda/config/serializer/ColorSerializer.kt b/src/main/kotlin/com/lambda/config/serializer/ColorSerializer.kt index 49f04d576..64d403f75 100644 --- a/src/main/kotlin/com/lambda/config/serializer/ColorSerializer.kt +++ b/src/main/kotlin/com/lambda/config/serializer/ColorSerializer.kt @@ -18,36 +18,35 @@ package com.lambda.config.serializer import com.google.gson.JsonDeserializationContext -import com.google.gson.JsonDeserializer import com.google.gson.JsonElement -import com.google.gson.JsonNull import com.google.gson.JsonParseException import com.google.gson.JsonPrimitive import com.google.gson.JsonSerializationContext -import com.google.gson.JsonSerializer +import com.lambda.config.Codec +import com.lambda.config.Stringifiable import java.awt.Color import java.lang.reflect.Type -object ColorSerializer : JsonSerializer, JsonDeserializer { +object ColorSerializer : Codec, Stringifiable { override fun serialize( - src: Color?, - typeOfSrc: Type?, + src: Color, + typeOfSrc: Type, context: JsonSerializationContext?, ): JsonElement = - src?.let { - JsonPrimitive("${it.red},${it.green},${it.blue},${it.alpha}") - } ?: JsonNull.INSTANCE + JsonPrimitive("${src.red},${src.green},${src.blue},${src.alpha}") override fun deserialize( - json: JsonElement?, - typeOfT: Type?, + json: JsonElement, + typeOfT: Type, context: JsonDeserializationContext?, ): Color = - json?.asString?.split(",")?.let { + json.asString.split(",").let { when (it.size) { 3 -> Color(it[0].toInt(), it[1].toInt(), it[2].toInt()) 4 -> Color(it[0].toInt(), it[1].toInt(), it[2].toInt(), it[3].toInt()) else -> throw JsonParseException("Invalid color format") } - } ?: throw JsonParseException("Invalid color format") + } + + override fun stringify(value: Color) = "${value.red},${value.green},${value.blue},${value.alpha}" } diff --git a/src/main/kotlin/com/lambda/config/serializer/GameProfileSerializer.kt b/src/main/kotlin/com/lambda/config/serializer/GameProfileCodec.kt similarity index 76% rename from src/main/kotlin/com/lambda/config/serializer/GameProfileSerializer.kt rename to src/main/kotlin/com/lambda/config/serializer/GameProfileCodec.kt index d832e39d1..77fd12889 100644 --- a/src/main/kotlin/com/lambda/config/serializer/GameProfileSerializer.kt +++ b/src/main/kotlin/com/lambda/config/serializer/GameProfileCodec.kt @@ -24,6 +24,8 @@ import com.google.gson.JsonNull import com.google.gson.JsonObject import com.google.gson.JsonSerializationContext import com.google.gson.JsonSerializer +import com.lambda.config.Codec +import com.lambda.config.Stringifiable import com.mojang.authlib.GameProfile import java.lang.reflect.Type import java.util.* @@ -32,26 +34,24 @@ import java.util.* // But who cares, I'm doing it again. // What you gon' do bout it, huh? // That's what I thought. -object GameProfileSerializer : JsonSerializer, JsonDeserializer { +object GameProfileCodec : Codec, Stringifiable { override fun serialize( - src: GameProfile?, + src: GameProfile, typeOfSrc: Type?, context: JsonSerializationContext?, ): JsonElement = - src?.let { - JsonObject().apply { - addProperty("name", it.name) - addProperty("id", it.id.toString()) - } - } ?: JsonNull.INSTANCE + JsonObject().apply { + addProperty("name", src.name) + addProperty("id", src.id.toString()) + } override fun deserialize( - json: JsonElement?, + json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?, ): GameProfile { - val name = json?.asJsonObject?.get("name")?.asString ?: "nil" - val id = json?.asJsonObject?.get("id")?.asString ?: "00000000-0000-0000-0000-000000000000" + val name = json.asJsonObject.get("name")?.asString ?: "nil" + val id = json.asJsonObject.get("id")?.asString ?: "00000000-0000-0000-0000-000000000000" val parsedId = if (id.length == 32) id.replaceFirst( "(\\w{8})(\\w{4})(\\w{4})(\\w{4})(\\w{12})".toRegex(), @@ -61,4 +61,6 @@ object GameProfileSerializer : JsonSerializer, JsonDeserializer. + */ + +package com.lambda.config.serializer + +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonElement +import com.google.gson.JsonPrimitive +import com.google.gson.JsonSerializationContext +import com.lambda.config.Codec +import com.lambda.config.Stringifiable +import net.minecraft.item.Item +import net.minecraft.registry.Registries +import net.minecraft.util.Identifier +import java.lang.reflect.Type + +object ItemCodec : Codec, Stringifiable { + override fun serialize( + item: Item, + typeOfSrc: Type, + context: JsonSerializationContext + ): JsonElement = JsonPrimitive(item.toString()) + + override fun deserialize( + json: JsonElement, + typeOfT: Type, + context: JsonDeserializationContext + ): Item = + Registries.ITEM.get(Identifier.of(json.asString)) // Watch out!! Errors are silently catched by gson!! + + override fun stringify(value: Item) = value.name.string.replaceFirstChar { it.uppercase() } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/serializer/ItemStackSerializer.kt b/src/main/kotlin/com/lambda/config/serializer/ItemStackCodec.kt similarity index 87% rename from src/main/kotlin/com/lambda/config/serializer/ItemStackSerializer.kt rename to src/main/kotlin/com/lambda/config/serializer/ItemStackCodec.kt index 4b7e9e82e..76c3c5624 100644 --- a/src/main/kotlin/com/lambda/config/serializer/ItemStackSerializer.kt +++ b/src/main/kotlin/com/lambda/config/serializer/ItemStackCodec.kt @@ -18,16 +18,16 @@ package com.lambda.config.serializer import com.google.gson.JsonDeserializationContext -import com.google.gson.JsonDeserializer import com.google.gson.JsonElement import com.google.gson.JsonSerializationContext -import com.google.gson.JsonSerializer +import com.lambda.config.Codec +import com.lambda.config.Stringifiable import com.mojang.serialization.JsonOps import net.minecraft.item.ItemStack import java.lang.reflect.Type import kotlin.jvm.optionals.getOrElse -object ItemStackSerializer : JsonSerializer, JsonDeserializer { +object ItemStackCodec : Codec, Stringifiable { override fun serialize( stack: ItemStack, typeOfSrc: Type, @@ -44,4 +44,6 @@ object ItemStackSerializer : JsonSerializer, JsonDeserializer, JsonDeserializer { +object KeyCodeCodec : Codec { override fun serialize( src: KeyCode?, typeOfSrc: Type?, diff --git a/src/main/kotlin/com/lambda/config/serializer/OptionalSerializer.kt b/src/main/kotlin/com/lambda/config/serializer/OptionalCodec.kt similarity index 94% rename from src/main/kotlin/com/lambda/config/serializer/OptionalSerializer.kt rename to src/main/kotlin/com/lambda/config/serializer/OptionalCodec.kt index da3089a1f..413446f89 100644 --- a/src/main/kotlin/com/lambda/config/serializer/OptionalSerializer.kt +++ b/src/main/kotlin/com/lambda/config/serializer/OptionalCodec.kt @@ -23,10 +23,11 @@ import com.google.gson.JsonElement import com.google.gson.JsonNull import com.google.gson.JsonSerializationContext import com.google.gson.JsonSerializer +import com.lambda.config.Codec import java.lang.reflect.Type import java.util.* -object OptionalSerializer : JsonSerializer>, JsonDeserializer> { +object OptionalCodec : Codec> { override fun serialize(src: Optional?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement = src?.map { context?.serialize(it) }?.orElse(JsonNull.INSTANCE) ?: JsonNull.INSTANCE diff --git a/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt new file mode 100644 index 000000000..6ca899fe6 --- /dev/null +++ b/src/main/kotlin/com/lambda/config/settings/collections/BlockCollectionSetting.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2025 Lambda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lambda.config.settings.collections + +import com.google.gson.JsonElement +import com.google.gson.reflect.TypeToken +import com.lambda.Lambda.gson +import com.lambda.config.serializer.BlockCodec +import com.lambda.gui.dsl.ImGuiBuilder +import imgui.flag.ImGuiSelectableFlags.DontClosePopups +import net.minecraft.block.Block + +class BlockCollectionSetting( + override var name: String, + private val immutableCollection: Collection, + defaultValue: MutableCollection, + description: String, + visibility: () -> Boolean, +) : CollectionSetting( + name, + immutableCollection, + defaultValue, + TypeToken.getParameterized(Collection::class.java, Block::class.java).type, + description, + visibility, +) { + override fun ImGuiBuilder.buildLayout() { + val text = if (value.size == 1) "block" else "blocks" + + combo("##$name", "$name: ${value.size} $text") { + value.toMutableList() // Copy the list instead of iterating the immutable one + .forEach { + selectable( + label = BlockCodec.stringify(it), + selected = true, + flags = DontClosePopups + ) { value.remove(it) } + } + } + + button("Add") { openPopup("Blocks") } + + popup("Blocks") { + filter("Search for blocks") { filter -> + immutableCollection + .filter { + //filter.inputBuffer.levenshteinDistance(ItemCodec.stringify(it)) < 3 && + !value.contains(it) + } + .forEach { + text(BlockCodec.stringify(it)) + sameLine() + button("Add") { value.add(it) } + } + } + } + } + + override fun toJson(): JsonElement = gson.toJsonTree(value, type) + + override fun loadFromJson(serialized: JsonElement) { + value = gson.fromJson>(serialized, type) + .toMutableList() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt new file mode 100644 index 000000000..1bd531008 --- /dev/null +++ b/src/main/kotlin/com/lambda/config/settings/collections/ClassCollectionSetting.kt @@ -0,0 +1,78 @@ +/* + * Copyright 2025 Lambda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lambda.config.settings.collections + +import com.google.gson.JsonElement +import com.google.gson.reflect.TypeToken +import com.lambda.Lambda.gson +import com.lambda.gui.dsl.ImGuiBuilder +import imgui.flag.ImGuiSelectableFlags.DontClosePopups + +/** + * @see [com.lambda.config.settings.collections.CollectionSettings] + * @see [com.lambda.config.Configurable] + */ +class ClassCollectionSetting( + override var name: String, + private val immutableCollection: Collection, + defaultValue: MutableCollection, + description: String, + visibility: () -> Boolean, +) : CollectionSetting( + name, + immutableCollection, + defaultValue, + TypeToken.getParameterized(Collection::class.java, Any::class.java).type, + description, + visibility, +) { + override fun ImGuiBuilder.buildLayout() { + combo("##$name", "$name: ${value.size} item(s)") { + immutableCollection + .forEach { + val isSelected = value.contains(it) + + selectable( + label = it.className, + selected = isSelected, + flags = DontClosePopups, + ) { + if (isSelected) value.remove(it) + else value.add(it) + } + } + } + } + + val Any.className: String get() = this::class.java.name + .substringAfter("${this::class.java.packageName}.") + .replace('$', '.') + + // When serializing the list to json we do not want to serialize the elements' classes, but their stringified representation. + // If we do serialize the classes we'll run into missing type adapters errors by Gson. + // This is intended behaviour. If you wish your collection settings to display something else then you must extend this class. + override fun toJson(): JsonElement = gson.toJsonTree(value.map { it.className }) + + override fun loadFromJson(serialized: JsonElement) { + val strList = gson.fromJson>(serialized, type) + .mapNotNull { str -> immutableCollection.find { it.className == str } } + .toMutableList() + + value = strList + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt similarity index 62% rename from src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt rename to src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt index fec22d410..6f0aaa533 100644 --- a/src/main/kotlin/com/lambda/config/settings/collections/ListSetting.kt +++ b/src/main/kotlin/com/lambda/config/settings/collections/CollectionSetting.kt @@ -25,81 +25,81 @@ import com.lambda.config.SettingEditorDsl import com.lambda.config.SettingGroupEditor import com.lambda.context.SafeContext import com.lambda.gui.dsl.ImGuiBuilder -import com.lambda.threading.runSafe import imgui.flag.ImGuiSelectableFlags.DontClosePopups import java.lang.reflect.Type /** + * This generic collection settings handles all [Comparable] values (i.e not classes) and serialize + * their values by calling [Any.toString] and loads them by comparing what's in the [immutableCollection]. + * This behaviour is by design. If you wish to store collections of non-comparable values you must use [ClassCollectionSetting]. + * + * If you wish to use a different codec or simply display values differently you must create your own + * collection setting. + * * @see [com.lambda.config.Configurable] */ -class ListSetting( +open class CollectionSetting( override var name: String, - private var immutableList: List, - defaultValue: MutableList, + private var immutableCollection: Collection, + defaultValue: MutableCollection, type: Type, description: String, visibility: () -> Boolean, -) : AbstractSetting>( +) : AbstractSetting>( name, defaultValue, type, description, visibility ) { + private val strListType = + TypeToken.getParameterized(Collection::class.java, String::class.java).type + private val selectListeners = mutableListOf Unit>() private val deselectListeners = mutableListOf Unit>() - private val strListType = - TypeToken.getParameterized(MutableList::class.java, String::class.java).type + + fun onSelect(block: SafeContext.(T) -> Unit) = apply { + selectListeners.add(block) + } + + fun onDeselect(block: SafeContext.(T) -> Unit) = apply { + deselectListeners.add(block) + } override fun ImGuiBuilder.buildLayout() { combo("##$name", "$name: ${value.size} item(s)") { - immutableList + immutableCollection .forEach { val isSelected = value.contains(it) selectable( - it.toString(), isSelected, - flags = DontClosePopups + label = it.toString(), + selected = isSelected, + flags = DontClosePopups, ) { - if (isSelected) { - value.remove(it) - runSafe { deselectListeners.forEach { listener -> listener(it) } } - } else { - value.add(it) - runSafe { selectListeners.forEach { listener -> listener(it) } } - } + if (isSelected) value.remove(it) + else value.add(it) } } } } - // When serializing the list to json we do not want to serialize the elements' classes, but - // their stringified representation. - // If we do serialize the classes we'll run into missing type adapters errors by Gson. override fun toJson(): JsonElement = gson.toJsonTree(value.map { it.toString() }) override fun loadFromJson(serialized: JsonElement) { - val strList = gson.fromJson>(serialized, strListType) - .mapNotNull { str -> immutableList.find { it.toString() == str } } + val strList = gson.fromJson>(serialized, strListType) + .mapNotNull { str -> immutableCollection.find { it.toString() == str } } .toMutableList() value = strList } - fun onSelect(block: SafeContext.(T) -> Unit) = apply { - selectListeners.add(block) - } - - fun onDeselect(block: SafeContext.(T) -> Unit) = apply { - deselectListeners.add(block) - } - companion object { @SettingEditorDsl @Suppress("unchecked_cast") - fun SettingGroupEditor.TypedEditBuilder>.immutableList(immutableList: List) { - (settings as Collection>).forEach { it.immutableList = immutableList } + fun SettingGroupEditor.TypedEditBuilder>.immutableCollection(collection: Collection) { + (settings as Collection>).forEach { it.immutableCollection = collection } } } } diff --git a/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt new file mode 100644 index 000000000..daf88804b --- /dev/null +++ b/src/main/kotlin/com/lambda/config/settings/collections/ItemCollectionSetting.kt @@ -0,0 +1,80 @@ +/* + * Copyright 2025 Lambda + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.lambda.config.settings.collections + +import com.google.gson.JsonElement +import com.google.gson.reflect.TypeToken +import com.lambda.Lambda.gson +import com.lambda.config.serializer.ItemCodec +import com.lambda.gui.dsl.ImGuiBuilder +import imgui.flag.ImGuiSelectableFlags.DontClosePopups +import net.minecraft.item.Item + +class ItemCollectionSetting( + override var name: String, + private val immutableCollection: Collection, + defaultValue: MutableCollection, + description: String, + visibility: () -> Boolean, +) : CollectionSetting( + name, + immutableCollection, + defaultValue, + TypeToken.getParameterized(Collection::class.java, Item::class.java).type, + description, + visibility, +) { + override fun ImGuiBuilder.buildLayout() { + val text = if (value.size == 1) "item" else "items" + + combo("##$name", "$name: ${value.size} $text") { + value.toMutableList() // Copy the list instead of iterating the immutable one + .forEach { + selectable( + label = ItemCodec.stringify(it), + selected = true, + flags = DontClosePopups + ) { value.remove(it) } + } + } + + button("Add") { openPopup("Items") } + + popup("Items") { + filter("Search for items") { filter -> + immutableCollection + .filter { + //filter.inputBuffer.levenshteinDistance(ItemCodec.stringify(it)) < 3 && + !value.contains(it) + } + .forEach { + text(ItemCodec.stringify(it)) + sameLine() + button("Add") { value.add(it) } + } + } + } + } + + override fun toJson(): JsonElement = gson.toJsonTree(value, type) + + override fun loadFromJson(serialized: JsonElement) { + value = gson.fromJson>(serialized, type) + .toMutableList() + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt b/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt deleted file mode 100644 index 65ae4eba9..000000000 --- a/src/main/kotlin/com/lambda/config/settings/collections/SetSetting.kt +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2025 Lambda - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lambda.config.settings.collections - -import com.google.gson.JsonElement -import com.google.gson.reflect.TypeToken -import com.lambda.Lambda.gson -import com.lambda.config.AbstractSetting -import com.lambda.config.SettingEditorDsl -import com.lambda.config.SettingGroupEditor -import com.lambda.context.SafeContext -import com.lambda.gui.dsl.ImGuiBuilder -import com.lambda.threading.runSafe -import imgui.flag.ImGuiSelectableFlags.DontClosePopups -import java.lang.reflect.Type - -/** - * @see [com.lambda.config.Configurable] - */ -class SetSetting( - override var name: String, - private var immutableSet: Set, - defaultValue: MutableSet, - type: Type, - description: String, - visibility: () -> Boolean, -) : AbstractSetting>( - name, - defaultValue, - type, - description, - visibility -) { - private val selectListeners = mutableListOf Unit>() - private val deselectListeners = mutableListOf Unit>() - private val strSetType = - TypeToken.getParameterized(Set::class.java, String::class.java).type - - override fun ImGuiBuilder.buildLayout() { - combo("##$name", "$name: ${value.size} item(s)") { - immutableSet - .forEach { - val isSelected = value.contains(it) - - selectable( - it.toString(), isSelected, - flags = DontClosePopups - ) { - if (isSelected) { - value.remove(it) - runSafe { deselectListeners.forEach { listener -> listener(it) } } - } else { - value.add(it) - runSafe { selectListeners.forEach { listener -> listener(it) } } - } - } - } - } - } - - // When serializing the list to json we do not want to serialize the elements' classes, but - // their stringified representation. - // If we do serialize the classes we'll run into missing type adapters errors by Gson. - override fun toJson(): JsonElement = - gson.toJsonTree(value.map { it.toString() }) - - override fun loadFromJson(serialized: JsonElement) { - val strSet = gson.fromJson>(serialized, strSetType) - .mapNotNull { str -> immutableSet.find { it.toString() == str } } - .toMutableSet() - - value = strSet - } - - fun onSelect(block: SafeContext.(T) -> Unit) = apply { - selectListeners.add(block) - } - - fun onDeselect(block: SafeContext.(T) -> Unit) = apply { - deselectListeners.add(block) - } - - companion object { - @SettingEditorDsl - @Suppress("unchecked_cast") - fun SettingGroupEditor.TypedEditBuilder>.immutableSet(immutableSet: Set) { - (settings as Collection>).forEach { it.immutableSet = immutableSet } - } - } -} diff --git a/src/main/kotlin/com/lambda/friend/FriendManager.kt b/src/main/kotlin/com/lambda/friend/FriendManager.kt index 5c13e6010..38c9c9f03 100644 --- a/src/main/kotlin/com/lambda/friend/FriendManager.kt +++ b/src/main/kotlin/com/lambda/friend/FriendManager.kt @@ -19,6 +19,7 @@ package com.lambda.friend import com.lambda.config.Configurable import com.lambda.config.configurations.FriendConfig +import com.lambda.config.serializer.GameProfileCodec import com.lambda.core.Loadable import com.lambda.util.text.ClickEvents import com.lambda.util.text.buildText @@ -41,7 +42,7 @@ import java.util.* // - Improve save file structure. object FriendManager : Configurable(FriendConfig), Loadable { override val name = "friends" - val friends by setting("friends", emptySet(), setOf()) + val friends by setting("friends", emptySet()) fun befriend(profile: GameProfile) = friends.add(profile) fun unfriend(profile: GameProfile): Boolean = friends.remove(profile) diff --git a/src/main/kotlin/com/lambda/gui/dsl/ImGuiBuilder.kt b/src/main/kotlin/com/lambda/gui/dsl/ImGuiBuilder.kt index 2b987c981..ae3049c34 100644 --- a/src/main/kotlin/com/lambda/gui/dsl/ImGuiBuilder.kt +++ b/src/main/kotlin/com/lambda/gui/dsl/ImGuiBuilder.kt @@ -1583,15 +1583,19 @@ object ImGuiBuilder { lambdaTooltip(description()) } + @ImGuiDsl + fun openPopup(strId: String, flags: Int = ImGuiPopupFlags.None) = + ImGui.openPopup(strId, flags) + /** - * Creates a popup. + * Creates a popup. You must first call [openPopup] with the same [strId] * * @param strId Unique identifier * @param flags Popup flags * @param block Content of the popup */ @ImGuiDsl - inline fun popup(strId: String, flags: Int = ImGuiPopupFlags.None, block: ProcedureBlock) { + inline fun popup(strId: String, flags: Int = ImGuiPopupFlags.AnyPopup, block: ProcedureBlock) { if (beginPopup(strId, flags)) { block() endPopup() diff --git a/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt b/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt index 16275ef85..e1a892335 100644 --- a/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt +++ b/src/main/kotlin/com/lambda/interaction/BaritoneManager.kt @@ -26,6 +26,8 @@ import com.lambda.config.configurations.LambdaConfig import com.lambda.config.groups.RotationSettings import com.lambda.context.Automated import com.lambda.config.AutomationConfig +import com.lambda.config.serializer.BlockCodec +import com.lambda.config.serializer.ItemCodec import com.lambda.util.BlockUtils.blockPos import com.lambda.util.NamedEnum @@ -171,7 +173,7 @@ object BaritoneManager : Configurable(LambdaConfig), Automated by AutomationConf setting("Sprint In Water", sprintInWater.value).group(Group.Behavior, SubGroup.Movement).onValueChange { _, it -> sprintInWater.value = it } setting("Allow Break", allowBreak.value).group(Group.Behavior, SubGroup.Interaction).onValueChange { _, it -> allowBreak.value = it } - setting("Allow Break Anyway", allowBreakAnyway.value.toSet()).group(Group.Behavior, SubGroup.Interaction).onValueChange { _, it -> allowBreakAnyway.value = it.toList() } + setting("Allow Break Anyway", allowBreakAnyway.value).group(Group.Behavior, SubGroup.Interaction).onValueChange { _, it -> allowBreakAnyway.value = it.toList() } setting("Allow Sprint", allowSprint.value).group(Group.Behavior, SubGroup.Interaction).onValueChange { _, it -> allowSprint.value = it } setting("Allow Place", allowPlace.value).group(Group.Behavior, SubGroup.Interaction).onValueChange { _, it -> allowPlace.value = it } setting("Allow Place In Fluids Source", allowPlaceInFluidsSource.value).group(Group.Behavior, SubGroup.Interaction).onValueChange { _, it -> allowPlaceInFluidsSource.value = it } @@ -262,18 +264,19 @@ object BaritoneManager : Configurable(LambdaConfig), Automated by AutomationConf setting("Schematic Fallback Extension", schematicFallbackExtension.value).group(Group.Building, SubGroup.Schematic).onValueChange { _, it -> schematicFallbackExtension.value = it } setting("Builder Tick Scan Radius", builderTickScanRadius.value, 0..64).group(Group.Building, SubGroup.Schematic).onValueChange { _, it -> builderTickScanRadius.value = it } - setting("Acceptable Throwaway Items", acceptableThrowawayItems.value.toSet()).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> acceptableThrowawayItems.value = it.toList() } - setting("Blocks To Avoid", blocksToAvoid.value.toSet()).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> blocksToAvoid.value = it.toList() } - setting("Blocks To Disallow Breaking", blocksToDisallowBreaking.value.toSet()).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> blocksToDisallowBreaking.value = it.toList() } - setting("Blocks To Avoid Breaking", blocksToAvoidBreaking.value.toSet()).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> blocksToAvoidBreaking.value = it.toList() } - setting("Build Ignore Blocks", buildIgnoreBlocks.value.toSet()).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildIgnoreBlocks.value = it.toList() } - setting("Build Skip Blocks", buildSkipBlocks.value.toSet()).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildSkipBlocks.value = it.toList() } - setting("Build Valid Substitutes", buildValidSubstitutes.value.mapValues { (_, v) -> v.toSet() }).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildValidSubstitutes.value = it.mapValues { (_, v) -> v.toList() } } - setting("Build Substitutes", buildSubstitutes.value.mapValues { (_, v) -> v.toSet() }).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildSubstitutes.value = it.mapValues { (_, v) -> v.toList() } } - setting("Ok If Air", okIfAir.value.toSet()).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> okIfAir.value = it.toList() } + setting("Acceptable Throwaway Items", acceptableThrowawayItems.value).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> acceptableThrowawayItems.value = it.toList() } + setting("Blocks To Avoid", blocksToAvoid.value).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> blocksToAvoid.value = it.toList() } + setting("Blocks To Disallow Breaking", blocksToDisallowBreaking.value).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> blocksToDisallowBreaking.value = it.toList() } + setting("Blocks To Avoid Breaking", blocksToAvoidBreaking.value).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> blocksToAvoidBreaking.value = it.toList() } + setting("Build Ignore Blocks", buildIgnoreBlocks.value).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildIgnoreBlocks.value = it.toList() } + setting("Build Skip Blocks", buildSkipBlocks.value).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildSkipBlocks.value = it.toList() } + // FixMe: lmao fuck this im so done + //setting("Build Valid Substitutes", buildValidSubstitutes.value.flatMap { it.value }).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildValidSubstitutes.value = it.mapValues { (_, v) -> v.toList() } } + //setting("Build Substitutes", buildSubstitutes.value.flatMap { it.value }).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildSubstitutes.value = it.mapValues { (_, v) -> v.toList() } } + setting("Ok If Air", okIfAir.value).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> okIfAir.value = it.toList() } setting("Build Ignore Existing", buildIgnoreExisting.value).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildIgnoreExisting.value = it } setting("Build Ignore Direction", buildIgnoreDirection.value).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildIgnoreDirection.value = it } - setting("Build Ignore Properties", buildIgnoreProperties.value.toSet()).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildIgnoreProperties.value = it.toList() } + setting("Build Ignore Properties", buildIgnoreProperties.value).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> buildIgnoreProperties.value = it.toList() } setting("Avoid Updating Falling Blocks", avoidUpdatingFallingBlocks.value).group(Group.Building, SubGroup.BlockRules).onValueChange { _, it -> avoidUpdatingFallingBlocks.value = it } // RENDERING diff --git a/src/main/kotlin/com/lambda/interaction/construction/verify/TargetState.kt b/src/main/kotlin/com/lambda/interaction/construction/verify/TargetState.kt index 4ef59c17e..3642d133b 100644 --- a/src/main/kotlin/com/lambda/interaction/construction/verify/TargetState.kt +++ b/src/main/kotlin/com/lambda/interaction/construction/verify/TargetState.kt @@ -79,7 +79,7 @@ sealed class TargetState(val type: Type) : StateMatcher { override fun isEmpty() = true } - data class Solid(val replace: Set) : TargetState(Type.Solid) { + data class Solid(val replace: Collection) : TargetState(Type.Solid) { override fun toString() = "Solid" context(safeContext: SafeContext) diff --git a/src/main/kotlin/com/lambda/interaction/request/Request.kt b/src/main/kotlin/com/lambda/interaction/request/Request.kt index ba61c3c54..a010af841 100644 --- a/src/main/kotlin/com/lambda/interaction/request/Request.kt +++ b/src/main/kotlin/com/lambda/interaction/request/Request.kt @@ -31,7 +31,7 @@ abstract class Request : Automated { abstract val requestId: Int var fresh = true - abstract val tickStageMask: Set + abstract val tickStageMask: Collection abstract val nowOrNothing: Boolean abstract val done: Boolean diff --git a/src/main/kotlin/com/lambda/interaction/request/RequestHandler.kt b/src/main/kotlin/com/lambda/interaction/request/RequestHandler.kt index 2251edea8..ff188b8cc 100644 --- a/src/main/kotlin/com/lambda/interaction/request/RequestHandler.kt +++ b/src/main/kotlin/com/lambda/interaction/request/RequestHandler.kt @@ -35,10 +35,12 @@ import kotlin.reflect.KClass */ abstract class RequestHandler( val stagePriority: Int, - private vararg val openStages: Event, + vararg val blacklistedStages: TickEvent, private val onOpen: (SafeContext.() -> Unit)? = null, private val onClose: (SafeContext.() -> Unit)? = null ) : Loadable { + val openStages: List = ALL_STAGES.filter { it !in blacklistedStages } + /** * Represents if the handler is accepting requests at any given time */ diff --git a/src/main/kotlin/com/lambda/interaction/request/breaking/BreakConfig.kt b/src/main/kotlin/com/lambda/interaction/request/breaking/BreakConfig.kt index 434f11732..61c9f2e14 100644 --- a/src/main/kotlin/com/lambda/interaction/request/breaking/BreakConfig.kt +++ b/src/main/kotlin/com/lambda/interaction/request/breaking/BreakConfig.kt @@ -52,7 +52,7 @@ interface BreakConfig : ActionConfig, ISettingGroup { val avoidLiquids: Boolean val avoidSupporting: Boolean - val ignoredBlocks: Set + val ignoredBlocks: Collection val efficientOnly: Boolean val suitableToolsOnly: Boolean diff --git a/src/main/kotlin/com/lambda/interaction/request/breaking/BreakManager.kt b/src/main/kotlin/com/lambda/interaction/request/breaking/BreakManager.kt index a60e41b35..861253876 100644 --- a/src/main/kotlin/com/lambda/interaction/request/breaking/BreakManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/breaking/BreakManager.kt @@ -112,10 +112,6 @@ import kotlin.math.min */ object BreakManager : RequestHandler( 0, - TickEvent.Pre, - TickEvent.Input.Pre, - TickEvent.Input.Post, - TickEvent.Player.Post, onOpen = { if (activeInfos.isNotEmpty() || breaks.isNotEmpty()) BreakManager.logger.newStage(BreakManager.tickStage) diff --git a/src/main/kotlin/com/lambda/interaction/request/hotbar/HotbarConfig.kt b/src/main/kotlin/com/lambda/interaction/request/hotbar/HotbarConfig.kt index 6e701db86..3043d6017 100644 --- a/src/main/kotlin/com/lambda/interaction/request/hotbar/HotbarConfig.kt +++ b/src/main/kotlin/com/lambda/interaction/request/hotbar/HotbarConfig.kt @@ -53,5 +53,5 @@ interface HotbarConfig : ISettingGroup { /** * The sub-tick timings at which hotbar actions can be performed */ - val tickStageMask: Set + val tickStageMask: Collection } \ No newline at end of file diff --git a/src/main/kotlin/com/lambda/interaction/request/hotbar/HotbarManager.kt b/src/main/kotlin/com/lambda/interaction/request/hotbar/HotbarManager.kt index 5726dd362..e93d59fee 100644 --- a/src/main/kotlin/com/lambda/interaction/request/hotbar/HotbarManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/hotbar/HotbarManager.kt @@ -47,10 +47,6 @@ import net.minecraft.item.ItemStack */ object HotbarManager : RequestHandler( 1, - TickEvent.Pre, - TickEvent.Input.Pre, - TickEvent.Input.Post, - TickEvent.Player.Post, onOpen = { if (activeRequest != null) { setActiveSlot() diff --git a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionManager.kt b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionManager.kt index 01fce1170..171aa14e7 100644 --- a/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/interacting/InteractionManager.kt @@ -54,10 +54,6 @@ import net.minecraft.util.Hand */ object InteractionManager : RequestHandler( 0, - TickEvent.Pre, - TickEvent.Input.Pre, - TickEvent.Input.Post, - TickEvent.Player.Post, onOpen = { if (potentialInteractions.isNotEmpty()) InteractionManager.logger.newStage(InteractionManager.tickStage) diff --git a/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryConfig.kt b/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryConfig.kt index a61bb80c3..2647b15ad 100644 --- a/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryConfig.kt +++ b/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryConfig.kt @@ -28,8 +28,8 @@ import net.minecraft.block.Block interface InventoryConfig : ISettingGroup { val actionsPerSecond: Int - val tickStageMask: Set - val disposables: Set + val tickStageMask: Collection + val disposables: Collection val swapWithDisposables: Boolean val providerPriority: Priority val storePriority: Priority diff --git a/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt b/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt index 45f26f8d0..2602e0705 100644 --- a/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/inventory/InventoryManager.kt @@ -52,10 +52,6 @@ import net.minecraft.screen.slot.Slot */ object InventoryManager : RequestHandler( 1, - TickEvent.Pre, - TickEvent.Input.Pre, - TickEvent.Input.Post, - TickEvent.Player.Post, onOpen = { processActiveRequest() } ), Logger { private var activeRequest: InventoryRequest? = null diff --git a/src/main/kotlin/com/lambda/interaction/request/placing/PlaceManager.kt b/src/main/kotlin/com/lambda/interaction/request/placing/PlaceManager.kt index eb94479f2..3153710db 100644 --- a/src/main/kotlin/com/lambda/interaction/request/placing/PlaceManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/placing/PlaceManager.kt @@ -71,10 +71,6 @@ import kotlin.math.min object PlaceManager : RequestHandler( 0, - TickEvent.Pre, - TickEvent.Input.Pre, - TickEvent.Input.Post, - TickEvent.Player.Post, onOpen = { if (potentialPlacements.isNotEmpty()) PlaceManager.logger.newStage(PlaceManager.tickStage) diff --git a/src/main/kotlin/com/lambda/interaction/request/rotating/RotationConfig.kt b/src/main/kotlin/com/lambda/interaction/request/rotating/RotationConfig.kt index c7b9c8af0..75cca282f 100644 --- a/src/main/kotlin/com/lambda/interaction/request/rotating/RotationConfig.kt +++ b/src/main/kotlin/com/lambda/interaction/request/rotating/RotationConfig.kt @@ -20,7 +20,6 @@ package com.lambda.interaction.request.rotating import com.lambda.config.AbstractSetting import com.lambda.config.ISettingGroup import com.lambda.event.events.TickEvent -import com.lambda.event.events.TickEvent.Companion.ALL_STAGES interface RotationConfig : ISettingGroup { /** @@ -56,6 +55,6 @@ interface RotationConfig : ISettingGroup { override val keepTicks = 1 override val decayTicks = 1 override val turnSpeed = 360.0 - override val tickStageMask = ALL_STAGES.toSet() + override val tickStageMask = RotationManager.openStages.toSet() } } diff --git a/src/main/kotlin/com/lambda/interaction/request/rotating/RotationManager.kt b/src/main/kotlin/com/lambda/interaction/request/rotating/RotationManager.kt index b3a9c755c..276edf865 100644 --- a/src/main/kotlin/com/lambda/interaction/request/rotating/RotationManager.kt +++ b/src/main/kotlin/com/lambda/interaction/request/rotating/RotationManager.kt @@ -26,6 +26,7 @@ import com.lambda.event.events.PacketEvent import com.lambda.event.events.PlayerEvent import com.lambda.event.events.RenderEvent import com.lambda.event.events.TickEvent +import com.lambda.event.events.TickEvent.Companion.ALL_STAGES import com.lambda.event.events.UpdateManagerEvent import com.lambda.event.listener.SafeListener.Companion.listen import com.lambda.event.listener.UnsafeListener.Companion.listenUnsafe @@ -61,10 +62,7 @@ import kotlin.math.sin */ object RotationManager : RequestHandler( 1, - TickEvent.Pre, - TickEvent.Input.Pre, - TickEvent.Input.Post, - TickEvent.Player.Post, + *(ALL_STAGES.subList(ALL_STAGES.indexOf(TickEvent.Player.Post), ALL_STAGES.size - 1).toTypedArray()), ), Logger { var activeRotation = Rotation.ZERO var serverRotation = Rotation.ZERO diff --git a/src/main/kotlin/com/lambda/module/modules/debug/SettingTest.kt b/src/main/kotlin/com/lambda/module/modules/debug/SettingTest.kt deleted file mode 100644 index 5d76c1634..000000000 --- a/src/main/kotlin/com/lambda/module/modules/debug/SettingTest.kt +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2025 Lambda - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package com.lambda.module.modules.debug - -import com.lambda.module.Module -import com.lambda.module.tag.ModuleTag -import com.lambda.util.Communication.info -import com.lambda.util.KeyCode -import com.lambda.util.NamedEnum -import net.minecraft.block.Blocks -import net.minecraft.util.math.BlockPos -import java.awt.Color - -object SettingTest : Module( - name = "SettingTest", - tag = ModuleTag.DEBUG, -) { - private enum class Group(override val displayName: String) : NamedEnum { - Generic("Generic"), - Numeric("Numeric"), - Collections("Collections"), - Complex("Complex"), - Functional("Functional"), - } - - private enum class SubGroup(override val displayName: String) : NamedEnum { - Foo("Foo"), - Bar("Bar") - } - - // CharSetting - private val charSetting by setting("Character Setting", 'A').group(Group.Generic) - - // String - private val stringSetting by setting("String Setting", "Default String").group(Group.Generic, SubGroup.Foo) - - // Comparable - private val booleanSetting by setting("Boolean Setting", true).group(Group.Generic, SubGroup.Bar) - private val enumSetting by setting("Enum Setting", ExampleEnum.ValueOne).group(Group.Generic) - - // Numeric - private val doubleSetting by setting("Double Setting", 3.14159, 0.0..100.0, 0.1, description = "Changes the crumbs count", unit = " crumbs").group(Group.Numeric) - private val floatSetting by setting("Float Setting", 3.14f, 0.0f..100.0f, 0.1f, unit = " pies").group(Group.Numeric) - private val integerSetting by setting("Integer Setting", 42, 0..1000, unit = " apples").group(Group.Numeric) - private val longSetting by setting("Long Setting", 100000L, 0L..1000000L, 1000L, unit = " pizzas").group(Group.Numeric) - - // Collections - private val stringList by setting("String List", listOf("Hello", "World"), listOf("Hello", "World")).group(Group.Collections) - private val stringSet by setting("String Set", setOf("Apple", "Banana"), setOf("Apple", "Banana")).group(Group.Collections) - private val stringMap by setting("String Map", mapOf("Key1" to "Value1", "Key2" to "Value2")).group(Group.Collections) - - // Complex - private val blockPosSetting by setting("Block Position", BlockPos(0, 0, 0)).group(Group.Complex) - private val blockSetting by setting("Block Setting", Blocks.OBSIDIAN).group(Group.Complex) - private val colorSetting by setting("Color Setting", Color.GREEN).group(Group.Complex) - private val keybindSettingTest by setting("Key Bind Setting", KeyCode.T).group(Group.Complex) - - // Complex collections - private val blockPosSet by setting("Block Position Set", setOf(BlockPos(0, 0, 0)), setOf(BlockPos(0, 0, 0))).group(Group.Complex) - private val blockList by setting("Block List", listOf(Blocks.OBSIDIAN), listOf(Blocks.OBSIDIAN)).group(Group.Complex) - private val colorMap by setting("Color Map", mapOf("Primary" to Color.GREEN)).group(Group.Complex) - private val keybindSet by setting("Key Bind Set", setOf(KeyCode.T), setOf(KeyCode.T)).group(Group.Complex) - - // Other - private val unitSetting by setting("Unit Test", { this@SettingTest.info("Unit setting") }).group(Group.Functional) - - enum class ExampleEnum { - ValueOne, - ValueTwo, - ValueThree - } -} diff --git a/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt b/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt index 33c382521..820541f40 100644 --- a/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt +++ b/src/main/kotlin/com/lambda/module/modules/movement/BetterFirework.kt @@ -33,7 +33,6 @@ import com.lambda.module.tag.ModuleTag import com.lambda.threading.runSafe import com.lambda.util.KeyCode import com.lambda.util.Mouse -import com.lambda.util.NamedEnum import com.lambda.util.player.SlotUtils.hotbar import com.lambda.util.player.SlotUtils.hotbarAndStorage import net.minecraft.client.network.ClientPlayerEntity @@ -49,20 +48,14 @@ object BetterFirework : Module( description = "Automatic takeoff with fireworks", tag = ModuleTag.MOVEMENT, ) { - private var activateButton by setting("Activate Key", Bind(0, 0, Mouse.Middle.ordinal), "Button to activate Firework").group(Group.General) - private var midFlightActivationKey by setting("Mid-Flight Activation Key", Bind(0, 0, KeyCode.Unbound.code), "Firework use key for mid flight activation").group(Group.General) - private var middleClickCancel by setting("Middle Click Cancel", false, description = "Cancel pick block action on middle mouse click") { activateButton.key != KeyCode.Unbound.code }.group(Group.General) + private var activateButton by setting("Activate Key", Bind(0, 0, Mouse.Middle.ordinal), "Button to activate Firework") + private var midFlightActivationKey by setting("Mid-Flight Activation Key", Bind(0, 0, KeyCode.Unbound.code), "Firework use key for mid flight activation") + private var middleClickCancel by setting("Middle Click Cancel", false, description = "Cancel pick block action on middle mouse click") { activateButton.key != KeyCode.Unbound.code } private var fireworkInteract by setting("Right Click Fly", true, "Automatically start flying when right clicking fireworks") private var fireworkInteractCancel by setting("Right Click Cancel", false, "Cancel block interactions while holding fireworks") { fireworkInteract } - private var clientSwing by setting("Swing", true, "Swing hand client side").group(Group.General) - private var invUse by setting("Inventory", true, "Use fireworks from inventory") { activateButton.key != KeyCode.Unbound.code }.group(Group.General) - - private enum class Group(override val displayName: String) : NamedEnum { - General("General"), - Hotbar("Hotbar"), - Inventory("Inventory") - } + private var clientSwing by setting("Swing", true, "Swing hand client side") + private var invUse by setting("Inventory", true, "Use fireworks from inventory") { activateButton.key != KeyCode.Unbound.code } private var takeoffState = TakeoffState.None diff --git a/src/main/kotlin/com/lambda/module/modules/network/PacketLimiter.kt b/src/main/kotlin/com/lambda/module/modules/network/PacketLimiter.kt index db575fc9f..fa5010fc2 100644 --- a/src/main/kotlin/com/lambda/module/modules/network/PacketLimiter.kt +++ b/src/main/kotlin/com/lambda/module/modules/network/PacketLimiter.kt @@ -53,7 +53,7 @@ object PacketLimiter : Module( ) // ToDo: Find a way to have a list of serverbound packets - private val ignorePackets by setting("Ignore Packets", defaultIgnorePackets, defaultIgnorePackets, "Packets to ignore when limiting") + private val ignorePackets by setting("Ignore Packets", defaultIgnorePackets, description = "Packets to ignore when limiting") init { onEnable { diff --git a/src/main/kotlin/com/lambda/module/modules/network/PacketLogger.kt b/src/main/kotlin/com/lambda/module/modules/network/PacketLogger.kt index 0e862af78..b4b8519bd 100644 --- a/src/main/kotlin/com/lambda/module/modules/network/PacketLogger.kt +++ b/src/main/kotlin/com/lambda/module/modules/network/PacketLogger.kt @@ -17,6 +17,7 @@ package com.lambda.module.modules.network +import com.google.gson.JsonPrimitive import com.lambda.Lambda import com.lambda.Lambda.mc import com.lambda.event.events.PacketEvent @@ -32,6 +33,7 @@ import com.lambda.util.DynamicReflectionSerializer.dynamicString import com.lambda.util.FolderRegister import com.lambda.util.FolderRegister.relativeMCPath import com.lambda.util.Formatting.getTime +import com.lambda.util.reflections.getInstances import com.lambda.util.text.ClickEvents import com.lambda.util.text.buildText import com.lambda.util.text.clickEvent @@ -58,8 +60,11 @@ object PacketLogger : Module( private val networkSide by setting("Network Side", NetworkSide.Any, "Side of the network to log packets from") private val logTicks by setting("Log Ticks", true, "Show game ticks in the log") private val scope by setting("Scope", Scope.Any, "Scope of packets to log") - private val whitelist by setting("Whitelist Packets", emptyList(), emptyList(), "Packets to whitelist") { scope == Scope.Whitelist } - private val blacklist by setting("Blacklist Packets", emptyList(), emptyList(), "Packets to blacklist") { scope == Scope.Blacklist } + + val packetList = getInstances> { println(it.moduleInfo.location); true } + // ToDo: Add a packet list + //private val whitelist by setting("Whitelist Packets", emptyList(), emptyList(), "Packets to whitelist", { JsonPrimitive(it) }, { it.asString }) { scope == Scope.Whitelist } + //private val blacklist by setting("Blacklist Packets", emptyList(), emptyList(), "Packets to blacklist", { JsonPrimitive(it) }, { it.asString }) { scope == Scope.Blacklist } private val maxRecursionDepth by setting("Max Recursion Depth", 6, 1..10, 1, "Maximum recursion depth for packet serialization") private val logConcurrent by setting("Build Data Concurrent", false, "Whether to serialize packets concurrently. Will not save packets in chronological order but wont lag the game.") @@ -79,8 +84,8 @@ object PacketLogger : Module( fun shouldLog(packet: Packet<*>) = when (this) { Any -> true - Whitelist -> packet::class.simpleName in whitelist - Blacklist -> packet::class.simpleName !in blacklist + Whitelist -> false//packet::class.simpleName in whitelist + Blacklist -> false//packet::class.simpleName !in blacklist } } diff --git a/src/main/kotlin/com/lambda/module/modules/render/BlockESP.kt b/src/main/kotlin/com/lambda/module/modules/render/BlockESP.kt index 6cc826950..d58be2c9b 100644 --- a/src/main/kotlin/com/lambda/module/modules/render/BlockESP.kt +++ b/src/main/kotlin/com/lambda/module/modules/render/BlockESP.kt @@ -18,6 +18,7 @@ package com.lambda.module.modules.render import com.lambda.Lambda.mc +import com.lambda.config.serializer.BlockCodec import com.lambda.context.SafeContext import com.lambda.graphics.renderer.esp.ChunkedESP.Companion.newChunkedESP import com.lambda.graphics.renderer.esp.DirectionMask @@ -42,7 +43,7 @@ object BlockESP : Module( ) { // ToDo: Toggle searching, solve memory leak private val searchBlocks by setting("Search Blocks", true, "Search for blocks around the player") - private val blocks by setting("Blocks", setOf(Blocks.BEDROCK), setOf(Blocks.BEDROCK), "Render blocks") { searchBlocks }.onValueChange(::rebuildMesh) + private val blocks by setting("Blocks", setOf(Blocks.BEDROCK), description = "Render blocks") { searchBlocks }.onValueChange(::rebuildMesh) private var drawFaces: Boolean by setting("Draw Faces", true, "Draw faces of blocks") { searchBlocks }.onValueChange(::rebuildMesh).onValueChange { _, to -> if (!to) drawOutlines = true } private var drawOutlines: Boolean by setting("Draw Outlines", true, "Draw outlines of blocks") { searchBlocks }.onValueChange(::rebuildMesh).onValueChange { _, to -> if (!to) drawFaces = true } private val mesh by setting("Mesh", true, "Connect similar adjacent blocks") { searchBlocks }.onValueChange(::rebuildMesh) diff --git a/src/main/kotlin/com/lambda/module/modules/render/XRay.kt b/src/main/kotlin/com/lambda/module/modules/render/XRay.kt index be52e5208..08d90d0f3 100644 --- a/src/main/kotlin/com/lambda/module/modules/render/XRay.kt +++ b/src/main/kotlin/com/lambda/module/modules/render/XRay.kt @@ -44,7 +44,7 @@ object XRay : Module( val opacity by setting("Opacity", 40, 0..100, 1, "Opacity of the non x-rayed blocks, (automatically overridden as 0 when running Sodium)") .onValueChange { _, _ -> if (isEnabled) mc.worldRenderer.reload() } - private val selection by setting("Block Selection", defaultBlocks, defaultBlocks, "Block selection that will be shown (whitelist) or hidden (blacklist)") + private val selection by setting("Block Selection", defaultBlocks, "Block selection that will be shown (whitelist) or hidden (blacklist)") .onValueChange { _, _ -> if (isEnabled) mc.worldRenderer.reload() } private val mode by setting("Selection Mode", Selection.Whitelist, "The mode of the block selection")