From 1b4b3d3b2843372a61bc3838852f7a3eba43d9d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hasan=20Demirta=C5=9F?= Date: Sun, 13 Oct 2024 17:54:31 +0300 Subject: [PATCH] experimental model type. (#19) --- .../net/infumia/pack/FileResourceUnknown.java | 20 +++ .../java/net/infumia/pack/FileResources.java | 12 ++ .../net/infumia/pack/ResourceProducers.java | 18 +- .../net/infumia/pack/PackReferencePart.java | 1 + .../infumia/pack/PackReferencePartImage.java | 2 +- .../infumia/pack/PackReferencePartModel.java | 159 ++++++++++++++++++ gradle/libs.versions.toml | 1 - 7 files changed, 207 insertions(+), 6 deletions(-) create mode 100644 common/src/main/java/net/infumia/pack/FileResourceUnknown.java create mode 100644 generator/src/main/java/net/infumia/pack/PackReferencePartModel.java diff --git a/common/src/main/java/net/infumia/pack/FileResourceUnknown.java b/common/src/main/java/net/infumia/pack/FileResourceUnknown.java new file mode 100644 index 0000000..6e3d117 --- /dev/null +++ b/common/src/main/java/net/infumia/pack/FileResourceUnknown.java @@ -0,0 +1,20 @@ +package net.infumia.pack; + +import team.unnamed.creative.ResourcePack; +import team.unnamed.creative.base.Writable; + +final class FileResourceUnknown implements FileResource { + + final String path; + final Writable writable; + + FileResourceUnknown(final String path, final Writable writable) { + this.path = path; + this.writable = writable; + } + + @Override + public void write(final ResourcePack pack) { + pack.unknownFile(this.path, this.writable); + } +} diff --git a/common/src/main/java/net/infumia/pack/FileResources.java b/common/src/main/java/net/infumia/pack/FileResources.java index 5cc6bb4..17743a6 100644 --- a/common/src/main/java/net/infumia/pack/FileResources.java +++ b/common/src/main/java/net/infumia/pack/FileResources.java @@ -3,6 +3,7 @@ import java.util.Arrays; import java.util.Collection; import team.unnamed.creative.atlas.Atlas; +import team.unnamed.creative.base.Writable; import team.unnamed.creative.font.Font; import team.unnamed.creative.model.Model; import team.unnamed.creative.texture.Texture; @@ -52,6 +53,17 @@ public static FileResource model(final Model model) { return new FileResourceModel(model); } + /** + * Creates a {@link FileResource} for the specified path and writable data. + * + * @param path the path to create a file resource for. Cannot be null. + * @param writable the writable to create a file resource for. Cannot be null. + * @return a {@link FileResource} representing the unknown file. + */ + public static FileResource unknown(final String path, final Writable writable) { + return new FileResourceUnknown(path, writable); + } + /** * Creates a {@link FileResource} for a collection of file resources. * diff --git a/common/src/main/java/net/infumia/pack/ResourceProducers.java b/common/src/main/java/net/infumia/pack/ResourceProducers.java index 2b63aee..a81a0ba 100644 --- a/common/src/main/java/net/infumia/pack/ResourceProducers.java +++ b/common/src/main/java/net/infumia/pack/ResourceProducers.java @@ -84,10 +84,10 @@ public static GlyphImage image( /** * Creates an item resource with the specified parameters. * - * @param itemKey The key for the item. Cannot be null. - * @param overriddenItemKey The key for the base model. Cannot be null. - * @param itemImage The writable image for the blank slot. Cannot be null. - * @param customModelData The custom model data value. + * @param itemKey The key for the item. Cannot be null. + * @param overriddenItemKey The key for the base model. Cannot be null. + * @param itemImage The writable image for the blank slot. Cannot be null. + * @param customModelData The custom model data value. * @return A {@link FileResource} representing the created item. */ public static FileResource item( @@ -130,6 +130,16 @@ public static FileResource item( ); } + /** + * Creates a model resource with the specified parameters. + * + * @param key The key for the item. Cannot be null. + * @return A {@link FileResource} representing the created model. + */ + public static FileResource model(final Key key) { + return FileResources.model(Model.model().key(key).build()); + } + private ResourceProducers() { throw new IllegalStateException("Utility class"); } diff --git a/generator/src/main/java/net/infumia/pack/PackReferencePart.java b/generator/src/main/java/net/infumia/pack/PackReferencePart.java index 2aab1dd..01661c2 100644 --- a/generator/src/main/java/net/infumia/pack/PackReferencePart.java +++ b/generator/src/main/java/net/infumia/pack/PackReferencePart.java @@ -13,6 +13,7 @@ { @JsonSubTypes.Type(value = PackReferencePartImage.class, name = "image"), @JsonSubTypes.Type(value = PackReferencePartItem.class, name = "item"), + @JsonSubTypes.Type(value = PackReferencePartModel.class, name = "model"), } ) public abstract class PackReferencePart { diff --git a/generator/src/main/java/net/infumia/pack/PackReferencePartImage.java b/generator/src/main/java/net/infumia/pack/PackReferencePartImage.java index aefe3ee..6025305 100644 --- a/generator/src/main/java/net/infumia/pack/PackReferencePartImage.java +++ b/generator/src/main/java/net/infumia/pack/PackReferencePartImage.java @@ -37,7 +37,7 @@ public void add(final PackGeneratorContext context) { context .pack() .with( - (ResourceIdentifierImage) () -> key.value(), + (ResourceIdentifierImage) key::value, ResourceProducers.image( Font.MINECRAFT_DEFAULT, Texture.texture( diff --git a/generator/src/main/java/net/infumia/pack/PackReferencePartModel.java b/generator/src/main/java/net/infumia/pack/PackReferencePartModel.java new file mode 100644 index 0000000..a5b626d --- /dev/null +++ b/generator/src/main/java/net/infumia/pack/PackReferencePartModel.java @@ -0,0 +1,159 @@ +package net.infumia.pack; + +import com.fasterxml.jackson.annotation.JsonProperty; +import java.nio.file.Path; +import java.util.List; +import java.util.Locale; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.stream.Collectors; +import net.kyori.adventure.key.Key; +import team.unnamed.creative.base.Writable; +import team.unnamed.creative.model.ItemOverride; +import team.unnamed.creative.model.ItemPredicate; +import team.unnamed.creative.model.Model; +import team.unnamed.creative.model.ModelTexture; +import team.unnamed.creative.model.ModelTextures; +import team.unnamed.creative.texture.Texture; + +/** + * Represents a model part of a pack reference. + */ +public final class PackReferencePartModel extends PackReferencePart { + + @JsonProperty + private String namespace; + + @JsonProperty(required = true) + private String key; + + @JsonProperty(required = true) + private List textures; + + @JsonProperty(required = true) + private String model; + + @JsonProperty(value = "custom-model-data") + private Integer customModelData; + + @JsonProperty("overridden-namespace") + private String overriddenNamespace; + + @JsonProperty(value = "overridden-key", required = true) + private String overriddenKey; + + private Path directory; + + @Override + public void add(final PackGeneratorContext context) { + final Key key = this.extractKey(context); + final Key overriddenItemKey; + if (this.overriddenNamespace == null) { + overriddenItemKey = Key.key(this.overriddenKey); + } else { + overriddenItemKey = Key.key(this.overriddenNamespace, this.overriddenKey); + } + + context + .pack() + .with( + FileResources.all( + this.textures.stream() + .map(texture -> { + final String path = this.parent(context) + texture; + return FileResources.texture( + Texture.texture( + Key.key(key.namespace(), path), + Writable.path(context.rootDirectory().resolve(path)) + ) + ); + }) + .collect(Collectors.toList()) + ) + ); + final String path = this.parent(context) + this.model; + context + .pack() + .with( + FileResources.unknown( + "assets/" + key.namespace() + "/models/" + path, + Writable.path(context.rootDirectory().resolve(path)) + ) + ); + context + .pack() + .with( + FileResources.model( + Model.model() + .key(overriddenItemKey) + .parent(Model.ITEM_GENERATED) + .textures( + ModelTextures.builder() + .layers(ModelTexture.ofKey(overriddenItemKey)) + .build() + ) + .overrides( + ItemOverride.of( + key, + ItemPredicate.customModelData(this.customModelData(context)) + ) + ) + .build() + ) + ); + } + + @Override + PackReferencePartModel directory(final Path directory) { + this.directory = directory; + return this; + } + + @Override + Key extractKey(final PackGeneratorContext context) { + final String namespace = this.namespace == null + ? context.packReference().defaultNamespace() + : this.namespace; + if (namespace == null) { + throw new IllegalStateException("Pack reference namespace cannot be null!"); + } + return Key.key(namespace, this.parent(context) + this.key); + } + + private String parent(final PackGeneratorContext context) { + if (this.directory == null) { + return ""; + } + return ( + context + .rootDirectory() + .relativize(this.directory) + .toString() + .toLowerCase(Locale.ROOT) + .replace("\\", "/") + .replace(" ", "_") + + "/" + ); + } + + private int customModelData(final PackGeneratorContext context) { + if (this.customModelData != null) { + return this.customModelData; + } + + final Integer offset = context.packReference().customModelDataOffset(); + if (offset == null) { + throw new IllegalStateException( + String.format( + "Custom model data offset cannot be null when custom-model-data not specified (%s)!", + this.extractKey(context) + ) + ); + } + + final AtomicInteger lastCustomModelData = context.lastCustomModelData(); + if (offset > lastCustomModelData.get()) { + lastCustomModelData.set(offset); + } + return lastCustomModelData.getAndIncrement(); + } +} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index d6ebe00..d1f3bfc 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,7 +2,6 @@ creative = "1.7.3" [libraries] -adventure-api = { module = "net.kyori:adventure-api", version = "4.17.0" } creative-api = { module = "team.unnamed:creative-api", version.ref = "creative" } creative-serializer = { module = "team.unnamed:creative-serializer-minecraft", version.ref = "creative" }