From b3578c1064ebfe1de0b4e46dfa5b82fc94b9caf0 Mon Sep 17 00:00:00 2001 From: Intybyte Date: Thu, 11 Dec 2025 18:03:23 +0100 Subject: [PATCH 1/2] Serializers and tests --- api-internal/pom.xml | 24 ++++++++ .../adapters/CannonSerializingManager.java | 12 ++++ .../CustomProjectileDefinitionSerializer.java | 51 +++++++++++++++++ .../internal/adapters/KeySerializer.java | 28 +++++++++ .../CustomProjectileDefinition.java | 57 ++++++------------- .../DefaultProjectileDefinition.java | 18 +++--- .../adapters/BuilderTypeSerializerTest.java | 52 +++++++++++++++++ 7 files changed, 194 insertions(+), 48 deletions(-) create mode 100644 api-internal/src/main/java/at/pavlov/internal/adapters/CannonSerializingManager.java create mode 100644 api-internal/src/main/java/at/pavlov/internal/adapters/CustomProjectileDefinitionSerializer.java create mode 100644 api-internal/src/main/java/at/pavlov/internal/adapters/KeySerializer.java create mode 100644 api-internal/src/test/java/adapters/BuilderTypeSerializerTest.java diff --git a/api-internal/pom.xml b/api-internal/pom.xml index f4df5edd..e733e895 100644 --- a/api-internal/pom.xml +++ b/api-internal/pom.xml @@ -16,6 +16,16 @@ + + org.spongepowered + configurate-core + 4.2.0 + + + org.spongepowered + configurate-yaml + 4.2.0 + com.google.code.gson gson @@ -33,6 +43,20 @@ 1.18.30 provided + + + + org.junit.jupiter + junit-jupiter + 5.11.4 + test + + + org.mockito + mockito-core + 5.18.0 + test + diff --git a/api-internal/src/main/java/at/pavlov/internal/adapters/CannonSerializingManager.java b/api-internal/src/main/java/at/pavlov/internal/adapters/CannonSerializingManager.java new file mode 100644 index 00000000..745fac8e --- /dev/null +++ b/api-internal/src/main/java/at/pavlov/internal/adapters/CannonSerializingManager.java @@ -0,0 +1,12 @@ +package at.pavlov.internal.adapters; + +import at.pavlov.internal.Key; +import at.pavlov.internal.projectile.definition.CustomProjectileDefinition; +import org.spongepowered.configurate.serialize.TypeSerializerCollection; + +public class CannonSerializingManager { + public static final TypeSerializerCollection serializerCollection = TypeSerializerCollection.defaults().childBuilder() + .register(Key.class, new KeySerializer()) + .register(CustomProjectileDefinition.class, new CustomProjectileDefinitionSerializer()) + .build(); +} diff --git a/api-internal/src/main/java/at/pavlov/internal/adapters/CustomProjectileDefinitionSerializer.java b/api-internal/src/main/java/at/pavlov/internal/adapters/CustomProjectileDefinitionSerializer.java new file mode 100644 index 00000000..e8bc133f --- /dev/null +++ b/api-internal/src/main/java/at/pavlov/internal/adapters/CustomProjectileDefinitionSerializer.java @@ -0,0 +1,51 @@ +package at.pavlov.internal.adapters; + +import at.pavlov.internal.Key; +import at.pavlov.internal.key.registries.Registries; +import at.pavlov.internal.projectile.definition.CustomProjectileDefinition; +import at.pavlov.internal.projectile.definition.ProjectilePhysics; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.configurate.ConfigurationNode; +import org.spongepowered.configurate.serialize.SerializationException; +import org.spongepowered.configurate.serialize.TypeSerializer; + +import java.lang.reflect.Type; + +public class CustomProjectileDefinitionSerializer implements TypeSerializer { + + @Override + public CustomProjectileDefinition deserialize(@NotNull Type type, ConfigurationNode node) throws SerializationException { + // Use the node's key as the projectile key + Key key = Key.from(node.key().toString()); // top-level key + Key entityKey = Key.from(node.node("entity").getString("SNOWBALL")); + + // Get default projectile physics if entityKey not registered + ProjectilePhysics dpd = Registries.DEFAULT_PROJECTILE_DEFINITION_REGISTRY.of(entityKey); + if (dpd == null) { + dpd = ProjectilePhysics.DEFAULT; + } + + // Build the CustomProjectileDefinition + return CustomProjectileDefinition.builder() + .key(key) + .entityKey(entityKey) + .constantAcceleration(node.node("constantAcceleration").get(Double.class, dpd.getConstantAcceleration())) + .gravity(node.node("gravity").getDouble(dpd.getGravity())) + .drag(node.node("drag").getDouble(dpd.getDrag())) + .waterDrag(node.node("waterDrag").getDouble(dpd.getWaterDrag())) + .glowing(node.node("glowing").getBoolean(false)) + .onFire(node.node("onFire").getBoolean(false)) + .charged(node.node("charged").getBoolean(false)) + .critical(node.node("critical").getBoolean(false)) + .material(Key.from(node.node("material").getString("SNOWBALL"))) + .customModelData(node.node("customModelData").get(Integer.class, (Integer) null)) + .build(); + } + + @Override + public void serialize(@NotNull Type type, CustomProjectileDefinition obj, @NotNull ConfigurationNode node) throws SerializationException { + // Not needed, can throw UnsupportedOperationException if you never serialize + throw new UnsupportedOperationException("Serialization not supported for this deserializer"); + } +} + diff --git a/api-internal/src/main/java/at/pavlov/internal/adapters/KeySerializer.java b/api-internal/src/main/java/at/pavlov/internal/adapters/KeySerializer.java new file mode 100644 index 00000000..e51f7b1e --- /dev/null +++ b/api-internal/src/main/java/at/pavlov/internal/adapters/KeySerializer.java @@ -0,0 +1,28 @@ +package at.pavlov.internal.adapters; + +import at.pavlov.internal.Key; +import org.jetbrains.annotations.NotNull; +import org.spongepowered.configurate.ConfigurationNode; +import org.spongepowered.configurate.serialize.SerializationException; +import org.spongepowered.configurate.serialize.TypeSerializer; + +import java.lang.reflect.Type; + +public class KeySerializer implements TypeSerializer { + + @Override + public Key deserialize(@NotNull Type type, ConfigurationNode node) throws SerializationException { + String value = node.getString(); + if (value == null || !value.contains(":")) { + throw new SerializationException("Invalid Key format, expected namespace:key"); + } + String[] parts = value.split(":", 2); + return new Key(parts[0], parts[1]); + } + + @Override + public void serialize(@NotNull Type type, Key obj, @NotNull ConfigurationNode node) throws SerializationException { + if (obj == null) return; + node.set(obj.full()); + } +} diff --git a/api-internal/src/main/java/at/pavlov/internal/projectile/definition/CustomProjectileDefinition.java b/api-internal/src/main/java/at/pavlov/internal/projectile/definition/CustomProjectileDefinition.java index b3a3971a..2187bc4f 100644 --- a/api-internal/src/main/java/at/pavlov/internal/projectile/definition/CustomProjectileDefinition.java +++ b/api-internal/src/main/java/at/pavlov/internal/projectile/definition/CustomProjectileDefinition.java @@ -1,56 +1,33 @@ package at.pavlov.internal.projectile.definition; import at.pavlov.internal.Key; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; +import lombok.*; import org.jetbrains.annotations.Nullable; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; @Getter @Builder +@EqualsAndHashCode +@ConfigSerializable +@NoArgsConstructor @AllArgsConstructor public class CustomProjectileDefinition implements ProjectilePhysics { - private final Key key; // for the name of the custom projectile definition - private final Key entityKey; + private Key key; // for the name of the custom projectile definition + private Key entityKey; - private final Double constantAcceleration; + private Double constantAcceleration; - private final double gravity; - private final double drag; - private final double waterDrag; + private double gravity; + private double drag; + private double waterDrag; - private final boolean glowing; + private boolean glowing; - private final boolean onFire; // visual fire for projectile - private final boolean charged; // works for wither skeletons - private final boolean critical; // for arrows and tridents + private boolean onFire; // visual fire for projectile + private boolean charged; // works for wither skeletons + private boolean critical; // for arrows and tridents //for throwable projectiles only - private final @Nullable Key material; - private final @Nullable Integer customModelData; - - /* - @Override - public double getGravity() { - return fromKey().getGravity(); - } - - @Override - public double getDrag() { - return fromKey().getDrag(); - } - - @Override - public double getWaterDrag() { - return fromKey().getWaterDrag(); - } - - private @NotNull ProjectilePhysics fromKey() { - DefaultProjectileDefinition value = Registries.DEFAULT_PROJECTILE_DEFINITION_REGISTRY.of(entityKey); - if (value == null) { - return ProjectilePhysics.DEFAULT; - } - - return value; - }*/ + private @Nullable Key material; + private @Nullable Integer customModelData; } diff --git a/api-internal/src/main/java/at/pavlov/internal/projectile/definition/DefaultProjectileDefinition.java b/api-internal/src/main/java/at/pavlov/internal/projectile/definition/DefaultProjectileDefinition.java index 4051e26c..cc387cf0 100644 --- a/api-internal/src/main/java/at/pavlov/internal/projectile/definition/DefaultProjectileDefinition.java +++ b/api-internal/src/main/java/at/pavlov/internal/projectile/definition/DefaultProjectileDefinition.java @@ -1,20 +1,22 @@ package at.pavlov.internal.projectile.definition; import at.pavlov.internal.Key; -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.Getter; +import lombok.*; import org.jetbrains.annotations.NotNull; +import org.spongepowered.configurate.objectmapping.ConfigSerializable; @Getter @Builder +@ConfigSerializable +@EqualsAndHashCode +@NoArgsConstructor @AllArgsConstructor public class DefaultProjectileDefinition implements ProjectilePhysics { - private final @NotNull Key key; // for the entity type - private final Double constantAcceleration; - private final double gravity; - private final double drag; - private final double waterDrag; + private @NotNull Key key; // for the entity type + private Double constantAcceleration; + private double gravity; + private double drag; + private double waterDrag; @Override public Key getEntityKey() { diff --git a/api-internal/src/test/java/adapters/BuilderTypeSerializerTest.java b/api-internal/src/test/java/adapters/BuilderTypeSerializerTest.java new file mode 100644 index 00000000..31170ab1 --- /dev/null +++ b/api-internal/src/test/java/adapters/BuilderTypeSerializerTest.java @@ -0,0 +1,52 @@ +package adapters; + +import at.pavlov.internal.Key; +import at.pavlov.internal.adapters.CannonSerializingManager; +import at.pavlov.internal.projectile.definition.DefaultProjectileDefinition; +import org.junit.jupiter.api.Test; +import org.spongepowered.configurate.ConfigurationNode; +import org.spongepowered.configurate.yaml.YamlConfigurationLoader; + +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +public class BuilderTypeSerializerTest { + + @Test + void testBuilderSerialization() throws Exception { + // Create temp file for YAML loader + Path tempFile = Files.createTempFile("test", ".yml"); + + // Create YAML loader with custom serializers + YamlConfigurationLoader loader = YamlConfigurationLoader.builder() + .path(tempFile) + .defaultOptions(options -> options.serializers(CannonSerializingManager.serializerCollection)) + .build(); + + // Create an instance using the builder + DefaultProjectileDefinition original = DefaultProjectileDefinition.builder() + .key(Key.mc("test")) + .drag(2.1) + .constantAcceleration(1.2) + .waterDrag(2.4) + .gravity(-1.4) + .build(); + + // Serialize to a ConfigurationNode + ConfigurationNode node = loader.createNode(); + node.set(original); + + // Optionally, print YAML for debugging + System.out.println(node); + + // Deserialize back + DefaultProjectileDefinition deserialized = node.get(DefaultProjectileDefinition.class); + + // Basic assertions + assertNotNull(deserialized, "Deserialized object should not be null"); + assertEquals(original, deserialized, "Deserialized object should be equal to original"); + } +} From b3c9d28762a0456b6adeec0daa5f42875af46e13 Mon Sep 17 00:00:00 2001 From: Intybyte Date: Fri, 12 Dec 2025 19:11:34 +0100 Subject: [PATCH 2/2] Correct testing --- .../adapters/BuilderTypeSerializerTest.java | 52 ------------------- ...tomProjectileDefinitionSerializerTest.java | 11 ++++ 2 files changed, 11 insertions(+), 52 deletions(-) delete mode 100644 api-internal/src/test/java/adapters/BuilderTypeSerializerTest.java create mode 100644 api-internal/src/test/java/adapters/CustomProjectileDefinitionSerializerTest.java diff --git a/api-internal/src/test/java/adapters/BuilderTypeSerializerTest.java b/api-internal/src/test/java/adapters/BuilderTypeSerializerTest.java deleted file mode 100644 index 31170ab1..00000000 --- a/api-internal/src/test/java/adapters/BuilderTypeSerializerTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package adapters; - -import at.pavlov.internal.Key; -import at.pavlov.internal.adapters.CannonSerializingManager; -import at.pavlov.internal.projectile.definition.DefaultProjectileDefinition; -import org.junit.jupiter.api.Test; -import org.spongepowered.configurate.ConfigurationNode; -import org.spongepowered.configurate.yaml.YamlConfigurationLoader; - -import java.nio.file.Files; -import java.nio.file.Path; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -public class BuilderTypeSerializerTest { - - @Test - void testBuilderSerialization() throws Exception { - // Create temp file for YAML loader - Path tempFile = Files.createTempFile("test", ".yml"); - - // Create YAML loader with custom serializers - YamlConfigurationLoader loader = YamlConfigurationLoader.builder() - .path(tempFile) - .defaultOptions(options -> options.serializers(CannonSerializingManager.serializerCollection)) - .build(); - - // Create an instance using the builder - DefaultProjectileDefinition original = DefaultProjectileDefinition.builder() - .key(Key.mc("test")) - .drag(2.1) - .constantAcceleration(1.2) - .waterDrag(2.4) - .gravity(-1.4) - .build(); - - // Serialize to a ConfigurationNode - ConfigurationNode node = loader.createNode(); - node.set(original); - - // Optionally, print YAML for debugging - System.out.println(node); - - // Deserialize back - DefaultProjectileDefinition deserialized = node.get(DefaultProjectileDefinition.class); - - // Basic assertions - assertNotNull(deserialized, "Deserialized object should not be null"); - assertEquals(original, deserialized, "Deserialized object should be equal to original"); - } -} diff --git a/api-internal/src/test/java/adapters/CustomProjectileDefinitionSerializerTest.java b/api-internal/src/test/java/adapters/CustomProjectileDefinitionSerializerTest.java new file mode 100644 index 00000000..eba7c738 --- /dev/null +++ b/api-internal/src/test/java/adapters/CustomProjectileDefinitionSerializerTest.java @@ -0,0 +1,11 @@ +package adapters; + +import org.junit.jupiter.api.Test; + +public class CustomProjectileDefinitionSerializerTest { + + @Test + void deserialize() throws Exception { + // todo: make testing + } +}