From 2bff2a15fcad88752cf5981f829e58c3491d0310 Mon Sep 17 00:00:00 2001 From: Bibi Reden Date: Wed, 21 May 2025 20:02:30 -0500 Subject: [PATCH 1/2] [partial-feat] resources separated by datapack, defaults removed for now --- gradle.properties | 2 +- .../config/AttributeConfigManager.kt | 11 +- .../config/DataAttributesConfigProviders.kt | 5 +- .../entry/DefaultAttributesReloadListener.kt | 89 ++++--- .../config/functions/AttributeFunction.kt | 14 +- .../functions/AttributeFunctionConfig.kt | 3 +- .../data/EntityAttributeData.kt | 3 +- .../data_attributes/identifier/Identifiers.kt | 7 + .../data_attributes/serde/JanksonBuilders.kt | 1 - .../data_attributes/ui/button/Buttons.kt | 10 + .../config/AttributeConfigComponent.kt | 3 - .../config/AttributeOverrideComponent.kt | 88 +++---- .../config/entities/EntityTypesComponent.kt | 24 +- .../entities/EntityTypesHeaderComponent.kt | 27 +- .../function/AttributeFunctionComponent.kt | 21 +- .../AttributeFunctionHeaderComponent.kt | 19 +- .../providers/AttributeFunctionProvider.kt | 9 - .../providers/AttributeOverrideProvider.kt | 12 +- .../config/providers/EntityTypesProvider.kt | 247 +----------------- .../config/providers/EntityTypesProviderV2.kt | 33 --- 20 files changed, 151 insertions(+), 477 deletions(-) create mode 100644 src/main/kotlin/com/bibireden/data_attributes/identifier/Identifiers.kt create mode 100644 src/main/kotlin/com/bibireden/data_attributes/ui/button/Buttons.kt delete mode 100644 src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProviderV2.kt diff --git a/gradle.properties b/gradle.properties index 215bf64..4213efc 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,7 @@ parchment_version=1.20.1:2023.09.03 quilt_mappings_version=23 yarn_mappings=1.20.1+build.10 -loader_version=0.15.11 +loader_version=0.16.14 modmenu_version=7.2.2 diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/AttributeConfigManager.kt b/src/main/kotlin/com/bibireden/data_attributes/config/AttributeConfigManager.kt index 36890e3..7995a18 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/AttributeConfigManager.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/AttributeConfigManager.kt @@ -10,6 +10,7 @@ import com.bibireden.data_attributes.config.functions.AttributeFunction import com.bibireden.data_attributes.config.models.OverridesConfigModel.AttributeOverride import com.bibireden.data_attributes.data.EntityAttributeData import com.bibireden.data_attributes.config.entities.EntityTypeData +import com.bibireden.data_attributes.config.entry.DatapackCaches import com.bibireden.data_attributes.endec.Endecs import com.bibireden.data_attributes.ext.keyOf import com.bibireden.data_attributes.mutable.MutableEntityAttribute @@ -33,7 +34,7 @@ import net.minecraft.util.Identifier class AttributeConfigManager(var data: Data = Data(), private val handler: AttributeContainerHandler = AttributeContainerHandler()) { var updateFlag: Int = 0 - var defaults: DefaultAttributesReloadListener.Cache = DefaultAttributesReloadListener.Cache() + var defaults: DatapackCaches = LinkedHashMap() @JvmRecord data class Tuple(val livingEntity: Class, val value: T) @@ -111,9 +112,11 @@ class AttributeConfigManager(var data: Data = Data(), private val handler: Attri * This applies the data immediately afterward. */ fun update() { - this.data.overrides = ConfigMerger.mergeOverrides(defaults.overrides.entries) - this.data.functions = ConfigMerger.mergeFunctions(defaults.functions.entries) - this.data.entity_types = ConfigMerger.mergeEntityTypes(defaults.types.entries) + for (cache in defaults.values) { + this.data.overrides = ConfigMerger.mergeOverrides(cache.overrides.entries) + this.data.functions = ConfigMerger.mergeFunctions(cache.functions.entries) + this.data.entity_types = ConfigMerger.mergeEntityTypes(cache.types.entries) + } this.onDataUpdate() } diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/DataAttributesConfigProviders.kt b/src/main/kotlin/com/bibireden/data_attributes/config/DataAttributesConfigProviders.kt index a7ab076..640fbc4 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/DataAttributesConfigProviders.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/DataAttributesConfigProviders.kt @@ -4,7 +4,6 @@ import com.bibireden.data_attributes.ui.colors.ColorCodes import com.bibireden.data_attributes.ui.config.providers.AttributeFunctionProvider import com.bibireden.data_attributes.ui.config.providers.AttributeOverrideProvider import com.bibireden.data_attributes.ui.config.providers.EntityTypesProvider -import com.bibireden.data_attributes.ui.config.providers.EntityTypesProviderV2 import com.google.common.base.Predicate import io.wispforest.owo.config.ui.OptionComponentFactory import io.wispforest.owo.ui.component.Components @@ -23,7 +22,7 @@ object DataAttributesConfigProviders { val text = Text.empty() if (entry != null) { text.append(Text.translatable(representation(entry)).append(" ")) - .setStyle(Style.EMPTY.withColor(if (isDefault) 0x84de56 else 0xE7C14B)) + .setStyle(Style.EMPTY.withColor(0xE7C14B)) } text.append(Text.literal("($id)").also { t -> t.setStyle( @@ -44,7 +43,7 @@ object DataAttributesConfigProviders { } val ENTITY_TYPES_FACTORY = OptionComponentFactory { _, option -> - return@OptionComponentFactory EntityTypesProviderV2(option).let { OptionComponentFactory.Result(it, it) } + return@OptionComponentFactory EntityTypesProvider(option).let { OptionComponentFactory.Result(it, it) } } fun textBoxComponent(txt: Text, obj: Any, predicate: Predicate? = null, onChange: ((String) -> Unit)? = null, textBoxID: String? = null): FlowLayout { diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/entry/DefaultAttributesReloadListener.kt b/src/main/kotlin/com/bibireden/data_attributes/config/entry/DefaultAttributesReloadListener.kt index 8024687..951c095 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/entry/DefaultAttributesReloadListener.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/entry/DefaultAttributesReloadListener.kt @@ -15,19 +15,22 @@ import kotlinx.serialization.json.Json import kotlinx.serialization.json.decodeFromStream import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener import net.minecraft.registry.Registries +import net.minecraft.resource.Resource import net.minecraft.resource.ResourceManager import net.minecraft.util.Identifier import net.minecraft.util.profiler.Profiler import java.util.concurrent.CompletableFuture import java.util.concurrent.Executor +typealias DatapackCaches = LinkedHashMap + /** * A listener meant to compile [Pack]'s based on load order for preference * and then be applied to the manager. */ @OptIn(ExperimentalSerializationApi::class) -class DefaultAttributesReloadListener : SimpleResourceReloadListener { - var data: Cache = Cache() +class DefaultAttributesReloadListener : SimpleResourceReloadListener { + var caches: DatapackCaches = LinkedHashMap() @Serializable data class Overrides(var entries: LinkedHashMap = LinkedHashMap()) @@ -36,8 +39,12 @@ class DefaultAttributesReloadListener : SimpleResourceReloadListener> = LinkedHashMap()) - @Serializable - data class Cache(val overrides: Overrides = Overrides(), val functions: Functions = Functions(), val types: EntityTypes = EntityTypes()) + data class Cache( + val resource: Resource, + val overrides: Overrides = Overrides(), + val functions: Functions = Functions(), + val types: EntityTypes = EntityTypes() + ) companion object { const val DIRECTORY = DataAttributes.MOD_ID @@ -47,60 +54,67 @@ class DefaultAttributesReloadListener : SimpleResourceReloadListener { + override fun load(manager: ResourceManager, profiler: Profiler, executor: Executor): CompletableFuture { return CompletableFuture.supplyAsync { - val cache = Cache() - - readOverrides(manager, cache) - readFunctions(manager, cache) - readEntityTypes(manager, cache) - - // Filtering before applying the cache. - cache.overrides.entries = LinkedHashMap(cache.overrides.entries.filter { (id, _) -> Registries.ATTRIBUTE.containsId(id) }) - cache.functions.entries.forEach { (id, functions) -> - if (!Registries.ATTRIBUTE.containsId(id)) { - cache.functions.entries.remove(id) - return@forEach + val caches: DatapackCaches = LinkedHashMap() + + readOverrides(manager, caches) + readFunctions(manager, caches) + readEntityTypes(manager, caches) + + // Filtering before applying the caches. + for (cache in caches.values) { + cache.overrides.entries = LinkedHashMap(cache.overrides.entries.filter { (id, _) -> Registries.ATTRIBUTE.containsId(id) }) + cache.functions.entries.forEach { (id, functions) -> + if (!Registries.ATTRIBUTE.containsId(id)) { + cache.functions.entries.remove(id) + return@forEach + } + cache.functions.entries[id] = LinkedHashMap(functions.filter { (id2) -> Registries.ATTRIBUTE.containsId(id2) }) } - cache.functions.entries[id] = LinkedHashMap(functions.filter { (id2) -> Registries.ATTRIBUTE.containsId(id2) }) - } - cache.types.entries.forEach { (id, data) -> - if (!Registries.ENTITY_TYPE.containsId(id)) { - cache.types.entries.remove(id) - return@forEach + cache.types.entries.forEach { (id, data) -> + if (!Registries.ENTITY_TYPE.containsId(id)) { + cache.types.entries.remove(id) + return@forEach + } + cache.types.entries[id] = LinkedHashMap(data.filter { (id2) -> Registries.ATTRIBUTE.containsId(id2) }) } - cache.types.entries[id] = LinkedHashMap(data.filter { (id2) -> Registries.ATTRIBUTE.containsId(id2) }) } - cache + caches } } - override fun apply(cache: Cache, manager: ResourceManager, profiler: Profiler, executor: Executor): CompletableFuture { - return CompletableFuture.runAsync { DataAttributes.MANAGER.defaults = cache } + override fun apply(caches: DatapackCaches, manager: ResourceManager, profiler: Profiler, executor: Executor): CompletableFuture { + return CompletableFuture.runAsync { DataAttributes.MANAGER.defaults = caches } + } + + private fun computeResourceToCache(caches: DatapackCaches, id: Identifier, resource: Resource): Cache { + return caches.computeIfAbsent(Identifier.of(id.namespace, "pack")!!) { Cache(resource) } } - private fun readOverrides(manager: ResourceManager, cache: Cache) { + private fun readOverrides(manager: ResourceManager, caches: DatapackCaches) { val path = "$DIRECTORY/overrides" - manager.findResources(path, ::isPathJson).forEach { (id, res) -> + manager.findResources(path, ::isPathJson).forEach { (resId, res) -> try { Json.decodeFromStream(res.inputStream).entries.forEach { (id, entry) -> - cache.overrides.entries.computeIfAbsent(id) { entry } + computeResourceToCache(caches, resId, res).overrides.entries.computeIfAbsent(id) { entry } } } catch (why: Exception) { - DataAttributes.LOGGER.error("Failed to parse overrides@$id :: {}", why.message) + DataAttributes.LOGGER.error("Failed to parse overrides@$resId :: {}", why.message) } } } - private fun readFunctions(manager: ResourceManager, cache: Cache) { + private fun readFunctions(manager: ResourceManager, caches: DatapackCaches) { val path = "$DIRECTORY/functions" - manager.findResources(path, ::isPathJson).forEach { (id, res) -> + manager.findResources(path, ::isPathJson).forEach { (resId, res) -> try { Json.decodeFromStream(res.inputStream).entries.forEach { (id, entry) -> + val cache = computeResourceToCache(caches, resId, res) val presentEntry = cache.functions.entries[id] if (presentEntry == null) { cache.functions.entries[id] = entry @@ -114,17 +128,18 @@ class DefaultAttributesReloadListener : SimpleResourceReloadListener + manager.findResources(path, ::isPathJson).forEach { (resId, res) -> try { Json.decodeFromStream(res.inputStream).entries.forEach { (id, entry) -> + val cache = computeResourceToCache(caches, resId, res) val presentEntry = cache.types.entries[id] if (presentEntry == null) { cache.types.entries[id] = entry @@ -138,7 +153,7 @@ class DefaultAttributesReloadListener : SimpleResourceReloadListener = StructEndecBuilder.of( Endec.BOOLEAN.optionalFieldOf("enabled", { it.enabled }, true), - Endec.STRING.xmap(StackingBehavior::of) { x -> x.name.uppercase() }.fieldOf("behavior") { it.behavior }, + Endec.STRING.xmap(StackingBehavior::of) { it.name.uppercase() }.fieldOf("behavior") { it.behavior }, Endec.DOUBLE.fieldOf("value") { it.value }, ::AttributeFunction ) diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/functions/AttributeFunctionConfig.kt b/src/main/kotlin/com/bibireden/data_attributes/config/functions/AttributeFunctionConfig.kt index e179472..2862903 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/functions/AttributeFunctionConfig.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/functions/AttributeFunctionConfig.kt @@ -2,6 +2,7 @@ package com.bibireden.data_attributes.config.functions import com.bibireden.data_attributes.endec.Endecs import com.bibireden.data_attributes.ext.keyOf +import io.wispforest.endec.Endec import net.minecraft.entity.attribute.EntityAttribute import net.minecraft.util.Identifier @@ -13,6 +14,6 @@ data class AttributeFunctionConfig( ) { companion object { @JvmField - val ENDEC = Endecs.IDENTIFIER.keyOf(Endecs.IDENTIFIER.keyOf(AttributeFunction.ENDEC)).xmap(::AttributeFunctionConfig) { it.data } + val ENDEC: Endec = Endecs.IDENTIFIER.keyOf(Endecs.IDENTIFIER.keyOf(AttributeFunction.ENDEC)).xmap(::AttributeFunctionConfig) { it.data } } } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/data_attributes/data/EntityAttributeData.kt b/src/main/kotlin/com/bibireden/data_attributes/data/EntityAttributeData.kt index 0a4a8a5..421c5df 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/data/EntityAttributeData.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/data/EntityAttributeData.kt @@ -6,6 +6,7 @@ import com.bibireden.data_attributes.config.models.OverridesConfigModel.Attribut import com.bibireden.data_attributes.endec.Endecs import com.bibireden.data_attributes.ext.keyOf import com.bibireden.data_attributes.mutable.MutableEntityAttribute +import io.wispforest.endec.Endec import io.wispforest.endec.impl.StructEndecBuilder import net.minecraft.entity.attribute.EntityAttribute import net.minecraft.registry.Registries @@ -20,7 +21,7 @@ class EntityAttributeData(val override: AttributeOverride? = null, val functions companion object { @JvmField - val ENDEC = StructEndecBuilder.of( + val ENDEC: Endec = StructEndecBuilder.of( AttributeOverride.ENDEC.nullableOf().fieldOf("override") { it.override }, Endecs.IDENTIFIER.keyOf(AttributeFunction.ENDEC).fieldOf("functions") { it.functions }, ::EntityAttributeData, diff --git a/src/main/kotlin/com/bibireden/data_attributes/identifier/Identifiers.kt b/src/main/kotlin/com/bibireden/data_attributes/identifier/Identifiers.kt new file mode 100644 index 0000000..1d8046b --- /dev/null +++ b/src/main/kotlin/com/bibireden/data_attributes/identifier/Identifiers.kt @@ -0,0 +1,7 @@ +package com.bibireden.data_attributes.identifier + +import net.minecraft.util.Identifier + +object Identifiers { + fun unknown(): Identifier = Identifier.of("minecraft", "unknown")!! +} \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/data_attributes/serde/JanksonBuilders.kt b/src/main/kotlin/com/bibireden/data_attributes/serde/JanksonBuilders.kt index 64a1be9..52e284f 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/serde/JanksonBuilders.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/serde/JanksonBuilders.kt @@ -2,7 +2,6 @@ package com.bibireden.data_attributes.serde import blue.endless.jankson.Jankson import blue.endless.jankson.JsonObject -import blue.endless.jankson.JsonPrimitive import com.bibireden.data_attributes.config.functions.AttributeFunction import com.bibireden.data_attributes.config.functions.AttributeFunctionConfig import com.bibireden.data_attributes.config.entities.EntityTypeData diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/button/Buttons.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/button/Buttons.kt new file mode 100644 index 0000000..eeb1325 --- /dev/null +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/button/Buttons.kt @@ -0,0 +1,10 @@ +package com.bibireden.data_attributes.ui.button + +import com.bibireden.data_attributes.ui.renderers.ButtonRenderers +import io.wispforest.owo.ui.component.ButtonComponent +import io.wispforest.owo.ui.component.Components +import net.minecraft.text.Text + +object Buttons { + fun add(onPress: (ButtonComponent) -> Unit): ButtonComponent = Components.button(Text.translatable("text.config.data_attributes.buttons.add"), onPress).renderer(ButtonRenderers.STANDARD) +} \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeConfigComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeConfigComponent.kt index 32716c1..5620430 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeConfigComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeConfigComponent.kt @@ -9,9 +9,6 @@ interface AttributeConfigComponent { val registry: Registry val registryEntry: T? get() = registry[identifier] - /** If this [Identifier] currently exists in the backing field. */ - val isDefault: Boolean - /** If the given entry is currently registered. */ val isRegistered: Boolean get() = registryEntry != null diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeOverrideComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeOverrideComponent.kt index 8756eba..197813c 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeOverrideComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeOverrideComponent.kt @@ -40,8 +40,6 @@ class AttributeOverrideComponent( private fun isRegistered() = attribute != null - private fun isDefault() = !backing.containsKey(identifier) - private val dataEntryMin: DataEntryComponent? private val dataEntryMax: DataEntryComponent? private val dataEntryMinFallback: DataEntryComponent? @@ -71,7 +69,7 @@ class AttributeOverrideComponent( dataEntryMaxFallback?.textbox?.setPlaceholder(Text.of(override.max_fallback.toString())) } - this.titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, isDefault())) + this.titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, false)) titleLayout().tooltip(null) @@ -79,21 +77,11 @@ class AttributeOverrideComponent( !isRegistered() -> { titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.invalid")) } - isDefault() -> { - titleLayout().tooltip(Text.translatable("text.config.data_attributes_data_entry.default")) - } } } private fun changeAttributeOverride(changed: AttributeOverride) { - val wasDefault = isDefault() replaceEntry(identifier, changed) - if (wasDefault) { - val index = provider.children().indexOf(this) - this.provider.child(index, AttributeOverrideComponent(identifier, changed, backing, provider)) - this.remove() - update() - } } init { @@ -111,55 +99,47 @@ class AttributeOverrideComponent( button.renderer(ButtonRenderers.STANDARD) }) - if (!isDefault()) { - content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.reset")) - { - changeAttributeOverride(override.copy( - min = attribute?.`data_attributes$min_fallback`() ?: override.min_fallback, - max = attribute?.`data_attributes$max_fallback`() ?: override.max_fallback, - smoothness = 1.0, - formula = StackingFormula.Flat, - format = AttributeFormat.Whole - )) - } - .renderer(ButtonRenderers.STANDARD) - ) + content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.reset")) + { + changeAttributeOverride(override.copy( + min = attribute?.`data_attributes$min_fallback`() ?: override.min_fallback, + max = attribute?.`data_attributes$max_fallback`() ?: override.max_fallback, + smoothness = 1.0, + formula = StackingFormula.Flat, + format = AttributeFormat.Whole + )) + } + .renderer(ButtonRenderers.STANDARD) + ) - content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.edit")) { - if (this.childById(EditFieldComponent::class.java, "edit-field") != null) return@button + content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.edit")) { + if (this.childById(EditFieldComponent::class.java, "edit-field") != null) return@button - val field = FieldComponents.identifier( - { newId, _ -> - if (newId in backing || !Registries.ATTRIBUTE.containsId(newId)) return@identifier + val field = FieldComponents.identifier( + { newId, _ -> + if (newId in backing || !Registries.ATTRIBUTE.containsId(newId)) return@identifier - this.backing.remove(identifier) - replaceEntry(newId, override) - update() - }, - autocomplete = Registries.ATTRIBUTE.ids - ).apply { id("edit-field") } + this.backing.remove(identifier) + replaceEntry(newId, override) + update() + }, + autocomplete = Registries.ATTRIBUTE.ids + ).apply { id("edit-field") } - field.textBox.predicate = { id -> id !in backing && Registries.ATTRIBUTE.containsId(id) } + field.textBox.predicate = { id -> id !in backing && Registries.ATTRIBUTE.containsId(id) } - this.child(0, field) - } - .renderer(ButtonRenderers.STANDARD) - ) - - content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.remove")) { - this.backing.remove(identifier) + this.child(0, field) + } + .renderer(ButtonRenderers.STANDARD) + ) - val default = DataAttributesAPI.serverManager.defaults.overrides.entries[identifier] - if (default != null) { - val index = provider.children().indexOf(this) - this.provider.child(index, AttributeOverrideComponent(identifier, default, backing, provider)) - } + content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.remove")) { + this.backing.remove(identifier) - remove() - } - .renderer(ButtonRenderers.STANDARD) - ) + remove() } + .renderer(ButtonRenderers.STANDARD) + ) }) dataEntryMin = EntryComponents.double(Text.translatable("$stub.min"), DataEntryComponent.Properties({ changeAttributeOverride(override.copy(min = it)) }), override.min.toString()) diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesComponent.kt index db3b3eb..e7d5f07 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesComponent.kt @@ -1,31 +1,24 @@ package com.bibireden.data_attributes.ui.components.config.entities import com.bibireden.data_attributes.DataAttributesClient -import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.config.DataAttributesConfigProviders.registryEntryToText import com.bibireden.data_attributes.config.DataAttributesConfigProviders.textBoxComponent import com.bibireden.data_attributes.config.Validators import com.bibireden.data_attributes.config.entities.EntityTypeData import com.bibireden.data_attributes.config.entities.EntityTypeEntry import com.bibireden.data_attributes.ext.round -import com.bibireden.data_attributes.ui.components.buttons.ButtonComponents import com.bibireden.data_attributes.ui.components.config.AttributeConfigComponent import com.bibireden.data_attributes.ui.components.config.ConfigDockComponent import com.bibireden.data_attributes.ui.components.entries.DataEntryComponent import com.bibireden.data_attributes.ui.components.entries.EntryComponents import com.bibireden.data_attributes.ui.components.fields.FieldComponents -import com.bibireden.data_attributes.ui.config.providers.EntityTypesProviderV2 -import com.bibireden.data_attributes.ui.renderers.ButtonRenderers +import com.bibireden.data_attributes.ui.config.providers.EntityTypesProvider import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.SearchAnchorComponent -import io.wispforest.owo.ui.component.Components import io.wispforest.owo.ui.component.LabelComponent -import io.wispforest.owo.ui.component.TextBoxComponent import io.wispforest.owo.ui.container.CollapsibleContainer -import io.wispforest.owo.ui.container.Containers import io.wispforest.owo.ui.container.FlowLayout import io.wispforest.owo.ui.core.Sizing -import io.wispforest.owo.ui.core.VerticalAlignment import net.minecraft.entity.EntityType import net.minecraft.entity.LivingEntity import net.minecraft.entity.attribute.ClampedEntityAttribute @@ -36,28 +29,25 @@ import net.minecraft.registry.Registry import net.minecraft.text.Text import net.minecraft.util.Identifier -class EntityTypesComponent(override var identifier: Identifier, private var parentId: Identifier, private var entry: EntityTypeEntry, private val provider: EntityTypesProviderV2) +class EntityTypesComponent(override var identifier: Identifier, private var parentId: Identifier, private var entry: EntityTypeEntry, private val provider: EntityTypesProvider) : CollapsibleContainer(Sizing.content(), Sizing.content(), Text.of(""), DataAttributesClient.UI_STATE.collapsible.entityTypeEntries[parentId.toString()]?.get(identifier.toString()) ?: true), AttributeConfigComponent { override val registry: Registry = Registries.ATTRIBUTE - override val isDefault: Boolean - get() = provider.backing[parentId]?.data?.get(identifier) == null - private fun updateSearchAnchor() { childById(SearchAnchorComponent::class.java, "search-anchor")?.remove() child(SearchAnchorComponent(titleLayout(), Option.Key.ROOT, { identifier.toString() }, { Text.translatable(identifier.toTranslationKey()).toString() }).id("search-anchor")) } private fun updateTextLabel() { - titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, registry, { it.translationKey }, isDefault)) + titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, registry, { it.translationKey }, false)) } override fun update() { titleLayout().tooltip(null) + when { !isRegistered -> titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.invalid")) - isDefault -> titleLayout().tooltip(Text.translatable("text.config.data_attributes_data_entry.default")) } // find fallback @@ -106,11 +96,7 @@ class EntityTypesComponent(override var identifier: Identifier, private var pare child(ConfigDockComponent(ConfigDockComponent.ConfigDefaultProperties({ _, _ -> val entry = provider.backing[parentId]?.data?.toMutableMap() ?: return@ConfigDefaultProperties if (entry.remove(identifier) != null) { - val defaultEntry = DataAttributesAPI.serverManager.defaults.types.entries[parentId]?.get(identifier) - if (defaultEntry != null) { - valueEntry.textbox.text = defaultEntry.value.toString() - } - else remove() + remove() provider.backing[parentId] = EntityTypeData(entry) diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesHeaderComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesHeaderComponent.kt index 5d16856..d2e7ebf 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesHeaderComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesHeaderComponent.kt @@ -1,48 +1,39 @@ package com.bibireden.data_attributes.ui.components.config.entities import com.bibireden.data_attributes.DataAttributesClient -import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.config.DataAttributesConfigProviders.registryEntryToText import com.bibireden.data_attributes.config.entities.EntityTypeData import com.bibireden.data_attributes.config.entities.EntityTypeEntry import com.bibireden.data_attributes.ui.components.CollapsibleFoldableContainer -import com.bibireden.data_attributes.ui.components.buttons.ButtonComponents import com.bibireden.data_attributes.ui.components.config.AttributeConfigComponent import com.bibireden.data_attributes.ui.components.config.ConfigDockComponent -import com.bibireden.data_attributes.ui.components.config.function.AttributeFunctionComponent import com.bibireden.data_attributes.ui.components.fields.FieldComponents -import com.bibireden.data_attributes.ui.config.providers.EntityTypesProviderV2 +import com.bibireden.data_attributes.ui.config.providers.EntityTypesProvider import com.bibireden.data_attributes.ui.renderers.ButtonRenderers import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.SearchAnchorComponent import io.wispforest.owo.ui.component.Components import io.wispforest.owo.ui.component.LabelComponent -import io.wispforest.owo.ui.container.Containers import io.wispforest.owo.ui.container.FlowLayout import io.wispforest.owo.ui.core.Sizing -import io.wispforest.owo.ui.core.VerticalAlignment import net.minecraft.entity.EntityType -import net.minecraft.entity.attribute.EntityAttribute import net.minecraft.registry.Registries import net.minecraft.registry.Registry import net.minecraft.text.Text import net.minecraft.util.Identifier -class EntityTypesHeaderComponent(override var identifier: Identifier, private val entityTypes: MutableMap, private val provider: EntityTypesProviderV2) +class EntityTypesHeaderComponent(override var identifier: Identifier, private val entityTypes: MutableMap, private val provider: EntityTypesProvider) : CollapsibleFoldableContainer(Sizing.content(), Sizing.content(), Text.of(""), DataAttributesClient.UI_STATE.collapsible.entityTypeHeaders[identifier.toString()] ?: true), AttributeConfigComponent> { override val registry: Registry> = Registries.ENTITY_TYPE - override val isDefault: Boolean - get() = !provider.backing.containsKey(identifier) - private fun updateSearchAnchor() { childById(SearchAnchorComponent::class.java, "search-anchor")?.remove() child(SearchAnchorComponent(titleLayout(), Option.Key.ROOT, { identifier.toString() }, { Text.translatable(identifier.toTranslationKey()).toString() }).id("search-anchor")) } private fun updateTextLabel() { - titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, registry, { it.translationKey }, isDefault)) + titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, registry, { it.translationKey }, false)) } private fun createEntry(entryId: Identifier, entry: EntityTypeEntry): EntityTypesComponent = childById(EntityTypesComponent::class.java, "entry#$entryId") ?: EntityTypesComponent(entryId, identifier, entry, provider).also { it.id("entry#$entryId")}.also(::child) @@ -53,9 +44,6 @@ class EntityTypesHeaderComponent(override var identifier: Identifier, private va !isRegistered -> { titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.invalid")) } - isDefault -> { - titleLayout().tooltip(Text.translatable("text.config.data_attributes_data_entry.default")) - } } updateTextLabel() updateSearchAnchor() @@ -71,14 +59,7 @@ class EntityTypesHeaderComponent(override var identifier: Identifier, private va child( ConfigDockComponent(ConfigDockComponent.ConfigDefaultProperties({ _, _ -> provider.backing.remove(identifier) - - val entries = DataAttributesAPI.serverManager.defaults.types.entries[identifier] - - if (entries != null) { - forEachDescendant { if (it is EntityTypesComponent) { if (entries.containsKey(it.identifier)) it.update() else it.remove() } } - update() - } - else remove() + remove() }) { _, _ -> if (childById(FlowLayout::class.java, "edit-field") == null) { diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionComponent.kt index 926e0b7..7222353 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionComponent.kt @@ -1,16 +1,12 @@ package com.bibireden.data_attributes.ui.components.config.function import com.bibireden.data_attributes.DataAttributesClient -import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.api.attribute.StackingBehavior import com.bibireden.data_attributes.config.DataAttributesConfigProviders.registryEntryToText import com.bibireden.data_attributes.config.functions.AttributeFunction import com.bibireden.data_attributes.mutable.MutableEntityAttribute -import com.bibireden.data_attributes.ui.components.buttons.ButtonComponents import com.bibireden.data_attributes.ui.components.config.AttributeConfigComponent -import com.bibireden.data_attributes.ui.components.config.AttributeOverrideComponent import com.bibireden.data_attributes.ui.components.config.ConfigDockComponent -import com.bibireden.data_attributes.ui.components.config.entities.EntityTypesComponent import com.bibireden.data_attributes.ui.components.entries.DataEntryComponent import com.bibireden.data_attributes.ui.components.entries.EntryComponents import com.bibireden.data_attributes.ui.components.fields.FieldComponents @@ -19,7 +15,6 @@ import com.bibireden.data_attributes.ui.renderers.ButtonRenderers import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.ConfigToggleButton import io.wispforest.owo.config.ui.component.SearchAnchorComponent -import io.wispforest.owo.ui.component.ButtonComponent import io.wispforest.owo.ui.component.Components import io.wispforest.owo.ui.component.LabelComponent import io.wispforest.owo.ui.container.CollapsibleContainer @@ -33,7 +28,6 @@ import net.minecraft.registry.Registries import net.minecraft.registry.Registry import net.minecraft.text.Text import net.minecraft.util.Identifier -import java.util.concurrent.Flow class AttributeFunctionComponent(override var identifier: Identifier, private var function: AttributeFunction, private var parentId: Identifier, private val provider: AttributeFunctionProvider) : CollapsibleContainer(Sizing.content(), Sizing.content(), Text.of(""), DataAttributesClient.UI_STATE.collapsible.functionChildren[parentId.toString()]?.get(identifier.toString()) ?: true), @@ -44,8 +38,6 @@ class AttributeFunctionComponent(override var identifier: Identifier, private va private val backing = provider.backing - override val isDefault get() = provider.backing[parentId]?.get(identifier) == null - private fun updateEntryToBacking(id: Identifier, function: AttributeFunction) { backing.computeIfAbsent(parentId) { mutableMapOf() }[id] = function update() @@ -57,7 +49,7 @@ class AttributeFunctionComponent(override var identifier: Identifier, private va } private fun updateTextLabel() { - titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, isDefault)) + titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, false)) } private val toggleButton = ConfigToggleButton().enabled(function.enabled).also { @@ -84,9 +76,6 @@ class AttributeFunctionComponent(override var identifier: Identifier, private va !isRegistered -> { titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.invalid")) } - isDefault -> { - titleLayout().tooltip(Text.translatable("text.config.data_attributes_data_entry.default")) - } } updateTextLabel() updateSearchAnchor() @@ -105,13 +94,7 @@ class AttributeFunctionComponent(override var identifier: Identifier, private va child(ConfigDockComponent( ConfigDockComponent.ConfigDefaultProperties({ _, _ -> - val defaultEntry = DataAttributesAPI.serverManager.defaults.functions.entries[parentId]?.get(identifier) - if (defaultEntry != null) { - toggleButton.enabled(defaultEntry.enabled) - valueEntry.textbox.text = defaultEntry.value.toString() - updateStackingBehavior(defaultEntry.behavior) - } - else remove() + remove() backing[parentId]?.remove(identifier) != null diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionHeaderComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionHeaderComponent.kt index badecd6..eb7c751 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionHeaderComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionHeaderComponent.kt @@ -29,9 +29,6 @@ class AttributeFunctionHeaderComponent(override var identifier: Identifier, priv override val registry: Registry get() = Registries.ATTRIBUTE - override val isDefault: Boolean - get() = !provider.backing.containsKey(identifier) - private fun createEntry(childId: Identifier, function: AttributeFunction): AttributeFunctionComponent = childById(AttributeFunctionComponent::class.java, "child#$childId") ?: AttributeFunctionComponent(childId, function, identifier, provider).also { it.id("child#$childId") }.also(::child) private fun updateSearchAnchor() { @@ -40,7 +37,7 @@ class AttributeFunctionHeaderComponent(override var identifier: Identifier, priv } private fun updateTextLabel() { - titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, isDefault)) + titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, false)) } override fun update() { @@ -49,9 +46,6 @@ class AttributeFunctionHeaderComponent(override var identifier: Identifier, priv !isRegistered -> { titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.invalid")) } - isDefault -> { - titleLayout().tooltip(Text.translatable("text.config.data_attributes_data_entry.default")) - } } updateTextLabel() updateSearchAnchor() @@ -69,16 +63,7 @@ class AttributeFunctionHeaderComponent(override var identifier: Identifier, priv child( ConfigDockComponent(ConfigDockComponent.ConfigDefaultProperties({ _, _ -> provider.backing.remove(identifier) - - val entries = DataAttributesAPI.serverManager.defaults.functions.entries[identifier] - - if (entries != null) { - forEachDescendant { - if (it is AttributeFunctionComponent) { if (entries.containsKey(it.identifier)) it.update() else it.remove() } - } - update() - } - else remove() + remove() }) { _, _ -> if (childById(FlowLayout::class.java, "edit-field") == null) { diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeFunctionProvider.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeFunctionProvider.kt index 3e5333f..7a7ad00 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeFunctionProvider.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeFunctionProvider.kt @@ -32,15 +32,6 @@ class AttributeFunctionProvider(val option: Option) : F for ((id, entry) in backing) { child(AttributeFunctionHeaderComponent(id, entry, this).id(id.toString())) } - for ((id, entry) in DataAttributesAPI.serverManager.defaults.functions.entries) { - val component = childById(AttributeFunctionHeaderComponent::class.java, id.toString()) - if (component != null) { - component.addFunctions(entry) - } - else { - child(AttributeFunctionHeaderComponent(id, entry, this).id(id.toString())) - } - } } override fun isValid() = !this.option.detached() diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeOverrideProvider.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeOverrideProvider.kt index a96356a..312d044 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeOverrideProvider.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeOverrideProvider.kt @@ -2,14 +2,14 @@ package com.bibireden.data_attributes.ui.config.providers import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.config.models.OverridesConfigModel.AttributeOverride +import com.bibireden.data_attributes.identifier.Identifiers +import com.bibireden.data_attributes.ui.button.Buttons import com.bibireden.data_attributes.ui.components.config.AttributeOverrideComponent import com.bibireden.data_attributes.ui.renderers.ButtonRenderers import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.OptionValueProvider -import io.wispforest.owo.ui.component.Components import io.wispforest.owo.ui.container.FlowLayout import io.wispforest.owo.ui.core.* -import net.minecraft.text.Text import net.minecraft.util.Identifier class AttributeOverrideProvider(val option: Option>) : FlowLayout(Sizing.fill(100), Sizing.content(), Algorithm.VERTICAL), OptionValueProvider { @@ -22,21 +22,17 @@ class AttributeOverrideProvider(val option: Option - if (id !in backing) createOverrideEntry(id, override) - } } override fun isValid() = !this.option.detached() diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProvider.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProvider.kt index 0e71f34..244e5a2 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProvider.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProvider.kt @@ -1,248 +1,29 @@ package com.bibireden.data_attributes.ui.config.providers -import com.bibireden.data_attributes.api.DataAttributesAPI -import com.bibireden.data_attributes.config.DataAttributesConfigProviders.registryEntryToText -import com.bibireden.data_attributes.config.DataAttributesConfigProviders.textBoxComponent -import com.bibireden.data_attributes.config.Validators import com.bibireden.data_attributes.config.entities.EntityTypeData -import com.bibireden.data_attributes.config.entities.EntityTypeEntry -import com.bibireden.data_attributes.ext.round -import com.bibireden.data_attributes.ui.components.CollapsibleFoldableContainer -import com.bibireden.data_attributes.ui.components.buttons.ButtonComponents -import com.bibireden.data_attributes.ui.components.fields.FieldComponents -import com.bibireden.data_attributes.ui.renderers.ButtonRenderers +import com.bibireden.data_attributes.identifier.Identifiers +import com.bibireden.data_attributes.ui.button.Buttons +import com.bibireden.data_attributes.ui.components.config.entities.EntityTypesHeaderComponent import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.OptionValueProvider -import io.wispforest.owo.config.ui.component.SearchAnchorComponent -import io.wispforest.owo.ui.component.Components -import io.wispforest.owo.ui.container.CollapsibleContainer -import io.wispforest.owo.ui.container.Containers import io.wispforest.owo.ui.container.FlowLayout -import io.wispforest.owo.ui.core.Component import io.wispforest.owo.ui.core.Sizing -import io.wispforest.owo.ui.core.VerticalAlignment -import net.minecraft.entity.EntityType -import net.minecraft.entity.LivingEntity -import net.minecraft.entity.attribute.ClampedEntityAttribute -import net.minecraft.entity.attribute.DefaultAttributeRegistry -import net.minecraft.registry.Registries -import net.minecraft.text.Text import net.minecraft.util.Identifier class EntityTypesProvider(val option: Option>) : FlowLayout(Sizing.fill(100), Sizing.content(), Algorithm.VERTICAL), OptionValueProvider { - private val backing = HashMap(option.value()) - - private val headerComponents: MutableMap = mutableMapOf() - private val entryComponents: MutableMap = mutableMapOf() - - private fun createEntries(id: Identifier, types: Map, isDefault: Boolean = false): CollapsibleFoldableContainer { - val container = childById(CollapsibleFoldableContainer::class.java, id.toString()) - ?: CollapsibleFoldableContainer(Sizing.content(), Sizing.content(), registryEntryToText(id, Registries.ENTITY_TYPE, { it.translationKey }, isDefault), true) - .also { ct -> - ct.gap(4) - ct.id(id.toString()) - - ct.child(Containers.horizontalFlow(Sizing.fill(100), Sizing.fixed(15)) - .apply { - verticalAlignment(VerticalAlignment.CENTER) - gap(10) - id("dock") - } - .also { fl -> - if (!isDefault) { - fl.child(ButtonComponents.remove { backing.remove(id); refreshAndDisplayEntries(true) } - .renderer(ButtonRenderers.STANDARD)) - - fl.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.edit")) { - if (ct.childById(FlowLayout::class.java, "edit-field") == null) { - val field = FieldComponents.identifier( - { newId, _ -> - if (backing.containsKey(newId) || !Registries.ENTITY_TYPE.containsId(newId)) return@identifier - - backing.remove(id)?.let { backing[newId] = it } - refreshAndDisplayEntries(true) - }, - autocomplete = Registries.ENTITY_TYPE.ids - ) - - field.textBox.predicate = { it !in backing && Registries.ENTITY_TYPE.containsId(it) } - - ct.child(0, field) - } - } - .renderer(ButtonRenderers.STANDARD) - ) - } - - fl.child( - Components.button(Text.translatable("text.config.data_attributes.buttons.add")) { - val map = backing[id]?.data?.toMutableMap() ?: mutableMapOf() - map[Identifier("unknown")] = EntityTypeEntry() - backing[id] = EntityTypeData(map) - refreshAndDisplayEntries(true) - } - .renderer(ButtonRenderers.STANDARD) - ) - } - ) - - headerComponents[id] = ct - - child(SearchAnchorComponent(ct.titleLayout(), Option.Key.ROOT, id::toString, { Text.translatable(id.toTranslationKey()).toString() })) - - - if (id.toString() == "minecraft:unknown" && children.size > 1) child(1, ct) - else child(ct) - } - - for ((entryId, entry) in types) { - createEntry(entryId, entry, id, container, backing[id]?.data?.get(entryId) == null) - } - - return container - } - - private fun createEntry(id: Identifier, entityTypeEntry: EntityTypeEntry, parentId: Identifier, parent: CollapsibleContainer, isDefault: Boolean) { - if (parent.childById(CollapsibleContainer::class.java, id.toString()) != null) return - - Containers.collapsible(Sizing.content(), Sizing.content(), registryEntryToText(id, Registries.ATTRIBUTE, { it.translationKey }, isDefault), true).also { ct -> - ct.gap(4) - ct.id(id.toString()) - - // find fallback - try { - entityTypeEntry.fallback = Registries.ENTITY_TYPE.get(parentId)?.let { entityType -> - val defaultContainer = DefaultAttributeRegistry.get(entityType as EntityType) - Registries.ATTRIBUTE.get(id)?.let(defaultContainer::getBaseValue) - }?.round(2) - } - catch (_: IllegalArgumentException) { - entityTypeEntry.fallback = 0.0 - } - - if (!isDefault) { - ct.child(Containers.horizontalFlow(Sizing.fill(100), Sizing.fixed(15)) - .apply { - verticalAlignment(VerticalAlignment.BOTTOM) - gap(10) - } - .also { fl -> - fl.child(ButtonComponents.remove { - val entry = backing[parentId]?.data?.toMutableMap() ?: return@remove - entry.remove(id) - backing[parentId] = EntityTypeData(entry) - refreshAndDisplayEntries(true) - } - .renderer(ButtonRenderers.STANDARD)) - - fl.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.edit")) { - if (ct.childById(FlowLayout::class.java, "edit-field") == null) { - val field = FieldComponents.identifier( - { newId, _ -> - val entry = backing[parentId]?.data?.toMutableMap() ?: return@identifier - if (entry.containsKey(newId) || !Registries.ATTRIBUTE.containsId(newId)) return@identifier - - entry[newId] = entry.remove(id) ?: return@identifier - backing[parentId] = EntityTypeData(entry) - - refreshAndDisplayEntries(true) - }, - autocomplete = Registries.ATTRIBUTE.ids - ) - - field.textBox.predicate = { backing[parentId]?.data?.get(it) == null && Registries.ATTRIBUTE.containsId(it) } - - ct.child(0, field) - } - } - .renderer(ButtonRenderers.STANDARD) - ) - } - ) - } - - ct.child(textBoxComponent( - Text.translatable("text.config.data_attributes.data_entry.entity_types.value"), - entityTypeEntry.value, - Validators::isNumeric, - onChange = { - it.toDoubleOrNull()?.let { value -> - val data = this.backing.remove(parentId) ?: EntityTypeData() - val mapping = data.data.toMutableMap() - mapping[id] = entityTypeEntry.copy(value = value) - this.backing[parentId] = data.copy(data = mapping) - - if (isDefault) refreshAndDisplayEntries(true) - } - } - ).apply { - val attribute = Registries.ATTRIBUTE[id] as? ClampedEntityAttribute ?: return@apply - tooltip(Text.translatable("text.config.data_attributes.data_entry.entity_type_value", id, attribute.minValue, attribute.maxValue)) - }) - - val fallback = entityTypeEntry.fallback - if (fallback != null) { - ct.child(textBoxComponent( - Text.translatable("text.config.data_attributes.data_entry.fallback"), - fallback, - Validators::isNumeric, - )) - } - - if (isDefault) { - ct.titleLayout().tooltip(Text.translatable("text.config.data_attributes_data_entry.default")) - } - - ct.child(SearchAnchorComponent(ct.titleLayout(), Option.Key.ROOT, id::toString, { Text.translatable(id.toTranslationKey()).toString() })) - - entryComponents[id] = ct - - if (id.toString() == "minecraft:unknown" && parent.children().size > 1) parent.child(1, ct) - else parent.child(ct) - } - - // force a rearrangement to bring the dock up top~ - parent.childById(FlowLayout::class.java, "dock")?.let { - parent.removeChild(it) - parent.child(0, it) - } - } - - private fun refreshAndDisplayEntries(clearHeaders: Boolean = false) { - if (clearHeaders) { - headerComponents.values.forEach { component -> - component.id(null) - component.remove() - } - headerComponents.clear() - } - entryComponents.values.forEach { component -> - component.id(null) - component.remove() - } - entryComponents.clear() - - for ((id, types) in backing) { - createEntries(id, types.data, false) - } - - for ((id, types) in DataAttributesAPI.serverManager.defaults.types.entries) { - createEntries(id, types, id !in backing) - } - } + val backing = option.value().toMutableMap() init { - child( - Components.button(Text.translatable("text.config.data_attributes.buttons.add")) { - backing[Identifier("unknown")] = EntityTypeData() - refreshAndDisplayEntries(true) - } - .renderer(ButtonRenderers.STANDARD) - .horizontalSizing(Sizing.content()) - .verticalSizing(Sizing.fixed(20)) - ) - - refreshAndDisplayEntries() + child(Buttons.add { + val identifier = Identifiers.unknown() + val entry = EntityTypeData() + backing[identifier] = entry + child(EntityTypesHeaderComponent(identifier, entry.data.toMutableMap(), this).id(id.toString())) + }) + + for ((id, entry) in backing) { + child(EntityTypesHeaderComponent(id, entry.data.toMutableMap(), this).id(id.toString())) + } } override fun isValid() = !this.option.detached() diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProviderV2.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProviderV2.kt deleted file mode 100644 index 961943c..0000000 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProviderV2.kt +++ /dev/null @@ -1,33 +0,0 @@ -package com.bibireden.data_attributes.ui.config.providers - -import com.bibireden.data_attributes.api.DataAttributesAPI -import com.bibireden.data_attributes.config.entities.EntityTypeData -import com.bibireden.data_attributes.ui.components.config.entities.EntityTypesComponent -import com.bibireden.data_attributes.ui.components.config.entities.EntityTypesHeaderComponent -import io.wispforest.owo.config.Option -import io.wispforest.owo.config.ui.component.OptionValueProvider -import io.wispforest.owo.ui.container.FlowLayout -import io.wispforest.owo.ui.core.Sizing -import net.minecraft.util.Identifier - -class EntityTypesProviderV2(val option: Option>) : FlowLayout(Sizing.fill(100), Sizing.content(), Algorithm.VERTICAL), OptionValueProvider { - val backing = option.value().toMutableMap() - - init { - for ((id, entry) in backing) { - child(EntityTypesHeaderComponent(id, entry.data.toMutableMap(), this).id(id.toString())) - } - for ((id, entry) in DataAttributesAPI.serverManager.defaults.types.entries) { - val component = childById(EntityTypesHeaderComponent::class.java, id.toString()) - if (component != null) { - component.addEntityTypes(entry) - } - else { - child(EntityTypesHeaderComponent(id, entry, this).id(id.toString())) - } - } - } - - override fun isValid() = !this.option.detached() - override fun parsedValue() = backing -} \ No newline at end of file From 86b1012be0edc3ca27bc8affc3f5f1392f7c5e1e Mon Sep 17 00:00:00 2001 From: Bibi Reden Date: Sun, 25 May 2025 09:40:29 -0500 Subject: [PATCH 2/2] [feat] partition ui to have readonly entries --- .../config/DataAttributesConfigProviders.kt | 4 +- .../config/models/ConfigModel.kt | 1 + .../config/AttributeOverrideComponent.kt | 118 ++++++++++-------- .../config/entities/EntityTypesComponent.kt | 8 +- .../entities/EntityTypesHeaderComponent.kt | 96 +++++++------- .../function/AttributeFunctionComponent.kt | 59 ++++----- .../AttributeFunctionHeaderComponent.kt | 86 ++++++------- .../components/entries/DataEntryComponent.kt | 7 +- .../ui/components/labels/LabelComponents.kt | 15 +++ .../providers/AttributeFunctionProvider.kt | 14 ++- .../providers/AttributeOverrideProvider.kt | 18 ++- .../config/providers/EntityTypesProvider.kt | 17 ++- .../ui/options/UIAttributeComponentOptions.kt | 3 + .../assets/data_attributes/lang/en_us.json | 8 +- 14 files changed, 268 insertions(+), 186 deletions(-) create mode 100644 src/main/kotlin/com/bibireden/data_attributes/ui/components/labels/LabelComponents.kt create mode 100644 src/main/kotlin/com/bibireden/data_attributes/ui/options/UIAttributeComponentOptions.kt diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/DataAttributesConfigProviders.kt b/src/main/kotlin/com/bibireden/data_attributes/config/DataAttributesConfigProviders.kt index 640fbc4..a2cb03a 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/DataAttributesConfigProviders.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/DataAttributesConfigProviders.kt @@ -17,12 +17,12 @@ import net.minecraft.text.Text import net.minecraft.util.Identifier object DataAttributesConfigProviders { - fun registryEntryToText(id: Identifier, registry: Registry, representation: (T) -> String, isDefault: Boolean = false): MutableText { + fun registryEntryToText(id: Identifier, registry: Registry, representation: (T) -> String, isReadonly: Boolean = false): MutableText { val entry = registry[id] val text = Text.empty() if (entry != null) { text.append(Text.translatable(representation(entry)).append(" ")) - .setStyle(Style.EMPTY.withColor(0xE7C14B)) + .setStyle(Style.EMPTY.withColor(if (isReadonly) 0x65bde3 else 0xE7C14B)) } text.append(Text.literal("($id)").also { t -> t.setStyle( diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/models/ConfigModel.kt b/src/main/kotlin/com/bibireden/data_attributes/config/models/ConfigModel.kt index 85d7530..3c8174a 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/models/ConfigModel.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/models/ConfigModel.kt @@ -4,6 +4,7 @@ import com.bibireden.data_attributes.DataAttributes import io.wispforest.owo.config.Option.SyncMode import io.wispforest.owo.config.annotation.Config import io.wispforest.owo.config.annotation.Sync +import net.minecraft.util.Identifier @Suppress("UNUSED") @Config(name = DataAttributes.MOD_ID, wrapperName = "DataAttributesConfig") diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeOverrideComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeOverrideComponent.kt index 197813c..0dce32e 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeOverrideComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/AttributeOverrideComponent.kt @@ -1,7 +1,6 @@ package com.bibireden.data_attributes.ui.components.config import com.bibireden.data_attributes.DataAttributesClient -import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.api.attribute.AttributeFormat import com.bibireden.data_attributes.api.attribute.StackingFormula import com.bibireden.data_attributes.config.DataAttributesConfigProviders.registryEntryToText @@ -12,7 +11,6 @@ import com.bibireden.data_attributes.ui.components.entries.DataEntryComponent import com.bibireden.data_attributes.ui.components.entries.EntryComponents import com.bibireden.data_attributes.ui.components.fields.EditFieldComponent import com.bibireden.data_attributes.ui.components.fields.FieldComponents -import com.bibireden.data_attributes.ui.config.providers.AttributeOverrideProvider import com.bibireden.data_attributes.ui.renderers.ButtonRenderers import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.ConfigToggleButton @@ -21,6 +19,7 @@ import io.wispforest.owo.ui.component.Components import io.wispforest.owo.ui.component.LabelComponent import io.wispforest.owo.ui.container.CollapsibleContainer import io.wispforest.owo.ui.container.Containers +import io.wispforest.owo.ui.container.FlowLayout import io.wispforest.owo.ui.core.Positioning import io.wispforest.owo.ui.core.Sizing import io.wispforest.owo.ui.core.VerticalAlignment @@ -33,8 +32,10 @@ class AttributeOverrideComponent( var identifier: Identifier, private var override: AttributeOverride, private val backing: MutableMap, - private val provider: AttributeOverrideProvider + private val options: Options ) : CollapsibleContainer(Sizing.content(), Sizing.content(), Text.of(""), DataAttributesClient.UI_STATE.collapsible.overrides[identifier.toString()] ?: true) { + data class Options(val isReadonly: Boolean) + private val attribute: MutableEntityAttribute? get() = Registries.ATTRIBUTE[identifier] @@ -47,6 +48,11 @@ class AttributeOverrideComponent( private fun replaceEntry(id: Identifier, override: AttributeOverride) { identifier = id + + if (!this.backing.containsKey(id)) { + (parent as FlowLayout).child(1, AttributeOverrideComponent(id, override, backing, Options(isReadonly = false))) + } + this.backing[id] = override } @@ -69,7 +75,7 @@ class AttributeOverrideComponent( dataEntryMaxFallback?.textbox?.setPlaceholder(Text.of(override.max_fallback.toString())) } - this.titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, false)) + this.titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, options.isReadonly)) titleLayout().tooltip(null) @@ -77,6 +83,9 @@ class AttributeOverrideComponent( !isRegistered() -> { titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.invalid")) } + options.isReadonly -> { + titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.readonly")) + } } } @@ -89,58 +98,61 @@ class AttributeOverrideComponent( update() - child(Containers.horizontalFlow(Sizing.fill(100), Sizing.fixed(15)).also { content -> - content.verticalAlignment(VerticalAlignment.BOTTOM) - content.gap(10) - - content.child(ConfigToggleButton().also { button -> - button.enabled(override.enabled) - button.onPress { changeAttributeOverride(override.copy(enabled = !override.enabled)) } - button.renderer(ButtonRenderers.STANDARD) - }) - - content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.reset")) - { - changeAttributeOverride(override.copy( - min = attribute?.`data_attributes$min_fallback`() ?: override.min_fallback, - max = attribute?.`data_attributes$max_fallback`() ?: override.max_fallback, - smoothness = 1.0, - formula = StackingFormula.Flat, - format = AttributeFormat.Whole - )) - } - .renderer(ButtonRenderers.STANDARD) - ) + if (!options.isReadonly) { + child(Containers.horizontalFlow(Sizing.fill(100), Sizing.fixed(15)).also { content -> + content.verticalAlignment(VerticalAlignment.BOTTOM) + + content.gap(10) + + content.child(ConfigToggleButton().also { button -> + button.enabled(override.enabled) + button.onPress { changeAttributeOverride(override.copy(enabled = !override.enabled)) } + button.renderer(ButtonRenderers.STANDARD) + }) + + content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.reset")) + { + changeAttributeOverride(override.copy( + min = attribute?.`data_attributes$min_fallback`() ?: override.min_fallback, + max = attribute?.`data_attributes$max_fallback`() ?: override.max_fallback, + smoothness = 1.0, + formula = StackingFormula.Flat, + format = AttributeFormat.Whole + )) + } + .renderer(ButtonRenderers.STANDARD) + ) - content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.edit")) { - if (this.childById(EditFieldComponent::class.java, "edit-field") != null) return@button + content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.edit")) { + if (this.childById(EditFieldComponent::class.java, "edit-field") != null) return@button - val field = FieldComponents.identifier( - { newId, _ -> - if (newId in backing || !Registries.ATTRIBUTE.containsId(newId)) return@identifier + val field = FieldComponents.identifier( + { newId, _ -> + if (newId in backing || !Registries.ATTRIBUTE.containsId(newId)) return@identifier - this.backing.remove(identifier) - replaceEntry(newId, override) - update() - }, - autocomplete = Registries.ATTRIBUTE.ids - ).apply { id("edit-field") } + this.backing.remove(identifier) + replaceEntry(newId, override) + update() + }, + autocomplete = Registries.ATTRIBUTE.ids + ).apply { id("edit-field") } - field.textBox.predicate = { id -> id !in backing && Registries.ATTRIBUTE.containsId(id) } + field.textBox.predicate = { id -> id !in backing && Registries.ATTRIBUTE.containsId(id) } - this.child(0, field) - } - .renderer(ButtonRenderers.STANDARD) - ) + this.child(0, field) + } + .renderer(ButtonRenderers.STANDARD) + ) - content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.remove")) { - this.backing.remove(identifier) + content.child(Components.button(Text.translatable("text.config.data_attributes.data_entry.remove")) { + this.backing.remove(identifier) - remove() - } - .renderer(ButtonRenderers.STANDARD) - ) - }) + remove() + } + .renderer(ButtonRenderers.STANDARD) + ) + }) + } dataEntryMin = EntryComponents.double(Text.translatable("$stub.min"), DataEntryComponent.Properties({ changeAttributeOverride(override.copy(min = it)) }), override.min.toString()) .also(::child) @@ -154,10 +166,12 @@ class AttributeOverrideComponent( verticalAlignment(VerticalAlignment.CENTER) gap(8) child(Components.label(Text.translatable("text.config.data_attributes.data_entry.overrides.smoothness")) - .sizing(Sizing.content(), Sizing.fixed(20)) + .verticalTextAlignment(VerticalAlignment.CENTER) + .sizing(Sizing.content(), Sizing.fill(100)) + .positioning(Positioning.relative(0, 50)) ) child(AttributeConfigComponents.smoothnessSlider(override) { changeAttributeOverride(override.copy(smoothness = max(it.value().round(2), 0.001))) } - .positioning(Positioning.relative(100, 0)) + .positioning(Positioning.relative(100, 50)) ) }.id("smoothness")) @@ -166,6 +180,7 @@ class AttributeOverrideComponent( hf.gap(8) hf.child( Components.label(Text.translatable("text.config.data_attributes.data_entry.overrides.formula")) + .verticalTextAlignment(VerticalAlignment.CENTER) .sizing(Sizing.content(), Sizing.fixed(20)) ) hf.child( @@ -184,6 +199,7 @@ class AttributeOverrideComponent( hf.gap(8) hf.child( Components.label(Text.translatable("text.config.data_attributes.data_entry.overrides.format")) + .verticalTextAlignment(VerticalAlignment.CENTER) .sizing(Sizing.content(), Sizing.fixed(20)) ) hf.child( diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesComponent.kt index e7d5f07..29ef473 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesComponent.kt @@ -13,6 +13,7 @@ import com.bibireden.data_attributes.ui.components.entries.DataEntryComponent import com.bibireden.data_attributes.ui.components.entries.EntryComponents import com.bibireden.data_attributes.ui.components.fields.FieldComponents import com.bibireden.data_attributes.ui.config.providers.EntityTypesProvider +import com.bibireden.data_attributes.ui.options.UIAttributeComponentOptions import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.SearchAnchorComponent import io.wispforest.owo.ui.component.LabelComponent @@ -29,7 +30,7 @@ import net.minecraft.registry.Registry import net.minecraft.text.Text import net.minecraft.util.Identifier -class EntityTypesComponent(override var identifier: Identifier, private var parentId: Identifier, private var entry: EntityTypeEntry, private val provider: EntityTypesProvider) +class EntityTypesComponent(override var identifier: Identifier, private var parentId: Identifier, private var entry: EntityTypeEntry, private val provider: EntityTypesProvider, private val options: UIAttributeComponentOptions) : CollapsibleContainer(Sizing.content(), Sizing.content(), Text.of(""), DataAttributesClient.UI_STATE.collapsible.entityTypeEntries[parentId.toString()]?.get(identifier.toString()) ?: true), AttributeConfigComponent { override val registry: Registry = Registries.ATTRIBUTE @@ -40,7 +41,7 @@ class EntityTypesComponent(override var identifier: Identifier, private var pare } private fun updateTextLabel() { - titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, registry, { it.translationKey }, false)) + titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, registry, { it.translationKey }, options.isReadonly)) } override fun update() { @@ -48,6 +49,9 @@ class EntityTypesComponent(override var identifier: Identifier, private var pare when { !isRegistered -> titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.invalid")) + options.isReadonly -> { + titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.readonly")) + } } // find fallback diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesHeaderComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesHeaderComponent.kt index d2e7ebf..17f98df 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesHeaderComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/entities/EntityTypesHeaderComponent.kt @@ -9,6 +9,7 @@ import com.bibireden.data_attributes.ui.components.config.AttributeConfigCompone import com.bibireden.data_attributes.ui.components.config.ConfigDockComponent import com.bibireden.data_attributes.ui.components.fields.FieldComponents import com.bibireden.data_attributes.ui.config.providers.EntityTypesProvider +import com.bibireden.data_attributes.ui.options.UIAttributeComponentOptions import com.bibireden.data_attributes.ui.renderers.ButtonRenderers import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.SearchAnchorComponent @@ -22,7 +23,7 @@ import net.minecraft.registry.Registry import net.minecraft.text.Text import net.minecraft.util.Identifier -class EntityTypesHeaderComponent(override var identifier: Identifier, private val entityTypes: MutableMap, private val provider: EntityTypesProvider) +class EntityTypesHeaderComponent(override var identifier: Identifier, private val entityTypes: MutableMap, private val provider: EntityTypesProvider, private val options: UIAttributeComponentOptions) : CollapsibleFoldableContainer(Sizing.content(), Sizing.content(), Text.of(""), DataAttributesClient.UI_STATE.collapsible.entityTypeHeaders[identifier.toString()] ?: true), AttributeConfigComponent> { override val registry: Registry> = Registries.ENTITY_TYPE @@ -33,10 +34,10 @@ class EntityTypesHeaderComponent(override var identifier: Identifier, private va } private fun updateTextLabel() { - titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, registry, { it.translationKey }, false)) + titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, registry, { it.translationKey }, options.isReadonly)) } - private fun createEntry(entryId: Identifier, entry: EntityTypeEntry): EntityTypesComponent = childById(EntityTypesComponent::class.java, "entry#$entryId") ?: EntityTypesComponent(entryId, identifier, entry, provider).also { it.id("entry#$entryId")}.also(::child) + private fun createEntry(entryId: Identifier, entry: EntityTypeEntry): EntityTypesComponent = childById(EntityTypesComponent::class.java, "entry#$entryId") ?: EntityTypesComponent(entryId, identifier, entry, provider, options).also { it.id("entry#$entryId")}.also(::child) override fun update() { titleLayout().tooltip(null) @@ -44,6 +45,9 @@ class EntityTypesHeaderComponent(override var identifier: Identifier, private va !isRegistered -> { titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.invalid")) } + options.isReadonly -> { + titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.readonly")) + } } updateTextLabel() updateSearchAnchor() @@ -56,49 +60,51 @@ class EntityTypesHeaderComponent(override var identifier: Identifier, private va init { onToggled().subscribe { DataAttributesClient.UI_STATE.collapsible.entityTypeHeaders[identifier.toString()] = it } - child( - ConfigDockComponent(ConfigDockComponent.ConfigDefaultProperties({ _, _ -> - provider.backing.remove(identifier) - remove() - }) - { _, _ -> - if (childById(FlowLayout::class.java, "edit-field") == null) { - val field = FieldComponents.identifier( - { newId, _ -> - if (provider.backing.containsKey(newId) || !registry.containsId(newId)) return@identifier - - provider.backing.remove(identifier)?.let { provider.backing[newId] = it } - - identifier = newId - - children().filterIsInstance().forEach { it.updateParent(identifier) } - - update() - }, - autocomplete = registry.ids - ) - - field.textBox.predicate = { provider.backing[identifier]?.data?.get(it) == null && registry.containsId(it) } - - child(0, field) - } - }).child( - Components.button(Text.translatable("text.config.data_attributes.buttons.add")) { - val map = provider.backing[identifier]?.data?.toMutableMap() ?: mutableMapOf() - val childId = Identifier("unknown") - val entry = EntityTypeEntry() - map[childId] = entry - provider.backing[identifier] = EntityTypeData(map) - - child(1, EntityTypesComponent(childId, identifier, entry, provider)) - - update() - } - .renderer(ButtonRenderers.STANDARD) - .horizontalSizing(Sizing.content()) - .verticalSizing(Sizing.fixed(20)) + if (!options.isReadonly) { + child( + ConfigDockComponent(ConfigDockComponent.ConfigDefaultProperties({ _, _ -> + provider.backing.remove(identifier) + remove() + }) + { _, _ -> + if (childById(FlowLayout::class.java, "edit-field") == null) { + val field = FieldComponents.identifier( + { newId, _ -> + if (provider.backing.containsKey(newId) || !registry.containsId(newId)) return@identifier + + provider.backing.remove(identifier)?.let { provider.backing[newId] = it } + + identifier = newId + + children().filterIsInstance().forEach { it.updateParent(identifier) } + + update() + }, + autocomplete = registry.ids + ) + + field.textBox.predicate = { provider.backing[identifier]?.data?.get(it) == null && registry.containsId(it) } + + child(0, field) + } + }).child( + Components.button(Text.translatable("text.config.data_attributes.buttons.add")) { + val map = provider.backing[identifier]?.data?.toMutableMap() ?: mutableMapOf() + val childId = Identifier("unknown") + val entry = EntityTypeEntry() + map[childId] = entry + provider.backing[identifier] = EntityTypeData(map) + + child(1, EntityTypesComponent(childId, identifier, entry, provider, options)) + + update() + } + .renderer(ButtonRenderers.STANDARD) + .horizontalSizing(Sizing.content()) + .verticalSizing(Sizing.fixed(20)) + ) ) - ) + } addEntityTypes(this.entityTypes) diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionComponent.kt index 7222353..33583d2 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionComponent.kt @@ -11,6 +11,7 @@ import com.bibireden.data_attributes.ui.components.entries.DataEntryComponent import com.bibireden.data_attributes.ui.components.entries.EntryComponents import com.bibireden.data_attributes.ui.components.fields.FieldComponents import com.bibireden.data_attributes.ui.config.providers.AttributeFunctionProvider +import com.bibireden.data_attributes.ui.options.UIAttributeComponentOptions import com.bibireden.data_attributes.ui.renderers.ButtonRenderers import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.ConfigToggleButton @@ -29,7 +30,7 @@ import net.minecraft.registry.Registry import net.minecraft.text.Text import net.minecraft.util.Identifier -class AttributeFunctionComponent(override var identifier: Identifier, private var function: AttributeFunction, private var parentId: Identifier, private val provider: AttributeFunctionProvider) +class AttributeFunctionComponent(override var identifier: Identifier, private var function: AttributeFunction, private var parentId: Identifier, private val provider: AttributeFunctionProvider, private val options: UIAttributeComponentOptions) : CollapsibleContainer(Sizing.content(), Sizing.content(), Text.of(""), DataAttributesClient.UI_STATE.collapsible.functionChildren[parentId.toString()]?.get(identifier.toString()) ?: true), AttributeConfigComponent { @@ -49,7 +50,7 @@ class AttributeFunctionComponent(override var identifier: Identifier, private va } private fun updateTextLabel() { - titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, false)) + titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, options.isReadonly)) } private val toggleButton = ConfigToggleButton().enabled(function.enabled).also { @@ -92,41 +93,43 @@ class AttributeFunctionComponent(override var identifier: Identifier, private va init { onToggled().subscribe { DataAttributesClient.UI_STATE.collapsible.functionChildren.computeIfAbsent(parentId.toString()) { mutableMapOf() }[identifier.toString()] = it } - child(ConfigDockComponent( - ConfigDockComponent.ConfigDefaultProperties({ _, _ -> - remove() + if (!options.isReadonly) { + child(ConfigDockComponent( + ConfigDockComponent.ConfigDefaultProperties({ _, _ -> + remove() - backing[parentId]?.remove(identifier) != null + backing[parentId]?.remove(identifier) != null - update() - }) - { dc, _ -> - if (dc.childById(FlowLayout::class.java, "edit-field") == null && backing[parentId]?.get(identifier) != null) { - val field = FieldComponents.identifier( - { newId, _ -> - val entry = backing.computeIfAbsent(parentId) { mutableMapOf() } - if (!registry.containsId(newId) || entry[newId] != null) return@identifier + update() + }) + { dc, _ -> + if (dc.childById(FlowLayout::class.java, "edit-field") == null && backing[parentId]?.get(identifier) != null) { + val field = FieldComponents.identifier( + { newId, _ -> + val entry = backing.computeIfAbsent(parentId) { mutableMapOf() } + if (!registry.containsId(newId) || entry[newId] != null) return@identifier - entry[newId] = entry.remove(identifier) ?: return@identifier - backing[parentId] = entry + entry[newId] = entry.remove(identifier) ?: return@identifier + backing[parentId] = entry - identifier = newId + identifier = newId - for (fc in children().filterIsInstance()) { fc.updateParent(identifier) } + for (fc in children().filterIsInstance()) { fc.updateParent(identifier) } - update() - }, - autocomplete = Registries.ATTRIBUTE.ids - ) + update() + }, + autocomplete = Registries.ATTRIBUTE.ids + ) - field.textBox.predicate = { backing[parentId]?.get(it) == null && Registries.ATTRIBUTE.containsId(it) } + field.textBox.predicate = { backing[parentId]?.get(it) == null && Registries.ATTRIBUTE.containsId(it) } - child(0, field) + child(0, field) + } } - } - ).apply { - child(0, toggleButton) - }) + ).apply { + child(0, toggleButton) + }) + } valueEntry.also(::child) diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionHeaderComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionHeaderComponent.kt index eb7c751..6615ad4 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionHeaderComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/config/function/AttributeFunctionHeaderComponent.kt @@ -1,35 +1,32 @@ package com.bibireden.data_attributes.ui.components.config.function import com.bibireden.data_attributes.DataAttributesClient -import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.config.DataAttributesConfigProviders.registryEntryToText import com.bibireden.data_attributes.config.functions.AttributeFunction import com.bibireden.data_attributes.ui.components.CollapsibleFoldableContainer -import com.bibireden.data_attributes.ui.components.buttons.ButtonComponents import com.bibireden.data_attributes.ui.components.config.AttributeConfigComponent import com.bibireden.data_attributes.ui.components.config.ConfigDockComponent import com.bibireden.data_attributes.ui.components.fields.FieldComponents import com.bibireden.data_attributes.ui.config.providers.AttributeFunctionProvider +import com.bibireden.data_attributes.ui.options.UIAttributeComponentOptions import com.bibireden.data_attributes.ui.renderers.ButtonRenderers import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.SearchAnchorComponent import io.wispforest.owo.ui.component.Components import io.wispforest.owo.ui.component.LabelComponent -import io.wispforest.owo.ui.container.Containers import io.wispforest.owo.ui.container.FlowLayout import io.wispforest.owo.ui.core.Sizing -import io.wispforest.owo.ui.core.VerticalAlignment import net.minecraft.entity.attribute.EntityAttribute import net.minecraft.registry.Registries import net.minecraft.registry.Registry import net.minecraft.text.Text import net.minecraft.util.Identifier -class AttributeFunctionHeaderComponent(override var identifier: Identifier, private val functions: MutableMap, private val provider: AttributeFunctionProvider) : CollapsibleFoldableContainer(Sizing.content(), Sizing.content(), Text.of(""), DataAttributesClient.UI_STATE.collapsible.functionParents[identifier.toString()] ?: true), AttributeConfigComponent { +class AttributeFunctionHeaderComponent(override var identifier: Identifier, private val functions: MutableMap, private val provider: AttributeFunctionProvider, private val options: UIAttributeComponentOptions) : CollapsibleFoldableContainer(Sizing.content(), Sizing.content(), Text.of(""), DataAttributesClient.UI_STATE.collapsible.functionParents[identifier.toString()] ?: true), AttributeConfigComponent { override val registry: Registry get() = Registries.ATTRIBUTE - private fun createEntry(childId: Identifier, function: AttributeFunction): AttributeFunctionComponent = childById(AttributeFunctionComponent::class.java, "child#$childId") ?: AttributeFunctionComponent(childId, function, identifier, provider).also { it.id("child#$childId") }.also(::child) + private fun createEntry(childId: Identifier, function: AttributeFunction): AttributeFunctionComponent = childById(AttributeFunctionComponent::class.java, "child#$childId") ?: AttributeFunctionComponent(childId, function, identifier, provider, options).also { it.id("child#$childId") }.also(::child) private fun updateSearchAnchor() { childById(SearchAnchorComponent::class.java, "search-anchor")?.remove() @@ -37,7 +34,7 @@ class AttributeFunctionHeaderComponent(override var identifier: Identifier, priv } private fun updateTextLabel() { - titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, false)) + titleLayout().children().filterIsInstance().first().text(registryEntryToText(identifier, Registries.ATTRIBUTE, { it.translationKey }, options.isReadonly)) } override fun update() { @@ -46,12 +43,15 @@ class AttributeFunctionHeaderComponent(override var identifier: Identifier, priv !isRegistered -> { titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.invalid")) } + options.isReadonly -> { + titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.readonly")) + } } updateTextLabel() updateSearchAnchor() } - fun addFunctions(functions: MutableMap) { + private fun addFunctions(functions: MutableMap) { for ((id, function) in functions) createEntry(id, function) } @@ -60,52 +60,54 @@ class AttributeFunctionHeaderComponent(override var identifier: Identifier, priv update() - child( - ConfigDockComponent(ConfigDockComponent.ConfigDefaultProperties({ _, _ -> - provider.backing.remove(identifier) - remove() - }) - { _, _ -> - if (childById(FlowLayout::class.java, "edit-field") == null) { - val field = FieldComponents.identifier( - { newId, _ -> - if (provider.backing.containsKey(newId) || !registry.containsId(newId)) return@identifier + if (!options.isReadonly) { + child( + ConfigDockComponent(ConfigDockComponent.ConfigDefaultProperties({ _, _ -> + provider.backing.remove(identifier) + remove() + }) + { _, _ -> + if (childById(FlowLayout::class.java, "edit-field") == null) { + val field = FieldComponents.identifier( + { newId, _ -> + if (provider.backing.containsKey(newId) || !registry.containsId(newId)) return@identifier - provider.backing.remove(identifier)?.let { provider.backing[newId] = it } + provider.backing.remove(identifier)?.let { provider.backing[newId] = it } - identifier = newId + identifier = newId - for (afc in children().filterIsInstance()) { afc.updateParent(identifier) } + for (afc in children().filterIsInstance()) { afc.updateParent(identifier) } - update() - }, - autocomplete = registry.ids - ) + update() + }, + autocomplete = registry.ids + ) - field.textBox.predicate = { provider.backing[identifier]?.get(it) == null && registry.containsId(it) } + field.textBox.predicate = { provider.backing[identifier]?.get(it) == null && registry.containsId(it) } - child(0, field) - } - }).child( - Components.button(Text.translatable("text.config.data_attributes.buttons.add")) { - val entries = provider.backing.computeIfAbsent(identifier) { mutableMapOf() } + child(0, field) + } + }).child( + Components.button(Text.translatable("text.config.data_attributes.buttons.add")) { + val entries = provider.backing.computeIfAbsent(identifier) { mutableMapOf() } - val childId = Identifier("unknown") - val function = AttributeFunction() + val childId = Identifier("unknown") + val function = AttributeFunction() - entries[childId] = function + entries[childId] = function - provider.backing[identifier] = entries + provider.backing[identifier] = entries - child(2, AttributeFunctionComponent(childId, function, identifier, provider)) + child(2, AttributeFunctionComponent(childId, function, identifier, provider, options)) - update() - } - .renderer(ButtonRenderers.STANDARD) - .horizontalSizing(Sizing.content()) - .verticalSizing(Sizing.fixed(20)) + update() + } + .renderer(ButtonRenderers.STANDARD) + .horizontalSizing(Sizing.content()) + .verticalSizing(Sizing.fixed(20)) + ) ) - ) + } addFunctions(this.functions) } diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/entries/DataEntryComponent.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/entries/DataEntryComponent.kt index 24497dd..f41b24c 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/components/entries/DataEntryComponent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/entries/DataEntryComponent.kt @@ -5,10 +5,7 @@ import com.bibireden.data_attributes.ui.colors.ColorCodes import com.bibireden.data_attributes.ui.components.boxes.ParsedTextBoxComponent import io.wispforest.owo.ui.component.Components import io.wispforest.owo.ui.container.FlowLayout -import io.wispforest.owo.ui.core.CursorStyle -import io.wispforest.owo.ui.core.Positioning -import io.wispforest.owo.ui.core.Sizing -import io.wispforest.owo.ui.core.VerticalAlignment +import io.wispforest.owo.ui.core.* import net.minecraft.text.Text import java.util.function.Consumer @@ -51,7 +48,7 @@ class DataEntryComponent(label: Text, val parser: Parser, properti verticalAlignment(VerticalAlignment.CENTER) gap(6) - child(Components.label(label).sizing(Sizing.content(), Sizing.fixed(20))) + child(Components.label(label).verticalTextAlignment(VerticalAlignment.CENTER).sizing(Sizing.content(), Sizing.content())) child(textbox) diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/components/labels/LabelComponents.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/components/labels/LabelComponents.kt new file mode 100644 index 0000000..d19a2fb --- /dev/null +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/components/labels/LabelComponents.kt @@ -0,0 +1,15 @@ +package com.bibireden.data_attributes.ui.components.labels + +import io.wispforest.owo.ui.component.Components +import io.wispforest.owo.ui.component.LabelComponent +import io.wispforest.owo.ui.core.HorizontalAlignment +import io.wispforest.owo.ui.core.Sizing +import net.minecraft.text.Style +import net.minecraft.text.Text + +object LabelComponents { + fun header(text: Text): LabelComponent = Components.label(text.copy().setStyle(Style.EMPTY.withBold(true))).apply { + horizontalTextAlignment(HorizontalAlignment.CENTER) + horizontalSizing(Sizing.fill(100)) + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeFunctionProvider.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeFunctionProvider.kt index 7a7ad00..304014b 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeFunctionProvider.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeFunctionProvider.kt @@ -4,6 +4,8 @@ import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.config.functions.AttributeFunction import com.bibireden.data_attributes.config.functions.AttributeFunctionConfig import com.bibireden.data_attributes.ui.components.config.function.AttributeFunctionHeaderComponent +import com.bibireden.data_attributes.ui.components.labels.LabelComponents +import com.bibireden.data_attributes.ui.options.UIAttributeComponentOptions import com.bibireden.data_attributes.ui.renderers.ButtonRenderers import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.OptionValueProvider @@ -22,7 +24,7 @@ class AttributeFunctionProvider(val option: Option) : F val id = Identifier("unknown") val entry = mutableMapOf() backing[id] = entry - child(1, AttributeFunctionHeaderComponent(id, entry,this)) + child(1, AttributeFunctionHeaderComponent(id, entry,this, UIAttributeComponentOptions(isReadonly = false))) } .renderer(ButtonRenderers.STANDARD) .horizontalSizing(Sizing.content()) @@ -30,7 +32,15 @@ class AttributeFunctionProvider(val option: Option) : F ) for ((id, entry) in backing) { - child(AttributeFunctionHeaderComponent(id, entry, this).id(id.toString())) + child(AttributeFunctionHeaderComponent(id, entry, this, UIAttributeComponentOptions(isReadonly = false)).id(id.toString())) + } + + DataAttributesAPI.serverManager.defaults.forEach { (rid, cache) -> + child(LabelComponents.header(Text.literal("<< ${rid.namespace} >>"))) + + cache.functions.entries.forEach { (id, functions) -> + child(AttributeFunctionHeaderComponent(id, functions, this, UIAttributeComponentOptions(isReadonly = true)).id(id.toString())) + } } } diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeOverrideProvider.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeOverrideProvider.kt index 312d044..ec516c2 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeOverrideProvider.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/AttributeOverrideProvider.kt @@ -5,11 +5,15 @@ import com.bibireden.data_attributes.config.models.OverridesConfigModel.Attribut import com.bibireden.data_attributes.identifier.Identifiers import com.bibireden.data_attributes.ui.button.Buttons import com.bibireden.data_attributes.ui.components.config.AttributeOverrideComponent -import com.bibireden.data_attributes.ui.renderers.ButtonRenderers +import com.bibireden.data_attributes.ui.components.labels.LabelComponents import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.OptionValueProvider +import io.wispforest.owo.ui.component.Components +import io.wispforest.owo.ui.component.LabelComponent import io.wispforest.owo.ui.container.FlowLayout import io.wispforest.owo.ui.core.* +import net.minecraft.text.Style +import net.minecraft.text.Text import net.minecraft.util.Identifier class AttributeOverrideProvider(val option: Option>) : FlowLayout(Sizing.fill(100), Sizing.content(), Algorithm.VERTICAL), OptionValueProvider { @@ -17,7 +21,7 @@ class AttributeOverrideProvider(val option: Option + child(LabelComponents.header(Text.literal("<< ${rid.namespace} >>"))) + + cache.overrides.entries.forEach { (id, override) -> + child(AttributeOverrideComponent(id, override, backing, AttributeOverrideComponent.Options(isReadonly = true))) + } + } } override fun isValid() = !this.option.detached() diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProvider.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProvider.kt index 244e5a2..e9ce038 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProvider.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/config/providers/EntityTypesProvider.kt @@ -1,13 +1,18 @@ package com.bibireden.data_attributes.ui.config.providers +import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.config.entities.EntityTypeData import com.bibireden.data_attributes.identifier.Identifiers import com.bibireden.data_attributes.ui.button.Buttons import com.bibireden.data_attributes.ui.components.config.entities.EntityTypesHeaderComponent +import com.bibireden.data_attributes.ui.components.config.function.AttributeFunctionHeaderComponent +import com.bibireden.data_attributes.ui.components.labels.LabelComponents +import com.bibireden.data_attributes.ui.options.UIAttributeComponentOptions import io.wispforest.owo.config.Option import io.wispforest.owo.config.ui.component.OptionValueProvider import io.wispforest.owo.ui.container.FlowLayout import io.wispforest.owo.ui.core.Sizing +import net.minecraft.text.Text import net.minecraft.util.Identifier class EntityTypesProvider(val option: Option>) : FlowLayout(Sizing.fill(100), Sizing.content(), Algorithm.VERTICAL), OptionValueProvider { @@ -18,11 +23,19 @@ class EntityTypesProvider(val option: Option>) : val identifier = Identifiers.unknown() val entry = EntityTypeData() backing[identifier] = entry - child(EntityTypesHeaderComponent(identifier, entry.data.toMutableMap(), this).id(id.toString())) + child(EntityTypesHeaderComponent(identifier, entry.data.toMutableMap(), this, UIAttributeComponentOptions(isReadonly = false)).id(id.toString())) }) for ((id, entry) in backing) { - child(EntityTypesHeaderComponent(id, entry.data.toMutableMap(), this).id(id.toString())) + child(EntityTypesHeaderComponent(id, entry.data.toMutableMap(), this, UIAttributeComponentOptions(isReadonly = false)).id(id.toString())) + } + + DataAttributesAPI.serverManager.defaults.forEach { (rid, cache) -> + child(LabelComponents.header(Text.literal("<< ${rid.namespace} >>"))) + + cache.types.entries.forEach { (id, types) -> + child(EntityTypesHeaderComponent(id, types, this, UIAttributeComponentOptions(isReadonly = true)).id(id.toString())) + } } } diff --git a/src/main/kotlin/com/bibireden/data_attributes/ui/options/UIAttributeComponentOptions.kt b/src/main/kotlin/com/bibireden/data_attributes/ui/options/UIAttributeComponentOptions.kt new file mode 100644 index 0000000..28f10d6 --- /dev/null +++ b/src/main/kotlin/com/bibireden/data_attributes/ui/options/UIAttributeComponentOptions.kt @@ -0,0 +1,3 @@ +package com.bibireden.data_attributes.ui.options + +data class UIAttributeComponentOptions(val isReadonly: Boolean) \ No newline at end of file diff --git a/src/main/resources/assets/data_attributes/lang/en_us.json b/src/main/resources/assets/data_attributes/lang/en_us.json index be0f92c..ffb9b79 100644 --- a/src/main/resources/assets/data_attributes/lang/en_us.json +++ b/src/main/resources/assets/data_attributes/lang/en_us.json @@ -144,10 +144,10 @@ {"text": "this field when ready, or replace the config entry in the file.", "italic": true, "color": "gray"} ], - "text.config.data_attributes_data_entry.default": [ - {"text": "✱ ", "color": "#84de56"}, - {"text": "Default Entry\n\n", "color": "white"}, - {"text": "This entry is from another mod or datapack, and can be overrided by editing it.", "color": "white"} + "text.config.data_attributes.data_entry.readonly": [ + {"text": "✱ Readonly Entry", "color": "#65bde3"}, + {"text": "\n\n", "color": "white"}, + {"text": "This entry is from another mod or datapack, and will be overrided by any config setting above it.", "color": "white"} ], "text.config.data_attributes.buttons.add": [