diff --git a/.github/workflows/build-and-deploy.yml b/.github/workflows/build-and-deploy.yml index 612294f..47505dc 100644 --- a/.github/workflows/build-and-deploy.yml +++ b/.github/workflows/build-and-deploy.yml @@ -71,4 +71,4 @@ jobs: changelog-file: CHANGELOG.md game-versions: "${{ steps.minecraft_version.outputs.minecraft_version }}" - java: "${{ matrix.java }}" + java: "${{ matrix.java }}" \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d4fe27..6b0df7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,2 +1,10 @@ -## Changes ⚙️ -- Now using `WrapMethod` on computation of modifier(s) to avoid unneeded recalculation. \ No newline at end of file +## Additions 🍎 +- Implemented a feature that reads data-packs and applies attribute modifications to the world based on order. + - More documentation on this feature will come as the mod stabilizes. + - For now, if you want to be aware of how to format your data-pack(s), look towards the source code of the next builds of PlayerEX/WizardEX. +## Changes 🌽 +- Changed how configs and modded entries are applied. + - Your config will appear sparse on startup, but when you go to a world (in an integrated server), it will show the extra modifications provided by loaded packs and mods. + - You can overwrite these, and they will appear in your actual config. Your config will **overwrite** any data-pack or modded pack. + - The UI will be overhauled to better assist in knowing what is supplied by datapacks/mods, but that will be in the later future. +- Deprecated the `DefaultAttributeRegistry` to keep previous versions functional, but it will be removed before release. \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index aa25f5d..5ab2b00 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,6 +1,7 @@ plugins { id("fabric-loom") kotlin("jvm") version "2.0.0" + kotlin("plugin.serialization") version "2.0.0" java `maven-publish` id("com.google.devtools.ksp") version "2.0.0-1.0.21" @@ -23,6 +24,8 @@ repositories { maven("https://maven.terraformersmc.com") maven("https://api.modrinth.com/maven") maven("https://maven.kosmx.dev/") + maven("https://maven.parchmentmc.org") + maven("https://maven.quiltmc.org/repository/release/") } dependencies { @@ -30,6 +33,14 @@ dependencies { mappings("net.fabricmc:yarn:${properties["yarn_mappings"]}:v2") +// mappings { +// loom.layered { +// mappings("org.quiltmc:quilt-mappings:${properties["minecraft_version"]}+build.${properties["quilt_mappings_version"]}:intermediary-v2") +// officialMojangMappings() +// parchment("org.parchmentmc.data:parchment-${properties["parchment_version"]}@zip") +// } +// } + modImplementation("net.fabricmc:fabric-loader:${properties["loader_version"]}") modImplementation("net.fabricmc:fabric-language-kotlin:${properties["fabric_kotlin_version"]}") modImplementation("net.fabricmc.fabric-api:fabric-api:${properties["fabric_api_version"]}") diff --git a/gradle.properties b/gradle.properties index 35b291d..4ffbfbf 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,4 +1,8 @@ +org.gradle.jvmargs=-Xmx4000m +org.gradle.parallel=true + kotlin.code.style=official + ksp_version=2.0.0-1.0.21 kotlinpoet_version=1.17.0 @@ -7,12 +11,16 @@ maven_group=com.bibireden.data_attributes loom_version=1.7-SNAPSHOT minecraft_version=1.20.1 -fabric_kotlin_version=1.11.0+kotlin.2.0.0 +fabric_kotlin_version=1.12.0+kotlin.2.0.10 fabric_api_version=0.92.2+1.20.1 -mod_version=2.0.0-beta.8+1.20.1 +mod_version=2.0.0+1.20.1-beta.9 loader=fabric +# Mappings +parchment_version=1.20.1:2023.09.03 +quilt_mappings_version=23 yarn_mappings=1.20.1+build.10 + loader_version=0.15.11 modmenu_version=7.2.2 @@ -24,6 +32,3 @@ endec_version=0.1.7 endec_netty_version=0.1.3 mixinextras_version=0.5.0-beta.1 - -org.gradle.jvmargs=-Xmx4000m -org.gradle.parallel=true diff --git a/src/main/java/com/bibireden/data_attributes/api/attribute/IEntityAttribute.java b/src/main/java/com/bibireden/data_attributes/api/attribute/IEntityAttribute.java index 7633967..8e849a9 100644 --- a/src/main/java/com/bibireden/data_attributes/api/attribute/IEntityAttribute.java +++ b/src/main/java/com/bibireden/data_attributes/api/attribute/IEntityAttribute.java @@ -1,7 +1,9 @@ package com.bibireden.data_attributes.api.attribute; import com.bibireden.data_attributes.config.functions.AttributeFunction; +import org.apache.commons.lang3.NotImplementedException; +import java.util.HashMap; import java.util.Map; /** @@ -15,36 +17,36 @@ public interface IEntityAttribute { /** * @return The minimum value of the attribute. */ - double data_attributes$min(); + default Double data_attributes$min() { return null; } /** * @return The maximum value of the attribute. */ - double data_attributes$max(); + default Double data_attributes$max() { return null; } /** Returns the intended minimum fallback of this attribute. */ - double data_attributes$min_fallback(); + default Double data_attributes$min_fallback() { return null; } /** Returns the intended maximum fallback of this attribute. */ - double data_attributes$max_fallback(); /** Returns the intended maximum fallback of this attribute. */ + default Double data_attributes$max_fallback() { return null; } /** Returns the smoothness of this attribute. */ - double data_attributes$smoothness(); + default Double data_attributes$smoothness() { return null; } /** * @return The attribute's {@link StackingFormula}. */ - StackingFormula data_attributes$formula(); + default StackingFormula data_attributes$formula() { return null; } /** * @return An immutable map of the function-parents attached to this attribute. * @since 1.4.0 */ - Map data_attributes$parents(); + default Map data_attributes$parents() { return null; } /** * @return An immutable map of the function-children attached to this attribute. * @since 1.4.0 */ - Map data_attributes$children(); + default Map data_attributes$children() { return null; } } diff --git a/src/main/java/com/bibireden/data_attributes/api/attribute/IEntityAttributeInstance.java b/src/main/java/com/bibireden/data_attributes/api/attribute/IEntityAttributeInstance.java index 7a51bb5..95acea2 100644 --- a/src/main/java/com/bibireden/data_attributes/api/attribute/IEntityAttributeInstance.java +++ b/src/main/java/com/bibireden/data_attributes/api/attribute/IEntityAttributeInstance.java @@ -15,5 +15,5 @@ public interface IEntityAttributeInstance { * @param uuid The uuid of the modifier. * @param value The value to change the modifier to. */ - void updateModifier(final UUID uuid, final double value); + default void data_attributes$updateModifier(final UUID uuid, final double value) {} } diff --git a/src/main/java/com/bibireden/data_attributes/api/event/EntityAttributeModifiedEvents.java b/src/main/java/com/bibireden/data_attributes/api/event/EntityAttributeModifiedEvents.java index 1f98b2d..29e78f9 100644 --- a/src/main/java/com/bibireden/data_attributes/api/event/EntityAttributeModifiedEvents.java +++ b/src/main/java/com/bibireden/data_attributes/api/event/EntityAttributeModifiedEvents.java @@ -29,7 +29,7 @@ public final class EntityAttributeModifiedEvents { /** * Fired after the attribute instance value was calculated, but before it was output. This offers one last chance to alter the - * value in some way (for example round a decimal to an integer). + * value in some way (for example, rounding a decimal to an integer). */ public static final Event CLAMPED = EventFactory.createArrayBacked(Clamped.class, callbacks -> (attribute, value) -> { double cache = value; diff --git a/src/main/java/com/bibireden/data_attributes/mixin/AttributeContainerMixin.java b/src/main/java/com/bibireden/data_attributes/mixin/AttributeContainerMixin.java index 87d877a..2094ac8 100644 --- a/src/main/java/com/bibireden/data_attributes/mixin/AttributeContainerMixin.java +++ b/src/main/java/com/bibireden/data_attributes/mixin/AttributeContainerMixin.java @@ -19,7 +19,6 @@ import com.bibireden.data_attributes.api.event.EntityAttributeModifiedEvents; import com.bibireden.data_attributes.mutable.MutableAttributeContainer; -import com.bibireden.data_attributes.mutable.MutableAttributeInstance; import com.google.common.collect.Multimap; import net.minecraft.entity.LivingEntity; @@ -53,7 +52,7 @@ private void updateTrackedStatus(EntityAttributeInstance instance) {} @Inject(method = "updateTrackedStatus", at = @At("HEAD"), cancellable = true) private void data_attributes$updateTrackedStatus(EntityAttributeInstance instance, CallbackInfo ci) { - Identifier identifier = ((MutableAttributeInstance) instance).data_attributes$get_id(); + Identifier identifier = instance.data_attributes$get_id(); if (identifier != null) { this.data_attributes$tracked.put(identifier, instance); } @@ -74,16 +73,15 @@ private void updateTrackedStatus(EntityAttributeInstance instance) {} Identifier identifier = Registries.ATTRIBUTE.getId(attribute2); if (identifier == null) return original; - EntityAttributeInstance entityAttributeInstance = this.data_attributes$custom.computeIfAbsent(identifier, id -> this.fallback.createOverride(this::updateTrackedStatus, attribute2)); - if (entityAttributeInstance != null) { - MutableAttributeInstance mutable = (MutableAttributeInstance) entityAttributeInstance; - mutable.data_attributes$setContainerCallback((AttributeContainer) (Object) this); - if (mutable.data_attributes$get_id() == null) { - mutable.data_attributes$updateId(identifier); + EntityAttributeInstance instance = this.data_attributes$custom.computeIfAbsent(identifier, id -> this.fallback.createOverride(this::updateTrackedStatus, attribute2)); + if (instance != null) { + instance.data_attributes$setContainerCallback((AttributeContainer) (Object) this); + if (instance.data_attributes$get_id() == null) { + instance.data_attributes$updateId(identifier); } } - return entityAttributeInstance; + return instance; } @ModifyReturnValue(method = "hasAttribute(Lnet/minecraft/entity/attribute/EntityAttribute;)Z", at = @At("RETURN")) @@ -136,7 +134,7 @@ private void updateTrackedStatus(EntityAttributeInstance instance) {} @Inject(method = "setFrom", at = @At("HEAD"), cancellable = true) private void data_attributes$setFrom(AttributeContainer other, CallbackInfo ci) { - ((MutableAttributeContainer) other).data_attributes$custom().values().forEach(attributeInstance -> { + other.data_attributes$custom().values().forEach(attributeInstance -> { EntityAttribute entityAttribute = attributeInstance.getAttribute(); EntityAttributeInstance entityAttributeInstance = this.getCustomInstance(entityAttribute); @@ -177,9 +175,7 @@ private void updateTrackedStatus(EntityAttributeInstance instance) {} @Override public void data_attributes$refresh() { - for (EntityAttributeInstance instance : this.data_attributes$custom.values()) { - ((MutableAttributeInstance) instance).data_attributes$refresh(); - } + this.data_attributes$custom.values().forEach(EntityAttributeInstance::data_attributes$refresh); } @Override diff --git a/src/main/java/com/bibireden/data_attributes/mixin/ClampedEntityAttributeMixin.java b/src/main/java/com/bibireden/data_attributes/mixin/ClampedEntityAttributeMixin.java index f4d86a4..ffa05fe 100644 --- a/src/main/java/com/bibireden/data_attributes/mixin/ClampedEntityAttributeMixin.java +++ b/src/main/java/com/bibireden/data_attributes/mixin/ClampedEntityAttributeMixin.java @@ -1,6 +1,6 @@ package com.bibireden.data_attributes.mixin; -import com.bibireden.data_attributes.config.models.OverridesConfigModel; +import com.bibireden.data_attributes.config.models.OverridesConfigModel.AttributeOverride; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import com.llamalad7.mixinextras.sugar.Local; import org.spongepowered.asm.mixin.Final; @@ -26,7 +26,7 @@ abstract class ClampedEntityAttributeMixin extends EntityAttributeMixin { @Inject(method = "", at = @At("TAIL")) private void data_attributes$init(String translationKey, double fallback, double min, double max, CallbackInfo ci) { - this.data_attributes$override(new OverridesConfigModel.AttributeOverride(false, minValue, maxValue, min, max, 0.0, StackingFormula.Flat)); + this.data_attributes$override(new AttributeOverride(false, minValue, maxValue, min, max, 0.0, StackingFormula.Flat)); } @ModifyReturnValue(method = "getMinValue", at = @At("RETURN")) @@ -45,17 +45,15 @@ abstract class ClampedEntityAttributeMixin extends EntityAttributeMixin { } @Override - public double data_attributes$smoothness() { return this.data_attributes$smoothness; } + public Double data_attributes$smoothness() { return this.data_attributes$smoothness; } @Override - public double data_attributes$min_fallback() { + public Double data_attributes$min_fallback() { return this.minValue; } @Override - public double data_attributes$max_fallback() { - return this.maxValue; - } + public Double data_attributes$max_fallback() { return this.maxValue; } @Override public void data_attributes$clear() { diff --git a/src/main/java/com/bibireden/data_attributes/mixin/EntityAttributeInstanceMixin.java b/src/main/java/com/bibireden/data_attributes/mixin/EntityAttributeInstanceMixin.java index 7a3f0bc..c9035f2 100644 --- a/src/main/java/com/bibireden/data_attributes/mixin/EntityAttributeInstanceMixin.java +++ b/src/main/java/com/bibireden/data_attributes/mixin/EntityAttributeInstanceMixin.java @@ -6,8 +6,6 @@ import com.llamalad7.mixinextras.injector.ModifyExpressionValue; import com.llamalad7.mixinextras.injector.ModifyReturnValue; -import com.llamalad7.mixinextras.injector.wrapmethod.WrapMethod; -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; @@ -23,10 +21,7 @@ import com.bibireden.data_attributes.api.attribute.StackingFormula; import com.bibireden.data_attributes.api.event.EntityAttributeModifiedEvents; import com.bibireden.data_attributes.api.util.VoidConsumer; -import com.bibireden.data_attributes.mutable.MutableAttributeContainer; import com.bibireden.data_attributes.mutable.MutableAttributeInstance; -import com.bibireden.data_attributes.mutable.MutableAttributeModifier; -import com.bibireden.data_attributes.mutable.MutableEntityAttribute; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.attribute.AttributeContainer; @@ -35,6 +30,7 @@ import net.minecraft.entity.attribute.EntityAttributeModifier; import net.minecraft.util.Identifier; import net.minecraft.registry.Registries; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; @Mixin(EntityAttributeInstance.class) abstract class EntityAttributeInstanceMixin implements MutableAttributeInstance, IEntityAttributeInstance { @@ -84,13 +80,13 @@ protected void onUpdate() {} } @SuppressWarnings("UnreachableCode") - @WrapMethod(method = "computeValue") - private double data_attributes$computeValue(Operation original) { - MutableEntityAttribute attribute = (MutableEntityAttribute) this.getAttribute(); + @Inject(method = "computeValue", at = @At("HEAD"), cancellable = true) + private void data_attributes$computeValue(CallbackInfoReturnable cir) { + EntityAttribute attribute = this.getAttribute(); StackingFormula formula = attribute.data_attributes$formula(); - // If the formula is set to Flat and there is no associated container, provide original. - if (formula == StackingFormula.Flat && this.data_attributes$container == null) return original.call(); + // If the formula is set to Flat and there is no associated container, drop out early. + if (formula == StackingFormula.Flat && this.data_attributes$container == null) return; AtomicReference k = new AtomicReference<>(0.0D); AtomicReference v = new AtomicReference<>(0.0D); @@ -158,12 +154,11 @@ protected void onUpdate() {} }); } - return ((EntityAttribute) attribute).clamp(e.get()); + cir.setReturnValue(attribute.clamp(e.get())); } @Inject(method = "addModifier", at = @At("HEAD"), cancellable = true) private void data_attributes$addModifier(EntityAttributeModifier modifier, CallbackInfo ci) { - EntityAttributeInstance instance = (EntityAttributeInstance) (Object) this; UUID key = modifier.getId(); EntityAttributeModifier entityAttributeModifier = this.idToModifiers.get(key); @@ -173,8 +168,8 @@ protected void onUpdate() {} this.data_attributes$actionModifier( () -> { this.idToModifiers.put(key, modifier); - instance.getModifiers(modifier.getOperation()).add(modifier); - }, instance, modifier, true + this.getModifiers(modifier.getOperation()).add(modifier); + }, (EntityAttributeInstance) (Object) this, modifier, true ); } @@ -211,10 +206,9 @@ protected void onUpdate() {} public void data_attributes$actionModifier(final VoidConsumer consumerIn, final EntityAttributeInstance instanceIn, final EntityAttributeModifier modifierIn, final boolean isWasAdded) { if (this.data_attributes$container == null) return; - EntityAttribute parentAttribute = this.getAttribute(); - MutableEntityAttribute mutableParentAttribute = (MutableEntityAttribute) this.getAttribute(); + EntityAttribute parent = this.getAttribute(); - for (IEntityAttribute child : mutableParentAttribute.data_attributes$childrenMutable().keySet()) { + for (IEntityAttribute child : parent.data_attributes$childrenMutable().keySet()) { EntityAttributeInstance instance = this.data_attributes$container.getCustomInstance((EntityAttribute) child); if (instance != null) instance.getValue(); } @@ -225,14 +219,14 @@ protected void onUpdate() {} this.onUpdate(); - LivingEntity livingEntity = ((MutableAttributeContainer) this.data_attributes$container).data_attributes$getLivingEntity(); + LivingEntity livingEntity = this.data_attributes$container.data_attributes$getLivingEntity(); - EntityAttributeModifiedEvents.MODIFIED.invoker().onModified(parentAttribute, livingEntity, modifierIn, value, isWasAdded); + EntityAttributeModifiedEvents.MODIFIED.invoker().onModified(parent, livingEntity, modifierIn, value, isWasAdded); - for (IEntityAttribute child : mutableParentAttribute.data_attributes$childrenMutable().keySet()) { + for (IEntityAttribute child : parent.data_attributes$childrenMutable().keySet()) { EntityAttributeInstance instance = this.data_attributes$container.getCustomInstance((EntityAttribute) child); if (instance != null) { - ((MutableAttributeInstance) instance).data_attributes$actionModifier(() -> {}, instance, modifierIn, isWasAdded); + instance.data_attributes$actionModifier(() -> {}, instance, modifierIn, isWasAdded); } } } @@ -248,11 +242,11 @@ protected void onUpdate() {} } @Override - public void updateModifier(final UUID uuid, final double value) { + public void data_attributes$updateModifier(final UUID uuid, final double value) { EntityAttributeModifier modifier = this.getModifier(uuid); if (modifier == null) return; - this.data_attributes$actionModifier(() -> ((MutableAttributeModifier) modifier).data_attributes$updateValue(value), (EntityAttributeInstance) (Object) this, modifier, false); + this.data_attributes$actionModifier(() -> modifier.data_attributes$updateValue(value), (EntityAttributeInstance) (Object) this, modifier, false); } @Override diff --git a/src/main/java/com/bibireden/data_attributes/mixin/EntityAttributeMixin.java b/src/main/java/com/bibireden/data_attributes/mixin/EntityAttributeMixin.java index a70761f..2e6ca51 100644 --- a/src/main/java/com/bibireden/data_attributes/mixin/EntityAttributeMixin.java +++ b/src/main/java/com/bibireden/data_attributes/mixin/EntityAttributeMixin.java @@ -2,7 +2,7 @@ import java.util.Map; -import com.bibireden.data_attributes.config.models.OverridesConfigModel; +import com.bibireden.data_attributes.config.models.OverridesConfigModel.AttributeOverride; import com.bibireden.data_attributes.config.functions.AttributeFunction; import com.llamalad7.mixinextras.injector.ModifyReturnValue; import net.minecraft.entity.attribute.EntityAttributeInstance; @@ -62,7 +62,7 @@ abstract class EntityAttributeMixin implements MutableEntityAttribute { } @Override - public void data_attributes$override(OverridesConfigModel.AttributeOverride override) { + public void data_attributes$override(AttributeOverride override) { this.data_attributes$enabled = override.enabled; this.data_attributes$min = override.min; this.data_attributes$max = override.max; @@ -90,12 +90,12 @@ abstract class EntityAttributeMixin implements MutableEntityAttribute { @Override public void data_attributes$clear() { - this.data_attributes$override(new OverridesConfigModel.AttributeOverride(this.data_attributes$enabled, this.fallback, this.fallback, this.fallback, this.fallback, 0.0D, StackingFormula.Flat)); + this.data_attributes$override(new AttributeOverride(this.data_attributes$enabled, this.fallback, this.fallback, this.fallback, this.fallback, 0.0D, StackingFormula.Flat)); this.data_attributes$clearDescendants(); } @Override - public double data_attributes$sum(final double k, final double k2, final double v, final double v2, EntityAttributeInstance instance) { + public Double data_attributes$sum(final double k, final double k2, final double v, final double v2, EntityAttributeInstance instance) { return this.data_attributes$formula.result(k, k2, v, v2, instance); } @@ -110,18 +110,18 @@ abstract class EntityAttributeMixin implements MutableEntityAttribute { } @Override - public double data_attributes$min() { return this.data_attributes$min; } + public Double data_attributes$min() { return this.data_attributes$min; } @Override - public double data_attributes$max() { return this.data_attributes$max; } + public Double data_attributes$max() { return this.data_attributes$max; } @Override - public double data_attributes$min_fallback() { + public Double data_attributes$min_fallback() { return Double.MIN_VALUE; } @Override - public double data_attributes$max_fallback() { + public Double data_attributes$max_fallback() { return Double.MAX_VALUE; } diff --git a/src/main/java/com/bibireden/data_attributes/mixin/EntityTrackerEntryMixin.java b/src/main/java/com/bibireden/data_attributes/mixin/EntityTrackerEntryMixin.java index 30da329..3fc1fef 100644 --- a/src/main/java/com/bibireden/data_attributes/mixin/EntityTrackerEntryMixin.java +++ b/src/main/java/com/bibireden/data_attributes/mixin/EntityTrackerEntryMixin.java @@ -1,21 +1,15 @@ package com.bibireden.data_attributes.mixin; - -import com.llamalad7.mixinextras.injector.wrapoperation.Operation; -import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; -import net.minecraft.entity.attribute.EntityAttributeInstance; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; -import com.bibireden.data_attributes.mutable.MutableAttributeContainer; - import net.minecraft.entity.Entity; import net.minecraft.entity.LivingEntity; import net.minecraft.server.network.EntityTrackerEntry; import org.spongepowered.asm.mixin.injection.At; - -import java.util.Set; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(EntityTrackerEntry.class) abstract class EntityTrackerEntryMixin { @@ -23,10 +17,6 @@ abstract class EntityTrackerEntryMixin { @Shadow private Entity entity; - @WrapOperation(method = "syncEntityData", at = @At(value = "INVOKE", target = "Ljava/util/Set;clear()V")) - private void data_attributes$syncEntityData(Set instances, Operation original) { - MutableAttributeContainer container = (MutableAttributeContainer) ((LivingEntity) this.entity).getAttributes(); - container.data_attributes$clearTracked(); - original.call(instances); - } + @Inject(method = "syncEntityData", at = @At(value = "INVOKE", target = "Ljava/util/Set;clear()V")) + private void data_attributes$syncEntityData(CallbackInfo ci) { ((LivingEntity) this.entity).getAttributes().data_attributes$clearTracked(); } } diff --git a/src/main/java/com/bibireden/data_attributes/mixin/LivingEntityMixin.java b/src/main/java/com/bibireden/data_attributes/mixin/LivingEntityMixin.java index 3f4ddb9..9f4f255 100644 --- a/src/main/java/com/bibireden/data_attributes/mixin/LivingEntityMixin.java +++ b/src/main/java/com/bibireden/data_attributes/mixin/LivingEntityMixin.java @@ -8,8 +8,6 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; -import com.bibireden.data_attributes.DataAttributes; - import net.minecraft.entity.EntityType; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.attribute.AttributeContainer; diff --git a/src/main/java/com/bibireden/data_attributes/mixin/ReloadCommandMixin.java b/src/main/java/com/bibireden/data_attributes/mixin/MinecraftServerMixin.java similarity index 50% rename from src/main/java/com/bibireden/data_attributes/mixin/ReloadCommandMixin.java rename to src/main/java/com/bibireden/data_attributes/mixin/MinecraftServerMixin.java index 8664d93..9ad57ce 100644 --- a/src/main/java/com/bibireden/data_attributes/mixin/ReloadCommandMixin.java +++ b/src/main/java/com/bibireden/data_attributes/mixin/MinecraftServerMixin.java @@ -1,11 +1,13 @@ package com.bibireden.data_attributes.mixin; import java.util.Collection; +import java.util.concurrent.CompletableFuture; import com.bibireden.data_attributes.api.DataAttributesAPI; import com.bibireden.data_attributes.config.AttributeConfigManager; import com.bibireden.data_attributes.networking.NetworkingChannels; import io.wispforest.endec.format.bytebuf.ByteBufSerializer; +import net.minecraft.server.MinecraftServer; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -19,28 +21,13 @@ import net.minecraft.network.PacketByteBuf; import net.minecraft.server.command.ReloadCommand; import net.minecraft.server.command.ServerCommandSource; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; /** Hooks onto the reload command on the server to update the manager and post changes to the client. */ -@Mixin(ReloadCommand.class) -abstract class ReloadCommandMixin { - @Inject(method = "tryReloadDataPacks", at = @At("TAIL")) - private static void data_attributes$tryReloadDataPacks(Collection dataPacks, ServerCommandSource source, CallbackInfo ci) { - DataAttributes.reloadConfigs(); - - AttributeConfigManager manager = DataAttributesAPI.getServerManager(); - - manager.update(); - manager.nextUpdateFlag(); - - PacketByteBuf buf = AttributeConfigManager.Packet.ENDEC.encodeFully(() -> ByteBufSerializer.of(PacketByteBufs.create()), manager.toPacket()); - PlayerLookup.all(source.getServer()).forEach(player -> ServerPlayNetworking.send(player, NetworkingChannels.RELOAD, buf)); - - DataAttributes.LOGGER.info( - "Updated manager with {} override(s), {} function(s) and {} entity types :: update flag [#{}]", - DataAttributes.OVERRIDES_CONFIG.getOverrides().size(), - DataAttributes.FUNCTIONS_CONFIG.getFunctions().getData().size(), - DataAttributes.ENTITY_TYPES_CONFIG.getEntity_types().size(), - manager.getUpdateFlag() - ); +@Mixin(MinecraftServer.class) +abstract class MinecraftServerMixin { + @Inject(method = "reloadResources", at = @At("TAIL")) + private void data_attributes$reloadResources(Collection dataPacks, CallbackInfoReturnable> cir) { +// DataAttributes.reload((MinecraftServer) (Object) this); } } diff --git a/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeContainer.java b/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeContainer.java index 798581b..078cc60 100644 --- a/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeContainer.java +++ b/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeContainer.java @@ -1,5 +1,6 @@ package com.bibireden.data_attributes.mutable; +import java.util.HashMap; import java.util.Map; import net.minecraft.entity.LivingEntity; @@ -8,18 +9,18 @@ public interface MutableAttributeContainer { - // Returns a map of custom attributes associated with this container - Map data_attributes$custom(); + /** Returns a map of custom {@link EntityAttributeInstance}'s associated with this container. */ + default Map data_attributes$custom() { return new HashMap<>(); } - // Returns the LivingEntity associated with this container - LivingEntity data_attributes$getLivingEntity(); + /** Returns the {@link LivingEntity} associated with this container. */ + default LivingEntity data_attributes$getLivingEntity() { return null; } - // Sets the LivingEntity associated with this container - void data_attributes$setLivingEntity(final LivingEntity livingEntity); + /** Sets the {@link LivingEntity} associated with this container. */ + default void data_attributes$setLivingEntity(final LivingEntity livingEntity) {} - // Refreshes the attributes of the associated LivingEntity - void data_attributes$refresh(); + /** Refreshes the attributes of the associated {@link LivingEntity}. */ + default void data_attributes$refresh() {} - // Clears any tracked information (possibly related to attribute changes) - void data_attributes$clearTracked(); + /** Clears any tracked information (possibly related to attribute changes). */ + default void data_attributes$clearTracked() {} } diff --git a/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeInstance.java b/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeInstance.java index f2fc79c..7d50aa1 100644 --- a/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeInstance.java +++ b/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeInstance.java @@ -9,18 +9,18 @@ public interface MutableAttributeInstance { - // Returns the unique identifier of the attribute instance - Identifier data_attributes$get_id(); + /** Returns the unique identifier associated with this instance. */ + default Identifier data_attributes$get_id() { return null; } - // Performs an action on the attribute modifier - void data_attributes$actionModifier(final VoidConsumer consumerIn, final EntityAttributeInstance instanceIn, final EntityAttributeModifier modifierIn, final boolean isWasAdded); + /** Executes an action involving the instance and a provided {@link EntityAttributeModifier}. */ + default void data_attributes$actionModifier(final VoidConsumer consumerIn, final EntityAttributeInstance instanceIn, final EntityAttributeModifier modifierIn, final boolean isWasAdded) {} - // Sets a callback for changes to the associated AttributeContainer - void data_attributes$setContainerCallback(final AttributeContainer containerIn); + /** Sets a callback for changes to the associated {@link AttributeContainer}. */ + default void data_attributes$setContainerCallback(final AttributeContainer containerIn) {} - // Updates the identifier of the attribute instance - void data_attributes$updateId(final Identifier identifierIn); + /** Updates the identifier of the instance. */ + default void data_attributes$updateId(final Identifier identifierIn) {} - // Refreshes the attribute instance - void data_attributes$refresh(); + /** Updates the instance. */ + default void data_attributes$refresh() {} } diff --git a/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeModifier.java b/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeModifier.java index 38e23f0..e3be554 100644 --- a/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeModifier.java +++ b/src/main/java/com/bibireden/data_attributes/mutable/MutableAttributeModifier.java @@ -2,6 +2,6 @@ public interface MutableAttributeModifier { - // Updates the value of the attribute modifier - void data_attributes$updateValue(double value); + /** Updates the value of the modifier. */ + default void data_attributes$updateValue(double value) {} } diff --git a/src/main/java/com/bibireden/data_attributes/mutable/MutableDefaultAttributeContainer.java b/src/main/java/com/bibireden/data_attributes/mutable/MutableDefaultAttributeContainer.java index 19ea973..a367ee3 100644 --- a/src/main/java/com/bibireden/data_attributes/mutable/MutableDefaultAttributeContainer.java +++ b/src/main/java/com/bibireden/data_attributes/mutable/MutableDefaultAttributeContainer.java @@ -4,6 +4,6 @@ public interface MutableDefaultAttributeContainer { - // Copies attribute configurations from a DefaultAttributeContainer.Builder - void data_attributes$copy(DefaultAttributeContainer.Builder builder); + /** Copies attribute configurations from a {@link DefaultAttributeContainer.Builder}. */ + default void data_attributes$copy(DefaultAttributeContainer.Builder builder) {}; } diff --git a/src/main/java/com/bibireden/data_attributes/mutable/MutableEntityAttribute.java b/src/main/java/com/bibireden/data_attributes/mutable/MutableEntityAttribute.java index cde0bb1..0dfa3fe 100644 --- a/src/main/java/com/bibireden/data_attributes/mutable/MutableEntityAttribute.java +++ b/src/main/java/com/bibireden/data_attributes/mutable/MutableEntityAttribute.java @@ -1,10 +1,11 @@ package com.bibireden.data_attributes.mutable; +import java.util.HashMap; import java.util.Map; import com.bibireden.data_attributes.api.attribute.IEntityAttribute; import com.bibireden.data_attributes.api.attribute.StackingFormula; -import com.bibireden.data_attributes.config.models.OverridesConfigModel; +import com.bibireden.data_attributes.config.models.OverridesConfigModel.AttributeOverride; import com.bibireden.data_attributes.config.functions.AttributeFunction; import net.minecraft.entity.attribute.EntityAttributeInstance; @@ -25,26 +26,26 @@ static boolean contains(MutableEntityAttribute lhs, MutableEntityAttribute rhs) } /** Overrides entity attribute properties. */ - void data_attributes$override(OverridesConfigModel.AttributeOverride override); + default void data_attributes$override(AttributeOverride override) {} /** Adds a parent attribute with a function. */ - void data_attributes$addParent(MutableEntityAttribute attribute, final AttributeFunction function); + default void data_attributes$addParent(MutableEntityAttribute attribute, final AttributeFunction function) {} /** Adds a child attribute with a function. */ - void data_attributes$addChild(MutableEntityAttribute attribute, final AttributeFunction function); + default void data_attributes$addChild(MutableEntityAttribute attribute, final AttributeFunction function) {} /** Clears all properties and relationships of the entity attribute. */ - void data_attributes$clear(); + default void data_attributes$clear() {} /** Calculates the sum based on the {@link StackingFormula}. * By including a secondary pair of variables, * it allows for the modeling of more complex scenarios, such as negative modifiers. */ - double data_attributes$sum(final double k, final double k2, final double v, final double v2, EntityAttributeInstance instance); + default Double data_attributes$sum(final double k, final double k2, final double v, final double v2, EntityAttributeInstance instance) { return null; } /** Returns a mutable map of parent entity attributes with associated functions. */ - Map data_attributes$parentsMutable(); + default Map data_attributes$parentsMutable() { return new HashMap<>(); } /** Returns a mutable map of child entity attributes with associated functions. */ - Map data_attributes$childrenMutable(); + default Map data_attributes$childrenMutable() { return new HashMap<>(); } } diff --git a/src/main/kotlin/com/bibireden/data_attributes/DataAttributes.kt b/src/main/kotlin/com/bibireden/data_attributes/DataAttributes.kt index c9cb26f..87ecbcc 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/DataAttributes.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/DataAttributes.kt @@ -1,21 +1,25 @@ package com.bibireden.data_attributes -import com.bibireden.data_attributes.config.* +import com.bibireden.data_attributes.api.DataAttributesAPI.serverManager +import com.bibireden.data_attributes.config.AttributeConfigManager +import com.bibireden.data_attributes.config.entry.DefaultAttributesReloadListener import com.bibireden.data_attributes.config.models.DataAttributesConfig import com.bibireden.data_attributes.config.models.EntityTypesConfig import com.bibireden.data_attributes.config.models.FunctionsConfig import com.bibireden.data_attributes.config.models.OverridesConfig import com.bibireden.data_attributes.ext.refreshAttributes -import com.bibireden.data_attributes.networking.NetworkingChannels import com.bibireden.data_attributes.networking.ConfigPacketBufs +import com.bibireden.data_attributes.networking.NetworkingChannels import com.bibireden.data_attributes.serde.JanksonBuilders import io.wispforest.endec.format.bytebuf.ByteBufSerializer import net.fabricmc.api.ModInitializer import net.fabricmc.fabric.api.entity.event.v1.ServerEntityWorldChangeEvents -import net.fabricmc.fabric.api.networking.v1.PacketByteBufs -import net.fabricmc.fabric.api.networking.v1.ServerLoginConnectionEvents -import net.fabricmc.fabric.api.networking.v1.ServerLoginNetworking +import net.fabricmc.fabric.api.event.lifecycle.v1.ServerLifecycleEvents +import net.fabricmc.fabric.api.networking.v1.* +import net.fabricmc.fabric.api.resource.ResourceManagerHelper import net.minecraft.entity.LivingEntity +import net.minecraft.resource.ResourceType +import net.minecraft.server.MinecraftServer import net.minecraft.util.Identifier import net.minecraft.world.World import org.apache.logging.log4j.LogManager @@ -34,6 +38,7 @@ class DataAttributes : ModInitializer { val MANAGER = AttributeConfigManager() + val RELOAD_LISTENER = DefaultAttributesReloadListener() /** Creates an [Identifier] associated with the [MOD_ID]. */ fun id(str: String) = Identifier.of(MOD_ID, str)!! @@ -59,15 +64,36 @@ class DataAttributes : ModInitializer { CONFIG.save() } + /** + * Initiates a reload of config and default data for the server's [AttributeConfigManager]. + * Changes are then networked to the client. + * */ + @JvmStatic + fun reload(server: MinecraftServer) { + reloadConfigs() + + val manager = serverManager + + manager.update() + manager.nextUpdateFlag() + + val buf = AttributeConfigManager.Packet.ENDEC.encodeFully({ ByteBufSerializer.of(PacketByteBufs.create()) }, manager.toPacket()) + PlayerLookup.all(server).forEach { player -> ServerPlayNetworking.send(player, NetworkingChannels.RELOAD, buf) } + } + init { ConfigPacketBufs.registerPacketSerializers() } } override fun onInitialize() { + ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(RELOAD_LISTENER) + ServerLoginNetworking.registerGlobalReceiver(NetworkingChannels.HANDSHAKE) { _, _, _, _, _, _ -> } - ServerLoginConnectionEvents.INIT.register { _, _ -> if (CONFIG.applyOnWorldStart) MANAGER.update() } + ServerLifecycleEvents.SERVER_STARTED.register(::reload) + ServerLifecycleEvents.END_DATA_PACK_RELOAD.register { server, _, _ -> reload(server) } + ServerLoginConnectionEvents.QUERY_START.register { _, _, sender, _ -> sender.sendPacket(NetworkingChannels.HANDSHAKE, AttributeConfigManager.Packet.ENDEC.encodeFully({ ByteBufSerializer.of(PacketByteBufs.create()) }, MANAGER.toPacket())) } diff --git a/src/main/kotlin/com/bibireden/data_attributes/api/DataAttributesAPI.kt b/src/main/kotlin/com/bibireden/data_attributes/api/DataAttributesAPI.kt index 2558641..f98e7b0 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/api/DataAttributesAPI.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/api/DataAttributesAPI.kt @@ -32,7 +32,6 @@ object DataAttributesAPI { @JvmStatic fun getManager(world: World) = DataAttributes.getManagerFromWorld(world) - @JvmStatic /** * Tries to obtain a [EntityAttribute] value off a [LivingEntity]. * Certain requirements must be met in order for the value to be present: @@ -40,6 +39,7 @@ object DataAttributesAPI { * - The attribute is registered to the game * - The attribute is **present** on the given [LivingEntity]. */ + @JvmStatic fun getValue(attribute: EntityAttribute, entity: LivingEntity): Optional { val container = entity.attributes @@ -51,7 +51,6 @@ object DataAttributesAPI { } } - @JvmStatic /** * Tries to obtain a [EntityAttribute] value off a [LivingEntity] based on a supplier implementation. * Certain requirements must be met in order for the value to be present: @@ -59,6 +58,7 @@ object DataAttributesAPI { * - The attribute is registered to the game * - The attribute is **present** on the given [LivingEntity]. */ + @JvmStatic fun getValue(supplier: Supplier>, entity: LivingEntity): Optional { return supplier.get().filter(entity.attributes::hasAttribute).map(entity.attributes::getValue) } diff --git a/src/main/kotlin/com/bibireden/data_attributes/api/event/AttributesReloadedEvent.kt b/src/main/kotlin/com/bibireden/data_attributes/api/event/AttributesReloadedEvent.kt index 0edf7b3..23219ad 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/api/event/AttributesReloadedEvent.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/api/event/AttributesReloadedEvent.kt @@ -10,7 +10,7 @@ import net.fabricmc.fabric.api.event.EventFactory object AttributesReloadedEvent { /** * Triggered on the **server** upon these conditions: - * - World Startup + * - World Startup (if the config is enabled for it) * - Reload through `/reload` brigadier command. * * Triggered on the **client** upon these conditions: diff --git a/src/main/kotlin/com/bibireden/data_attributes/api/factory/DefaultAttributeFactory.kt b/src/main/kotlin/com/bibireden/data_attributes/api/factory/DefaultAttributeFactory.kt index f2fab39..9128c36 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/api/factory/DefaultAttributeFactory.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/api/factory/DefaultAttributeFactory.kt @@ -1,18 +1,22 @@ package com.bibireden.data_attributes.api.factory import com.bibireden.data_attributes.DataAttributes +import com.bibireden.data_attributes.config.AttributeConfigManager import com.bibireden.data_attributes.config.functions.AttributeFunction import com.bibireden.data_attributes.config.models.OverridesConfigModel.AttributeOverride import com.bibireden.data_attributes.data.EntityTypeData import net.minecraft.util.Identifier /** - * Meant to register attributes into the DataAttributes config primarily after it is initialized. + * Meant to register attributes into the game's [AttributeConfigManager] directly. * * This is useful for mods that wish to implement their own defaults, so they can be applied to the world. - * Ensure that it is not done through static initialization, the config is not guaranteed to exist at that time. Instead, register afterward, such as on **mod initialization**. + * Ensure that it is not done through static initialization, the config is not guaranteed to exist at that time. + * + * Instead, register afterward, such as on **mod initialization**. */ object DefaultAttributeFactory { + @Deprecated("Use the new data-pack based system to register default entries.", level = DeprecationLevel.WARNING) @JvmStatic /** Registers default [AttributeOverride]'s to the config if they are not present currently within the config. */ fun registerOverrides(overrides: Map) { @@ -22,6 +26,7 @@ object DefaultAttributeFactory { DataAttributes.OVERRIDES_CONFIG.save() } + @Deprecated("Use the new data-pack based system to register default entries.", level = DeprecationLevel.WARNING) @JvmStatic /** Registers default [AttributeFunction]'s to the config if they are not present currently within the config. */ fun registerFunctions(functions: Map>) { @@ -41,6 +46,7 @@ object DefaultAttributeFactory { DataAttributes.FUNCTIONS_CONFIG.save() } + @Deprecated("Use the new data-pack based system to register default entries.", level = DeprecationLevel.WARNING) @JvmStatic /** Registers default [EntityTypeData]'s to the config if they are not present currently within the config. */ fun registerEntityTypes(entityTypes: Map) { 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 24a6041..2cb73eb 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/AttributeConfigManager.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/AttributeConfigManager.kt @@ -4,8 +4,10 @@ import com.bibireden.data_attributes.DataAttributes import com.bibireden.data_attributes.api.EntityInstances import com.bibireden.data_attributes.api.attribute.IEntityAttribute import com.bibireden.data_attributes.api.event.AttributesReloadedEvent -import com.bibireden.data_attributes.config.models.OverridesConfigModel.AttributeOverride +import com.bibireden.data_attributes.config.entry.ConfigMerger +import com.bibireden.data_attributes.config.entry.DefaultAttributesReloadListener 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.data.EntityTypeData import com.bibireden.data_attributes.endec.Endecs @@ -28,9 +30,11 @@ import net.minecraft.util.Identifier /** * Used to manage config data, and contains an [AttributeContainerHandler] to build related [EntityTypeData]. */ -class AttributeConfigManager(var data: Data = Data(), val handler: AttributeContainerHandler = AttributeContainerHandler()) { +class AttributeConfigManager(private var data: Data = Data(), val handler: AttributeContainerHandler = AttributeContainerHandler()) { var updateFlag: Int = 0 + var defaults: DefaultAttributesReloadListener.Cache = DefaultAttributesReloadListener.Cache() + @JvmRecord data class Tuple(val livingEntity: Class, val value: T) @@ -49,11 +53,10 @@ class AttributeConfigManager(var data: Data = Data(), val handler: AttributeCont /** * Wrapper for the config manager to use internally to send as [Packet] data and to reflect changes based on what it contains. */ - @JvmRecord data class Data( - val overrides: Map = mapOf(), - val functions: Map> = mapOf(), - val entity_types: Map = mapOf() + var overrides: Map = mapOf(), + var functions: Map> = mapOf(), + var entity_types: Map = mapOf() ) { companion object { @@ -108,11 +111,10 @@ class AttributeConfigManager(var data: Data = Data(), val handler: AttributeCont * This applies the data immediately afterward. */ fun update() { - this.data = Data( - DataAttributes.OVERRIDES_CONFIG.overrides, - DataAttributes.FUNCTIONS_CONFIG.functions.data, - DataAttributes.ENTITY_TYPES_CONFIG.entity_types - ) + 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) + this.onDataUpdate() } @@ -121,7 +123,10 @@ class AttributeConfigManager(var data: Data = Data(), val handler: AttributeCont /** Reads in the packet and applies fresh data and sets the update flag. */ fun readPacket(packet: Packet) { - this.data = packet.data + this.data.overrides = packet.data.overrides + this.data.functions = packet.data.functions + this.data.entity_types = packet.data.entity_types + this.updateFlag = packet.updateFlag } @@ -135,29 +140,8 @@ class AttributeConfigManager(var data: Data = Data(), val handler: AttributeCont fun onDataUpdate() { val entityAttributeData = mutableMapOf() - for ((id, value) in this.overrides) { - if (!Registries.ATTRIBUTE.containsId(id)) { - DataAttributes.LOGGER.warn("Attribute [$id] that was targeted for override is not registered. This has been skipped.") - continue - } - val attribute = Registries.ATTRIBUTE[id]!! as IEntityAttribute - if (value.max.isNaN()) { - value.max = attribute.`data_attributes$max_fallback`() - } - if (value.min.isNaN()) { - value.min = attribute.`data_attributes$min_fallback`() - } - entityAttributeData[id] = EntityAttributeData(value) - } - - for ((id, configs) in this.functions) { - if (!Registries.ATTRIBUTE.containsId(id)) { - DataAttributes.LOGGER.warn("Function parent [$id] that was defined in config is not registered. This has been skipped.") - } - else { - entityAttributeData.getOrPut(id, ::EntityAttributeData).putFunctions(configs) - } - } + insertOverrides(this.overrides, entityAttributeData) + insertFunctions(this.functions, entityAttributeData) for (id in Registries.ATTRIBUTE.ids) { (Registries.ATTRIBUTE[id] as? MutableEntityAttribute)?.`data_attributes$clear`() @@ -174,5 +158,37 @@ class AttributeConfigManager(var data: Data = Data(), val handler: AttributeCont this.handler.buildContainers(this.entityTypes) AttributesReloadedEvent.EVENT.invoker().onReloadCompleted() + + DataAttributes.LOGGER.info("Updated manager with {} entries & {} entity-types. :: update flag [#{}]", entityAttributeData.size, this.entityTypes.size, updateFlag) + } + + private fun insertOverrides(overrides: Map, entityAttributeData: MutableMap) { + overrides.forEach { (id, override) -> + if (!Registries.ATTRIBUTE.containsId(id)) { + DataAttributes.LOGGER.warn("Attribute [$id] that was targeted for override is not registered. This has been skipped.") + return@forEach + } + val attribute = Registries.ATTRIBUTE[id]!! as IEntityAttribute + if (override.max.isNaN()) { + override.max = attribute.`data_attributes$max_fallback`() + } + if (override.min.isNaN()) { + override.min = attribute.`data_attributes$min_fallback`() + } + entityAttributeData[id] = EntityAttributeData(override) + } + } + + private fun insertFunctions(store: Map>, data: MutableMap) { + store.forEach { (id, functions) -> + if (!Registries.ATTRIBUTE.containsId(id)) { + DataAttributes.LOGGER.warn("Function parent [$id] that was defined in config is not registered. This has been skipped.") + } + else { + val dat = data[id] ?: EntityAttributeData() + dat.putFunctions(functions) + data[id] = dat + } + } } } \ No newline at end of file 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 a886a1a..e971e9b 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/DataAttributesConfigProviders.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/DataAttributesConfigProviders.kt @@ -62,7 +62,7 @@ object DataAttributesConfigProviders { tb.setUneditableColor(ColorCodes.BEE_BLACK) tb.setEditable(!isUnchangeable) if (isUnchangeable) { - tb.active = false + tb.setTextPredicate { false } tb.cursorStyle(CursorStyle.POINTER) tb.setSuggestion(obj.toString()) tb.tooltip(Text.translatable("text.config.data_attributes.data_entry.unchangeable")) @@ -72,11 +72,8 @@ object DataAttributesConfigProviders { tb.text = obj.toString() } if (onChange != null) { - tb.onChanged().subscribe { v -> - if (predicate == null || predicate.apply(v)) { - onChange.invoke(v) - } - } + tb.setTextPredicate { predicate == null || predicate.apply(it) } + tb.onChanged().subscribe(onChange::invoke) } }.positioning(Positioning.relative(100, 50)).id(textBoxID) ) diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/Validators.kt b/src/main/kotlin/com/bibireden/data_attributes/config/Validators.kt index 3640828..73dfa3c 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/Validators.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/Validators.kt @@ -2,5 +2,5 @@ package com.bibireden.data_attributes.config object Validators { /** Checks if the [String] is a valid number via. Regex. */ - fun isNumeric(str: String) = str.matches("-?\\d+(\\.\\d+)?".toRegex()) + fun isNumeric(str: String) = str.matches("^[0-9.-]*\$".toRegex()) } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/entry/ConfigMerger.kt b/src/main/kotlin/com/bibireden/data_attributes/config/entry/ConfigMerger.kt new file mode 100644 index 0000000..f1f6c0e --- /dev/null +++ b/src/main/kotlin/com/bibireden/data_attributes/config/entry/ConfigMerger.kt @@ -0,0 +1,61 @@ +package com.bibireden.data_attributes.config.entry + +import com.bibireden.data_attributes.DataAttributes +import com.bibireden.data_attributes.config.functions.AttributeFunction +import com.bibireden.data_attributes.config.models.OverridesConfigModel.AttributeOverride +import com.bibireden.data_attributes.data.EntityTypeData +import net.minecraft.util.Identifier + +object ConfigMerger { + fun mergeOverrides(values: Map): Map { + val entries = values.toMutableMap() + for ((id, override) in DataAttributes.OVERRIDES_CONFIG.overrides) { + entries[id] = override + } + return entries + } + + fun mergeFunctions(values: Map>): Map> { + val entries = values.toMutableMap() + for ((primaryId, primaryFunctions) in DataAttributes.FUNCTIONS_CONFIG.functions.data) { + val secondaryEntry = entries[primaryId]?.toMutableList() + if (secondaryEntry == null) { + entries[primaryId] = primaryFunctions + } + else { + primaryFunctions.forEach { primaryFunction -> + var replaced = false + secondaryEntry.forEachIndexed { index, entry -> + if (entry.id == primaryFunction.id) { + secondaryEntry.removeAt(index) + secondaryEntry.add(index, primaryFunction) + replaced = true + } + } + if (!replaced) { + secondaryEntry.add(primaryFunction) + } + } + entries[primaryId] = secondaryEntry + } + } + return entries + } + + fun mergeEntityTypes(values: Map>): Map { + val entries = values.toMutableMap() + for ((primaryId, primaryEntry) in DataAttributes.ENTITY_TYPES_CONFIG.entity_types) { + val secondaryEntry = entries[primaryId]?.toMutableMap() + if (secondaryEntry == null) { + entries[primaryId] = primaryEntry.data + } + else { + for ((id, value) in primaryEntry.data) { + secondaryEntry[id] = value + } + entries[primaryId] = secondaryEntry + } + } + return entries.entries.associate { (k, v) -> k to EntityTypeData(v) } + } +} \ No newline at end of file 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 new file mode 100644 index 0000000..c1a8f19 --- /dev/null +++ b/src/main/kotlin/com/bibireden/data_attributes/config/entry/DefaultAttributesReloadListener.kt @@ -0,0 +1,109 @@ +@file:UseSerializers(IdentifierSerializer::class) + +package com.bibireden.data_attributes.config.entry + +import com.bibireden.data_attributes.serde.IdentifierSerializer +import kotlinx.serialization.UseSerializers + +import com.bibireden.data_attributes.DataAttributes +import com.bibireden.data_attributes.config.functions.AttributeFunction +import com.bibireden.data_attributes.config.models.OverridesConfigModel.AttributeOverride +import com.bibireden.data_attributes.data.EntityTypeData +import kotlinx.serialization.ExperimentalSerializationApi +import kotlinx.serialization.Serializable +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.decodeFromStream +import net.fabricmc.fabric.api.resource.SimpleResourceReloadListener +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 + +/** + * 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() + + @Serializable + data class Overrides(val entries: LinkedHashMap = LinkedHashMap()) + @Serializable + data class Functions(val entries: LinkedHashMap> = LinkedHashMap()) + @Serializable + data class EntityTypes(val entries: LinkedHashMap> = LinkedHashMap()) + + @Serializable + data class Cache(val overrides: Overrides = Overrides(), val functions: Functions = Functions(), val types: EntityTypes = EntityTypes()) + + companion object { + const val DIRECTORY = DataAttributes.MOD_ID + } + + private fun isPathJson(id: Identifier) = id.path.endsWith(".json") + + override fun getFabricId(): Identifier = DataAttributes.id(DIRECTORY) + + 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) + + cache + } + } + + override fun apply(cache: Cache, manager: ResourceManager, profiler: Profiler, executor: Executor): CompletableFuture { + return CompletableFuture.runAsync { DataAttributes.MANAGER.defaults = cache } + } + + private fun readOverrides(manager: ResourceManager, cache: Cache) { + val path = "$DIRECTORY/overrides" + + manager.findResources(path, ::isPathJson).forEach { (id, res) -> + try { + Json.decodeFromStream(res.inputStream).entries.forEach { (id, entry) -> + cache.overrides.entries.computeIfAbsent(id) { entry } + } + } + catch (why: Exception) { + DataAttributes.LOGGER.error("Failed to parse overrides@$id :: {}", why.message) + } + } + } + + private fun readFunctions(manager: ResourceManager, cache: Cache) { + val path = "$DIRECTORY/functions" + + manager.findResources(path, ::isPathJson).forEach { (id, res) -> + try { + Json.decodeFromStream(res.inputStream).entries.forEach { (id, entry) -> + cache.functions.entries.computeIfAbsent(id) { entry } + } + } + catch (why: Exception) { + DataAttributes.LOGGER.error("Failed to parse functions@$id :: {}", why.message) + } + } + } + + private fun readEntityTypes(manager: ResourceManager, cache: Cache) { + val path = "$DIRECTORY/entity_types" + + manager.findResources(path, ::isPathJson).forEach { (id, res) -> + try { + Json.decodeFromStream(res.inputStream).entries.forEach { (id, entry) -> + cache.types.entries.computeIfAbsent(id) { entry } + } + } + catch (why: Exception) { + DataAttributes.LOGGER.error("Failed to parse entity-types@$id :: {}", why.message) + } + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/functions/AttributeFunction.kt b/src/main/kotlin/com/bibireden/data_attributes/config/functions/AttributeFunction.kt index 38df4ec..1cf17bd 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/functions/AttributeFunction.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/functions/AttributeFunction.kt @@ -2,8 +2,10 @@ package com.bibireden.data_attributes.config.functions import com.bibireden.data_attributes.api.attribute.StackingBehavior import com.bibireden.data_attributes.endec.Endecs +import com.bibireden.data_attributes.serde.IdentifierSerializer import io.wispforest.endec.Endec import io.wispforest.endec.impl.StructEndecBuilder +import kotlinx.serialization.Serializable import net.minecraft.entity.attribute.EntityAttribute import net.minecraft.util.Identifier @@ -11,7 +13,13 @@ import net.minecraft.util.Identifier * A function that is composed of the target [EntityAttribute] by an [Identifier] it will be applied to, * the [StackingBehavior] of the function which will determine if the given [getValue] will be an additive or multiplicative one. * */ -data class AttributeFunction(var id: Identifier, var behavior: StackingBehavior, var value: Double) { +@Serializable +data class AttributeFunction( + @Serializable(with = IdentifierSerializer::class) + var id: Identifier, + var behavior: StackingBehavior, + var value: Double +) { @Suppress("UNUSED") constructor() : this(Identifier("unknown"), StackingBehavior.Add, 0.0) 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 be59849..85d7530 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 @@ -7,8 +7,4 @@ import io.wispforest.owo.config.annotation.Sync @Suppress("UNUSED") @Config(name = DataAttributes.MOD_ID, wrapperName = "DataAttributesConfig") -class ConfigModel { - @JvmField - @Sync(SyncMode.OVERRIDE_CLIENT) - var applyOnWorldStart: Boolean = true -} \ No newline at end of file +class ConfigModel \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/models/OverridesConfigModel.kt b/src/main/kotlin/com/bibireden/data_attributes/config/models/OverridesConfigModel.kt index a40975b..b761592 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/models/OverridesConfigModel.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/models/OverridesConfigModel.kt @@ -7,6 +7,7 @@ import io.wispforest.endec.Endec import io.wispforest.endec.impl.StructEndecBuilder import io.wispforest.owo.config.Option.SyncMode import io.wispforest.owo.config.annotation.* +import kotlinx.serialization.Serializable import net.minecraft.entity.attribute.EntityAttribute import net.minecraft.util.Identifier @@ -20,6 +21,7 @@ class OverridesConfigModel { @Hook var overrides: Map = mapOf() + @Serializable data class AttributeOverride( @JvmField var enabled: Boolean = true, @@ -51,7 +53,7 @@ class OverridesConfigModel { Endec.DOUBLE.optionalFieldOf("min_fallback", { it.min_fallback }, 0.0), Endec.DOUBLE.optionalFieldOf("max_fallback", { it.max_fallback }, 1_000_000.0), StackingFormula.ENDEC.fieldOf("formula") { it.formula }, - OverridesConfigModel::AttributeOverride, + ::AttributeOverride, ) } } diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeEntityTypesProvider.kt b/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeEntityTypesProvider.kt index bdce5f0..8cf9c8c 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeEntityTypesProvider.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeEntityTypesProvider.kt @@ -1,10 +1,11 @@ package com.bibireden.data_attributes.config.providers -import com.bibireden.data_attributes.config.DataAttributesConfigProviders +import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.config.DataAttributesConfigProviders.attributeIdentifierToText import com.bibireden.data_attributes.config.DataAttributesConfigProviders.entityTypeIdentifierToText import com.bibireden.data_attributes.config.DataAttributesConfigProviders.textBoxComponent import com.bibireden.data_attributes.config.Validators +import com.bibireden.data_attributes.config.entry.ConfigMerger import com.bibireden.data_attributes.data.EntityTypeData import com.bibireden.data_attributes.ui.components.CollapsibleFoldableContainer import io.wispforest.owo.config.Option @@ -15,16 +16,17 @@ import io.wispforest.owo.ui.core.Sizing import net.minecraft.entity.attribute.ClampedEntityAttribute import net.minecraft.registry.Registries import net.minecraft.text.Text +import net.minecraft.util.Formatting import net.minecraft.util.Identifier class AttributeEntityTypesProvider(val option: Option>) : FlowLayout(Sizing.fill(100), Sizing.content(), Algorithm.VERTICAL), OptionValueProvider { val backing = HashMap(option.value()) init { - backing.forEach { (topID, types) -> + ConfigMerger.mergeEntityTypes(DataAttributesAPI.serverManager.defaults.types.entries).forEach { (topID, types) -> CollapsibleFoldableContainer(Sizing.content(), Sizing.content(), entityTypeIdentifierToText(topID), true).also { ct -> ct.gap(15) - types.data.forEach { id, value -> + types.data.forEach { (id, value) -> Containers.collapsible(Sizing.content(), Sizing.content(), attributeIdentifierToText(id), true).also { it.gap(8) @@ -34,7 +36,7 @@ class AttributeEntityTypesProvider(val option: Option - val data = this.backing.remove(topID)?: return@let + val data = this.backing.remove(topID) ?: EntityTypeData() val mapping = data.data.toMutableMap() mapping[id] = value this.backing.put(topID, data.copy(data = mapping)) diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeFunctionsProvider.kt b/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeFunctionsProvider.kt index a8857a1..062e18f 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeFunctionsProvider.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeFunctionsProvider.kt @@ -1,10 +1,12 @@ package com.bibireden.data_attributes.config.providers +import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.api.attribute.StackingBehavior import com.bibireden.data_attributes.config.DataAttributesConfigProviders.attributeIdentifierToText import com.bibireden.data_attributes.config.DataAttributesConfigProviders.isAttributeUnregistered import com.bibireden.data_attributes.config.DataAttributesConfigProviders.textBoxComponent import com.bibireden.data_attributes.config.Validators +import com.bibireden.data_attributes.config.entry.ConfigMerger import com.bibireden.data_attributes.config.functions.AttributeFunctionConfig import com.bibireden.data_attributes.ui.components.CollapsibleFoldableContainer import com.bibireden.data_attributes.ui.renderers.ButtonRenderers @@ -24,7 +26,7 @@ class AttributeFunctionsProvider(val option: Option) : val backing = option.value().data.toMutableMap() init { - backing.forEach { (topID, functions) -> + ConfigMerger.mergeFunctions(DataAttributesAPI.serverManager.defaults.functions.entries).forEach { (topID, functions) -> val isFunctionParentUnregistered = isAttributeUnregistered(topID) CollapsibleFoldableContainer(Sizing.content(), Sizing.content(), attributeIdentifierToText(topID), true).also { ct -> ct.gap(15) @@ -58,8 +60,13 @@ class AttributeFunctionsProvider(val option: Option) : Validators::isNumeric, onChange = { it.toDoubleOrNull()?.let { v -> - val popped = this.backing.remove(topID)?.toMutableList() ?: return@textBoxComponent - popped[index] = function.copy(value = v) + val popped = this.backing.remove(topID)?.toMutableList() ?: mutableListOf() + if (popped.isEmpty()) { + popped.add(function.copy(value = v)) + } + else { + popped[index] = function.copy(value = v) + } this.backing.put(topID, popped) } } @@ -72,16 +79,20 @@ class AttributeFunctionsProvider(val option: Option) : .sizing(Sizing.content(), Sizing.fixed(20)) ) hf.child( - Components.button(Text.translatable("text.config.data_attributes.enum.functionBehavior.${function.behavior.name.lowercase()}"), { + Components.button(Text.translatable("text.config.data_attributes.enum.functionBehavior.${function.behavior.name.lowercase()}")) { function.behavior = when (function.behavior) { StackingBehavior.Add -> StackingBehavior.Multiply StackingBehavior.Multiply -> StackingBehavior.Add } it.message = Text.translatable("text.config.data_attributes.enum.functionBehavior.${function.behavior.name.lowercase()}") - val popped = this.backing.remove(topID)?.toMutableList() ?: return@button - popped[index] = function.copy(behavior = function.behavior) + val popped = this.backing.remove(topID)?.toMutableList() ?: mutableListOf() + if (popped.isEmpty()) { + popped.add(function.copy(behavior = function.behavior)) + } else { + popped[index] = function.copy(behavior = function.behavior) + } this.backing.put(topID, popped) - }) + } .renderer(ButtonRenderers.STANDARD) .positioning(Positioning.relative(100, 0)).horizontalSizing(Sizing.fixed(65)) ) diff --git a/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeOverrideProvider.kt b/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeOverrideProvider.kt index e4f6e4d..3b94c97 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeOverrideProvider.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/config/providers/AttributeOverrideProvider.kt @@ -1,10 +1,12 @@ package com.bibireden.data_attributes.config.providers +import com.bibireden.data_attributes.api.DataAttributesAPI import com.bibireden.data_attributes.api.attribute.StackingFormula import com.bibireden.data_attributes.config.DataAttributesConfigProviders.attributeIdentifierToText import com.bibireden.data_attributes.config.DataAttributesConfigProviders.isAttributeUnregistered import com.bibireden.data_attributes.config.DataAttributesConfigProviders.textBoxComponent import com.bibireden.data_attributes.config.Validators +import com.bibireden.data_attributes.config.entry.ConfigMerger import com.bibireden.data_attributes.config.models.OverridesConfigModel.AttributeOverride import com.bibireden.data_attributes.mutable.MutableEntityAttribute import com.bibireden.data_attributes.ui.renderers.ButtonRenderers @@ -21,12 +23,13 @@ import io.wispforest.owo.ui.core.VerticalAlignment import net.minecraft.registry.Registries import net.minecraft.text.Text import net.minecraft.util.Identifier +import kotlin.math.max class AttributeOverrideProvider(val option: Option>) : FlowLayout(Sizing.fill(100), Sizing.content(), Algorithm.VERTICAL), OptionValueProvider { val backing = option.value().toMutableMap() init { - backing.forEach { (id, config) -> + ConfigMerger.mergeOverrides(DataAttributesAPI.serverManager.defaults.overrides.entries).forEach { (id, config) -> var override = config // extract min & max fallbacks. val attribute = Registries.ATTRIBUTE[id] as MutableEntityAttribute? @@ -35,7 +38,7 @@ class AttributeOverrideProvider(val option: Option - this.backing.replace(id, override.copy(min = v)) + this.backing[id] = override.copy(min = v) } }, "inputs.min" @@ -93,7 +96,7 @@ class AttributeOverrideProvider(val option: Option - this.backing.replace(id, override.copy(max = v)) + this.backing[id] = override.copy(max = v) } }, "inputs.max" @@ -126,10 +129,8 @@ class AttributeOverrideProvider(val option: Option slider.onChanged().subscribe { - var smoothness = slider.value().round(2) - if (smoothness <= 0.0) {smoothness = 0.01} this.backing.remove(id) - this.backing.put(id, override.copy(smoothness = smoothness)) + this.backing[id] = override.copy(smoothness = max(slider.value().round(2), 0.01)) } } .positioning(Positioning.relative(100, 0)) @@ -150,7 +151,7 @@ class AttributeOverrideProvider(val option: Option StackingFormula.Flat } it.message = Text.translatable("text.config.data_attributes.enum.stackingFormula.${override.formula.name.lowercase()}") - this.backing.replace(id, override.copy(formula = override.formula)) + this.backing[id] = override.copy(formula = override.formula) }) .renderer(ButtonRenderers.STANDARD) .positioning(Positioning.relative(100, 0)).horizontalSizing(Sizing.fixed(65)) 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 2f8dc21..9ba7e36 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/data/EntityAttributeData.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/data/EntityAttributeData.kt @@ -49,11 +49,11 @@ class EntityAttributeData(val override: AttributeOverride? = null, val functions /** Joins a [List] of [AttributeFunction]'s with the data in this class. */ fun putFunctions(functions: List) { - this.functions.putAll(functions.map { (id, behavior, value) -> + functions.forEach { (id, behavior, value) -> if (!Registries.ATTRIBUTE.containsId(id)) { DataAttributes.LOGGER.warn("The attribute function child [$id] does not seem to be registered. This could allude to a missing mod or registered attribute.") } - id to AttributeFunction(id, behavior, value) - }) + this.functions[id] = AttributeFunction(id, behavior, value) + } } } \ No newline at end of file diff --git a/src/main/kotlin/com/bibireden/data_attributes/data/EntityTypeData.kt b/src/main/kotlin/com/bibireden/data_attributes/data/EntityTypeData.kt index 22c2eb6..38f54f8 100644 --- a/src/main/kotlin/com/bibireden/data_attributes/data/EntityTypeData.kt +++ b/src/main/kotlin/com/bibireden/data_attributes/data/EntityTypeData.kt @@ -1,10 +1,14 @@ +@file:UseSerializers(IdentifierSerializer::class) + package com.bibireden.data_attributes.data import com.bibireden.data_attributes.endec.Endecs import com.bibireden.data_attributes.ext.keyOf -import com.bibireden.data_attributes.mutable.MutableAttributeContainer import com.bibireden.data_attributes.mutable.MutableDefaultAttributeContainer +import com.bibireden.data_attributes.serde.IdentifierSerializer import io.wispforest.endec.Endec +import kotlinx.serialization.Serializable +import kotlinx.serialization.UseSerializers import net.minecraft.entity.attribute.DefaultAttributeContainer import net.minecraft.registry.Registries import net.minecraft.util.Identifier @@ -12,6 +16,7 @@ import net.minecraft.util.Identifier /** * Container for data that modifies the specific [Registries.ENTITY_TYPE] entry with an associated base value. */ +@Serializable data class EntityTypeData(val data: Map = mapOf()) { companion object { @JvmField diff --git a/src/main/kotlin/com/bibireden/data_attributes/serde/IdentifierSerializer.kt b/src/main/kotlin/com/bibireden/data_attributes/serde/IdentifierSerializer.kt new file mode 100644 index 0000000..3634be2 --- /dev/null +++ b/src/main/kotlin/com/bibireden/data_attributes/serde/IdentifierSerializer.kt @@ -0,0 +1,18 @@ +package com.bibireden.data_attributes.serde + +import kotlinx.serialization.KSerializer +import kotlinx.serialization.descriptors.PrimitiveKind +import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import net.minecraft.util.Identifier + +class IdentifierSerializer : KSerializer { + override val descriptor: SerialDescriptor + get() = PrimitiveSerialDescriptor("Identifier", PrimitiveKind.STRING) + + override fun deserialize(decoder: Decoder): Identifier = Identifier.tryParse(decoder.decodeString())!! + + override fun serialize(encoder: Encoder, value: Identifier) = encoder.encodeString(value.toString()) +} \ No newline at end of file diff --git a/src/main/resources/data_attributes.mixins.json b/src/main/resources/data_attributes.mixins.json index 04e45d9..19750c1 100644 --- a/src/main/resources/data_attributes.mixins.json +++ b/src/main/resources/data_attributes.mixins.json @@ -12,9 +12,9 @@ "EntityAttributeModifierMixin", "EntityTrackerEntryMixin", "LivingEntityMixin", + "MinecraftServerMixin", "MobEntityMixin", "PlayerEntityMixin", - "ReloadCommandMixin", "item.ArmorItemMixin", "item.ItemMixin", "item.ItemStackMixin", diff --git a/src/main/resources/fabric.mod.json b/src/main/resources/fabric.mod.json index 165d07b..2df57b1 100644 --- a/src/main/resources/fabric.mod.json +++ b/src/main/resources/fabric.mod.json @@ -50,9 +50,24 @@ "loaders": ["fabric", "quilt"], "dependencies": [ "fabric-api@0.92.2+1.20.1(required){modrinth:P7dR8mSH}{curseforge:306612}#(ignore:github)", - "fabric-language-kotlin@1.9.5+kotlin.1.8.22(required){modrinth:Ha28R6CL}{curseforge:308769}#(ignore:github)", + "fabric-language-kotlin@1.12.0+kotlin.2.0.10(required){modrinth:Ha28R6CL}{curseforge:308769}#(ignore:github)", "owo-lib@0.11.2(required){modrinth:ccKDOlHs}{curseforge:532610}#(ignore:github)" ] + }, + "loom:injected_interfaces": { + "net/minecraft/class_1320": ["com/bibireden/data_attributes/api/attribute/IEntityAttribute", "com/bibireden/data_attributes/mutable/MutableEntityAttribute"], + "net/minecraft/class_1324": ["com/bibireden/data_attributes/api/attribute/IEntityAttributeInstance", "com/bibireden/data_attributes/mutable/MutableAttributeInstance"], + "net/minecraft/class_5131": ["com/bibireden/data_attributes/mutable/MutableAttributeContainer"], + "net/minecraft/class_5132": ["com/bibireden/data_attributes/mutable/MutableDefaultAttributeContainer"], + "net/minecraft/class_1322": ["com/bibireden/data_attributes/mutable/MutableAttributeModifier"] + }, + "modmenu": { + "links": { + "modmenu.discord": "https://discord.gg/pcRw79hwey", + "modmenu.wiki": "https://bareminimumstudios.github.io/Bare-Minimum-Docs/", + "modmenu.kofi": "https://ko-fi.com/bibiredens", + "modmenu.modrinth": "https://modrinth.com/mod/data-attributes-directors-cut" + } } } } \ No newline at end of file