From 6f1d6963418deefdd051b80062c66f49964e76dc Mon Sep 17 00:00:00 2001 From: Gabriel Harris-Rouquette Date: Sun, 23 Feb 2025 00:44:47 -0800 Subject: [PATCH] wip: some thoughts on how we might translate data Data Providers are starting to become simpler to implement with more factory like methods instead of the complicated chained methods they currently are. Just some ideas, as Entities are apparently moving towards a more DataComponent centric world. --- .../provider/entity/AreaEffectCloudData.java | 17 +-- .../common/data/provider/entity/CatData.java | 16 +-- .../data/provider/entity/ChickenData.java | 7 +- .../data/provider/entity/EntityData.java | 19 ++-- .../provider/entity/EntityDataProviders.java | 101 +++++++++++++++++- 5 files changed, 135 insertions(+), 25 deletions(-) diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java b/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java index 95ec7d9b635..0113cce620d 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/AreaEffectCloudData.java @@ -25,6 +25,7 @@ package org.spongepowered.common.data.provider.entity; import com.google.common.collect.Streams; +import net.minecraft.core.component.DataComponents; import net.minecraft.world.entity.AreaEffectCloud; import net.minecraft.world.item.alchemy.PotionContents; import org.spongepowered.api.data.Keys; @@ -93,12 +94,6 @@ public static void register(final DataProviderRegistrator registrator) { h.accessor$durationOnUse(SpongeTicks.toSaturatedIntOrInfinite(v)); return true; }) - .create(Keys.POTION_EFFECTS) - .get(h -> PotionEffectUtil.copyAsPotionEffects(Streams.stream(h.accessor$potionContents().getAllEffects()).toList())) - .set((h, v) -> { - final PotionContents contents = h.accessor$potionContents(); - ((AreaEffectCloud) h).setPotionContents(new PotionContents(contents.potion(), contents.customColor(), PotionEffectUtil.copyAsEffectInstances(v), contents.customName())); - }) .create(Keys.REAPPLICATION_DELAY) .get(h -> new SpongeTicks(h.accessor$reapplicationDelay())) .setAnd((h, v) -> { @@ -108,6 +103,14 @@ public static void register(final DataProviderRegistrator registrator) { h.accessor$reapplicationDelay(SpongeTicks.toSaturatedIntOrInfinite(v)); return true; }); + // @formatter:on + final var areaEffectCloud = registrator.asMutable(AreaEffectCloud.class); + final var components = EntityDataProviders.of( + EntityDataProviders.transformedWith(Keys.POTION_EFFECTS, DataComponents.POTION_CONTENTS, + (p) -> PotionEffectUtil.copyAsPotionEffects(Streams.stream(p.getAllEffects()).toList()), + (a, original) -> new PotionContents(original.potion(), original.customColor(), PotionEffectUtil.copyAsEffectInstances(a), original.customName()) + ) + ); + components.forEach(p -> p.applyToRegistrator(areaEffectCloud)); } - // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java b/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java index b8b0442bc8d..48465d6ed99 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/CatData.java @@ -25,6 +25,8 @@ package org.spongepowered.common.data.provider.entity; import net.minecraft.core.Holder; +import net.minecraft.core.component.DataComponents; +import net.minecraft.core.registries.Registries; import net.minecraft.world.entity.animal.Cat; import net.minecraft.world.entity.animal.CatVariant; import org.spongepowered.api.data.Keys; @@ -43,12 +45,6 @@ private CatData() { public static void register(final DataProviderRegistrator registrator) { registrator .asMutable(Cat.class) - .create(Keys.CAT_TYPE) - .get(h -> (CatType) (Object) h.getVariant().value()) - .set((h, v) -> ((CatAccessor) h).invoker$setVariant(Holder.direct((CatVariant) (Object) v))) - .create(Keys.DYE_COLOR) - .get(h -> (DyeColor) (Object) h.getCollarColor()) - .set((h, v) -> ((CatAccessor)h).invoker$setCollarColor((net.minecraft.world.item.DyeColor) (Object) v)) .create(Keys.IS_BEGGING_FOR_FOOD) .get(h -> { throw new MissingImplementationException("CatData", "IS_BEGGING_FOR_FOOD::getter"); @@ -75,6 +71,12 @@ public static void register(final DataProviderRegistrator registrator) { .create(Keys.IS_RELAXED) .get(CatAccessor::invoker$isRelaxStateOne) .set(CatAccessor::invoker$setRelaxStateOne); + // @formatter:on + final var cat = registrator.asMutable(Cat.class); + final var components = EntityDataProviders.of( + EntityDataProviders.holderOf(Keys.CAT_TYPE, DataComponents.CAT_VARIANT, Registries.CAT_VARIANT), + EntityDataProviders.enumOf(Keys.DYE_COLOR, DataComponents.CAT_COLLAR) + ); + components.forEach(p -> p.applyToRegistrator(cat)); } - // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java b/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java index 04e8dfd8bae..7284546024b 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/ChickenData.java @@ -48,6 +48,11 @@ public static void register(final DataProviderRegistrator registrator) { h.eggTime = ticks; return true; }); + // @formatter:on + final var chicken = registrator.asMutable(Chicken.class); + final var components = EntityDataProviders.of( + // TODO - EitherHolder is a different kind of thing +// EntityDataProviders.eitherHolderOf() + ); } - // @formatter:on } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java index 69937fac579..12360b391a8 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityData.java @@ -25,6 +25,7 @@ package org.spongepowered.common.data.provider.entity; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; +import net.minecraft.core.component.DataComponents; import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.LivingEntity; import net.minecraft.world.entity.PortalProcessor; @@ -81,13 +82,6 @@ public static void register(final DataProviderRegistrator registrator) { } return (org.spongepowered.api.entity.Entity) rootVehicle; }) - .create(Keys.CUSTOM_NAME) - .get(h -> h.hasCustomName() ? SpongeAdventure.asAdventure(h.getCustomName()) : null) - .set((h, v) -> h.setCustomName(SpongeAdventure.asVanilla(v))) - .delete(h -> { - h.setCustomName(null); - h.setCustomNameVisible(false); - }) .create(Keys.DISPLAY_NAME) .get(h -> SpongeAdventure.asAdventure(h.getDisplayName())) .create(Keys.EYE_HEIGHT) @@ -266,6 +260,17 @@ public static void register(final DataProviderRegistrator registrator) { dv -> dv.getString(Constants.Entity.CUSTOM_NAME).map(GsonComponentSerializer.gson()::deserialize)); // @formatter:on + final var entity = registrator.asMutable(Entity.class); + final var components = EntityDataProviders.of( + EntityDataProviders.optionalTransformed(Keys.CUSTOM_NAME, DataComponents.CUSTOM_NAME, SpongeAdventure::asAdventure, SpongeAdventure::asVanilla), + EntityDataProviders.deleter(Keys.CUSTOM_NAME, h -> { + h.setCustomName(null); + h.setCustomNameVisible(false); + }) + ); + for (var provider : components) { + provider.applyToRegistrator(entity); + } } } diff --git a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java index 456a124c748..536f27d8354 100644 --- a/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java +++ b/src/main/java/org/spongepowered/common/data/provider/entity/EntityDataProviders.java @@ -29,17 +29,25 @@ import net.minecraft.core.component.DataComponentType; import net.minecraft.resources.ResourceKey; import net.minecraft.world.entity.Entity; +import org.checkerframework.checker.nullness.qual.Nullable; +import org.spongepowered.api.data.DataTransactionResult; import org.spongepowered.api.data.Key; +import org.spongepowered.api.data.Keys; import org.spongepowered.api.data.value.Value; import org.spongepowered.api.registry.DefaultedRegistryValue; +import org.spongepowered.common.adventure.SpongeAdventure; import org.spongepowered.common.data.provider.DataProviderRegistrator; import org.spongepowered.common.data.provider.DataProviderRegistratorBuilder; import java.util.List; +import java.util.Optional; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; public final class EntityDataProviders extends DataProviderRegistratorBuilder { - public sealed interface KeyComponentProvider { + public sealed interface KeyComponentProvider { void applyToRegistrator(DataProviderRegistrator.MutableRegistrator registrator); } @@ -47,6 +55,40 @@ public sealed interface KeyComponentProvider KeyComponentProvider transformed( + Key> apiKey, + DataComponentType componentType, + Function getter, + Function setter + ) { + return new FunctionalProvider<>(apiKey, componentType, getter, setter); + } + + public static KeyComponentProvider transformedWith( + Key> apiKey, + DataComponentType componentType, + Function getter, + BiFunction setter + ) { + return new BiFunctionProvider<>(apiKey, componentType, getter, setter); + } + + public static KeyComponentProvider optionalTransformed( + Key> apiKey, + DataComponentType componentType, + Function getter, + Function setter + ) { + return new OptionalFunctionProvider<>(apiKey, componentType, getter, setter); + } + + public static KeyComponentProvider deleter( + Key> apiKey, + Consumer deleter + ) { + return new DeletionProvider<>(apiKey, deleter); + } + public static KeyComponentProvider holderOf( Key> apiKey, DataComponentType> componentType, @@ -62,9 +104,62 @@ public static > KeyCompone return new EnumProvider<>(apiKey, componentType); } + record DeletionProvider( + Key> apiKey, + Consumer deleter + ) implements KeyComponentProvider { + public void applyToRegistrator(DataProviderRegistrator.MutableRegistrator registrator) { + registrator.create(this.apiKey) + .delete(deleter::accept); + } + } + + record FunctionalProvider( + Key> apiKey, + DataComponentType componentType, + Function getter, + Function setter + ) implements KeyComponentProvider { + public void applyToRegistrator(DataProviderRegistrator.MutableRegistrator registrator) { + registrator.create(this.apiKey) + .get(h -> this.getter.apply(h.get(this.componentType))) + .set((h, v) -> h.setComponent(this.componentType, this.setter.apply(v))); + } + } + + record BiFunctionProvider( + Key> apiKey, + DataComponentType componentType, + Function getter, + BiFunction setter + ) implements KeyComponentProvider { + public void applyToRegistrator(DataProviderRegistrator.MutableRegistrator registrator) { + registrator.create(this.apiKey) + .get(h -> this.getter.apply(h.get(this.componentType))) + .set((h, v) -> { + final var existing = h.get(this.componentType); + final var newValue = this.setter.apply(v, existing); + h.setComponent(this.componentType, newValue); + }); + } + } + + record OptionalFunctionProvider( + Key> apiKey, + DataComponentType componentType, + Function getter, + Function setter + ) implements KeyComponentProvider { + public void applyToRegistrator(DataProviderRegistrator.MutableRegistrator registrator) { + registrator.create(this.apiKey) + .get(h -> Optional.ofNullable(h.get(this.componentType)).map(this.getter).orElse(null)) + .set((h, v) -> h.setComponent(this.componentType, v == null ? null : this.setter.apply(v))); + } + } + @SuppressWarnings("unchecked") record HolderProvider( - Key> apiKey, + Key> apiKey, DataComponentType> componentType, ResourceKey> resourceKey ) implements KeyComponentProvider { @@ -85,7 +180,7 @@ public void applyToRegistrator(DataProviderRegistrator.Mutabl @SuppressWarnings("unchecked") record EnumProvider>( - Key> apiKey, + Key> apiKey, DataComponentType componentType ) implements KeyComponentProvider { public void applyToRegistrator(DataProviderRegistrator.MutableRegistrator registrator) {