Skip to content

Commit

Permalink
[feat/semver] Stage new beta and add all ui changes
Browse files Browse the repository at this point in the history
  • Loading branch information
bibi-reden committed Nov 25, 2024
1 parent b82a84b commit d9d91a1
Show file tree
Hide file tree
Showing 14 changed files with 517 additions and 394 deletions.
7 changes: 5 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
## Fixes 🍋
- Fixed attribute functions not being able to be edited (and that were default).
## Additions 🍎
- Added saved state for collapsed entries (session based, saved until game relaunch)
## Changes 🍐
- Applied a different method to updating UI components.
- Most entries sync, but there is still some work to do, so it will stay as beta until the rest of the issues are figured out.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ loom_version=1.8-SNAPSHOT
minecraft_version=1.20.1
fabric_kotlin_version=1.11.0+kotlin.2.0.0
fabric_api_version=0.92.2+1.20.1
mod_version=2.0.2+1.20.1
mod_version=2.0.3+1.20.1-beta.1
loader=fabric

# Mappings
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ data class ConfigUIState(val collapsible: Collapsible = Collapsible()) {
val overrides: MutableMap<String, Boolean> = mutableMapOf(),
val functionParents: MutableMap<String, Boolean> = mutableMapOf(),
val functionChildren: MutableMap<String, MutableMap<String, Boolean>> = mutableMapOf(),
val entityTypes: MutableMap<String, Boolean> = mutableMapOf()
val entityTypeHeaders: MutableMap<String, Boolean> = mutableMapOf(),
val entityTypeEntries: MutableMap<String, MutableMap<String, Boolean>> = mutableMapOf()
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ package com.bibireden.data_attributes.config

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.AttributeFunctionProviderV2
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
Expand Down Expand Up @@ -40,11 +40,11 @@ object DataAttributesConfigProviders {
}

val ATTRIBUTE_FUNCTIONS_FACTORY = OptionComponentFactory { _, option ->
return@OptionComponentFactory AttributeFunctionProviderV2(option).let { OptionComponentFactory.Result(it, it) }
return@OptionComponentFactory AttributeFunctionProvider(option).let { OptionComponentFactory.Result(it, it) }
}

val ENTITY_TYPES_FACTORY = OptionComponentFactory { _, option ->
return@OptionComponentFactory EntityTypesProvider(option).let { OptionComponentFactory.Result(it, it) }
return@OptionComponentFactory EntityTypesProviderV2(option).let { OptionComponentFactory.Result(it, it) }
}

fun textBoxComponent(txt: Text, obj: Any, predicate: Predicate<String>? = null, onChange: ((String) -> Unit)? = null, textBoxID: String? = null): FlowLayout {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,6 @@ interface AttributeConfigComponent<T> {
/** If the given entry is currently registered. */
val isRegistered: Boolean
get() = registryEntry != null

fun update()
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,11 +75,13 @@ class AttributeOverrideComponent(

titleLayout().tooltip(null)

if (!isRegistered()) {
titleLayout().tooltip(Text.translatable("text.config.data_attributes.data_entry.invalid"))
}
else if (isDefault()) {
titleLayout().tooltip(Text.translatable("text.config.data_attributes_data_entry.default"))
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"))
}
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.bibireden.data_attributes.ui.components.config

import com.bibireden.data_attributes.ui.components.buttons.ButtonComponents
import com.bibireden.data_attributes.ui.renderers.ButtonRenderers
import io.wispforest.owo.ui.component.ButtonComponent
import io.wispforest.owo.ui.component.Components
import io.wispforest.owo.ui.container.FlowLayout
import io.wispforest.owo.ui.core.Sizing
import io.wispforest.owo.ui.core.VerticalAlignment
import net.minecraft.text.Text
import org.jetbrains.annotations.ApiStatus

@ApiStatus.Internal
@Suppress("UnstableApiUsage")
class ConfigDockComponent(private val defaultProperties: ConfigDefaultProperties) : FlowLayout(Sizing.fill(100), Sizing.fixed(15), Algorithm.HORIZONTAL) {
class ConfigDefaultProperties(val onRemoveToggled: (ConfigDockComponent, ButtonComponent) -> Unit, val onEditToggled: (ConfigDockComponent, ButtonComponent) -> Unit)

init {
verticalAlignment(VerticalAlignment.BOTTOM)
gap(10)
id("dock")

child(ButtonComponents.remove { defaultProperties.onRemoveToggled(this, it) }
.renderer(ButtonRenderers.STANDARD))
child(Components.button(Text.translatable("text.config.data_attributes.data_entry.edit")) { defaultProperties.onEditToggled(this, it) }
.renderer(ButtonRenderers.STANDARD))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
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 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
import net.minecraft.entity.attribute.DefaultAttributeRegistry
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 EntityTypesComponent(override var identifier: Identifier, private var parentId: Identifier, private var entry: EntityTypeEntry, private val provider: EntityTypesProviderV2)
: CollapsibleContainer(Sizing.content(), Sizing.content(), Text.of("<n/a>"), DataAttributesClient.UI_STATE.collapsible.entityTypeEntries[parentId.toString()]?.get(identifier.toString()) ?: true), AttributeConfigComponent<EntityAttribute> {

override val registry: Registry<EntityAttribute> = 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<LabelComponent>().first().text(registryEntryToText(identifier, registry, { it.translationKey }, isDefault))
}

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
try {
entry.fallback = Registries.ENTITY_TYPE.get(parentId)
?.let { entityType -> registry.get(identifier)?.let(DefaultAttributeRegistry.get(entityType as EntityType<LivingEntity>)::getBaseValue) }
?.round(2)
}
catch (_: IllegalArgumentException) {
entry.fallback = 0.0
}

val fallback = entry.fallback
if (fallback != null) {
childById(FlowLayout::class.java, "fallback")?.remove()
child(textBoxComponent(Text.translatable("text.config.data_attributes.data_entry.fallback"), fallback, Validators::isNumeric).id("fallback"))
}

updateTextLabel()
updateSearchAnchor()
}


private val valueEntry: DataEntryComponent<Double> = EntryComponents.double(Text.translatable("text.config.data_attributes.data_entry.entity_types.value"), DataEntryComponent.Properties({ updateEntryToBacking(entry.copy(value = it)) }), entry.value.toString()).also {
val attribute = registryEntry
if (attribute is ClampedEntityAttribute) {
it.tooltip(Text.translatable("text.config.data_attributes.data_entry.entity_type_value", identifier, attribute.minValue, attribute.maxValue))
}
}

private fun updateEntryToBacking(entry: EntityTypeEntry) {
val etd = provider.backing[parentId] ?: return
val mapping = etd.data.toMutableMap()
mapping[identifier] = entry
provider.backing[parentId] = EntityTypeData(mapping)

update()
}

fun updateParent(parentId: Identifier) { this.parentId = parentId }


init {
onToggled().subscribe { DataAttributesClient.UI_STATE.collapsible.entityTypeEntries.computeIfAbsent(parentId.toString()) { mutableMapOf() } [identifier.toString()] = it }

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()

provider.backing[parentId] = EntityTypeData(entry)

update()
}
}, {_, _ ->
if (childById(FlowLayout::class.java, "edit-field") == null) {
val field = FieldComponents.identifier(
{ newId, _ ->
val entry = provider.backing[parentId]?.data?.toMutableMap() ?: return@identifier
if (entry.containsKey(newId) || !registry.containsId(newId)) return@identifier

entry[newId] = entry.remove(identifier) ?: return@identifier
provider.backing[parentId] = EntityTypeData(entry)

identifier = newId

update()
},
autocomplete = Registries.ATTRIBUTE.ids
)

field.textBox.predicate = { provider.backing[parentId]?.data?.get(it) == null && registry.containsId(it) }

child(0, field)
}
}
)))

valueEntry.also(::child)

update()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
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.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<Identifier, EntityTypeEntry>, private val provider: EntityTypesProviderV2)
: CollapsibleFoldableContainer(Sizing.content(), Sizing.content(), Text.of("<n/a>"), DataAttributesClient.UI_STATE.collapsible.entityTypeHeaders[identifier.toString()] ?: true), AttributeConfigComponent<EntityType<*>> {

override val registry: Registry<EntityType<*>> = 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<LabelComponent>().first().text(registryEntryToText(identifier, registry, { it.translationKey }, isDefault))
}

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)

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"))
}
}
updateTextLabel()
updateSearchAnchor()
}

fun addEntityTypes(entityTypes: MutableMap<Identifier, EntityTypeEntry>) {
for ((id, types) in entityTypes) createEntry(id, types)
}

init {
onToggled().subscribe { DataAttributesClient.UI_STATE.collapsible.entityTypeHeaders[identifier.toString()] = it }

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()
})
{ _, _ ->
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<EntityTypesComponent>().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))
)
)

addEntityTypes(this.entityTypes)

update()
}
}
Loading

0 comments on commit d9d91a1

Please sign in to comment.