From 36bfa6d62512fb2d2a2918e4536c5755a40ab7d7 Mon Sep 17 00:00:00 2001 From: Aurora Date: Thu, 3 Jul 2025 19:23:44 +0100 Subject: [PATCH 1/2] Add texts support, includes API, reading and writing, and some documentation --- .../creative/overlay/ResourceContainer.java | 29 +++++++++++++++++++ .../overlay/ResourceContainerImpl.java | 20 +++++++++++++ docs/texts.md | 25 ++++++++++++++++ .../MinecraftResourcePackReaderImpl.java | 7 +++++ .../MinecraftResourcePackStructure.java | 1 + .../MinecraftResourcePackWriterImpl.java | 10 +++++++ 6 files changed, 92 insertions(+) create mode 100644 docs/texts.md diff --git a/api/src/main/java/team/unnamed/creative/overlay/ResourceContainer.java b/api/src/main/java/team/unnamed/creative/overlay/ResourceContainer.java index 6c2d10c0..557c7c23 100644 --- a/api/src/main/java/team/unnamed/creative/overlay/ResourceContainer.java +++ b/api/src/main/java/team/unnamed/creative/overlay/ResourceContainer.java @@ -28,6 +28,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import team.unnamed.creative.atlas.Atlas; +import team.unnamed.creative.base.Readable; import team.unnamed.creative.base.Writable; import team.unnamed.creative.blockstate.BlockState; import team.unnamed.creative.equipment.Equipment; @@ -677,6 +678,34 @@ default void part(final @NotNull ResourcePackPart part) { part.addTo(this); } + //#region Texts (Keyed) + /** + * Sets a texts file in this resource container. + * + * @param content The content of the text to add into the pack + * @since 1.8.4 + */ + void texts(final @NotNull Key key, final @NotNull Writable content); + + /** + * Gets the text with the given key. + * + * @param key The text key + * @return The text, null if not found + * @since 1.8.4 + */ + @Nullable Writable texts(final @NotNull Key key); + + /** + * Gets all the texts in this resource container. + * The returned map cannot be modified. + * + * @return The texts + * @since 1.8.4 + */ + @NotNull Map texts(); + //#endregion + //#region Unknown Files (By path, relative to current's resource container) /** diff --git a/api/src/main/java/team/unnamed/creative/overlay/ResourceContainerImpl.java b/api/src/main/java/team/unnamed/creative/overlay/ResourceContainerImpl.java index 36267f36..725bf9c0 100644 --- a/api/src/main/java/team/unnamed/creative/overlay/ResourceContainerImpl.java +++ b/api/src/main/java/team/unnamed/creative/overlay/ResourceContainerImpl.java @@ -29,6 +29,7 @@ import org.jetbrains.annotations.Nullable; import team.unnamed.creative.atlas.Atlas; import team.unnamed.creative.atlas.AtlasSource; +import team.unnamed.creative.base.Readable; import team.unnamed.creative.base.Writable; import team.unnamed.creative.blockstate.BlockState; import team.unnamed.creative.equipment.Equipment; @@ -49,6 +50,7 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -70,6 +72,7 @@ public class ResourceContainerImpl implements ResourceContainer { private final Map soundRegistries = new LinkedHashMap<>(); private final Map sounds = new LinkedHashMap<>(); private final Map textures = new LinkedHashMap<>(); + private final Map texts = new LinkedHashMap<>(); // Unknown files we don't know how to parse private final Map files = new LinkedHashMap<>(); @@ -324,6 +327,23 @@ public boolean removeTexture(final @NotNull Key key) { } //#endregion + //#region Texts + @Override + public void texts(final @NotNull Key key, final @NotNull Writable splashTexts) { + this.texts.put(key, splashTexts); + } + + @Override + public @Nullable Writable texts(@NotNull Key key) { + return this.texts.get(key); + } + + @Override + public @NotNull Map texts() { + return Collections.unmodifiableMap(this.texts); + } + //#endregion + //#region Unknown Files (By absolute path) @Override public void unknownFile(final @NotNull String path, final @NotNull Writable data) { diff --git a/docs/texts.md b/docs/texts.md new file mode 100644 index 00000000..2982829b --- /dev/null +++ b/docs/texts.md @@ -0,0 +1,25 @@ +## Texts + +Minecraft supports modifying texts that appear in-game. This +includes various texts such as splash texts, end text and the credits. + +### Interacting with texts + +Interacting with texts can be done by either adding texts or reading them. +Below is an example with splash texts. + + +```java +// Reading... +Writable content = pack.texts(Key.key(Key.MINECRAFT_NAMESPACE, "splashes")); + +List texts = content.toUTF8String().split("\n"); + +// Writing... +pack.texts( + Key.key(Key.MINECRAFT_NAMESPACE, "splashes"), + Writable.stringUtf8(String.join("\n", texts)) +); +``` + + diff --git a/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackReaderImpl.java b/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackReaderImpl.java index 1d563df3..57f0abb7 100644 --- a/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackReaderImpl.java +++ b/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackReaderImpl.java @@ -268,6 +268,13 @@ private MinecraftResourcePackReaderImpl( )); } } + } else if (categoryName.equals(TEXTS_FOLDER)) { + String textKey = withoutExtension(categoryPath, TEXT_EXTENSION); + if (textKey != null) { + Key key = Key.key(namespace, textKey); + + container.texts(key, reader.content().asWritable()); + } } else { // get the resource category, if the local pack format (overlay or root) is the same as the // root pack format, we can use the previously computed map, otherwise we need to compute it diff --git a/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackStructure.java b/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackStructure.java index 26a5569d..f9b9d04e 100644 --- a/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackStructure.java +++ b/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackStructure.java @@ -41,6 +41,7 @@ public final class MinecraftResourcePackStructure { public static final String TEXTURE_EXTENSION = ".png"; public static final String METADATA_EXTENSION = ".mcmeta"; public static final String OBJECT_EXTENSION = ".json"; + public static final String TEXT_EXTENSION = ".txt"; public static final String FILE_SEPARATOR = "/"; diff --git a/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackWriterImpl.java b/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackWriterImpl.java index 753c45d6..24d5c648 100644 --- a/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackWriterImpl.java +++ b/serializer-minecraft/src/main/java/team/unnamed/creative/serialize/minecraft/MinecraftResourcePackWriterImpl.java @@ -24,6 +24,7 @@ package team.unnamed.creative.serialize.minecraft; import com.google.gson.stream.JsonWriter; +import net.kyori.adventure.key.Key; import net.kyori.adventure.key.Keyed; import org.jetbrains.annotations.NotNull; import team.unnamed.creative.ResourcePack; @@ -48,6 +49,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.UncheckedIOException; +import java.util.Collection; import java.util.HashMap; import java.util.Map; @@ -132,6 +134,14 @@ private void writeWithBasePathAndTargetPackFormat(FileTreeWriter target, Resourc } } + // write texts + for (Map.Entry text : container.texts().entrySet()) { + target.write( + String.format("%sassets/%s/texts/%s.txt", basePath, text.getKey().namespace(), text.getKey().value()), + text.getValue() + ); + } + // write unknown files for (Map.Entry entry : container.unknownFiles().entrySet()) { target.write(basePath + entry.getKey(), entry.getValue()); From a6e8d72764915fc081e20f904157aa5006315154 Mon Sep 17 00:00:00 2001 From: Aurora Date: Thu, 3 Jul 2025 19:25:28 +0100 Subject: [PATCH 2/2] Remove Readable imports --- .../java/team/unnamed/creative/overlay/ResourceContainer.java | 1 - .../team/unnamed/creative/overlay/ResourceContainerImpl.java | 1 - 2 files changed, 2 deletions(-) diff --git a/api/src/main/java/team/unnamed/creative/overlay/ResourceContainer.java b/api/src/main/java/team/unnamed/creative/overlay/ResourceContainer.java index 557c7c23..ac7a3e05 100644 --- a/api/src/main/java/team/unnamed/creative/overlay/ResourceContainer.java +++ b/api/src/main/java/team/unnamed/creative/overlay/ResourceContainer.java @@ -28,7 +28,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import team.unnamed.creative.atlas.Atlas; -import team.unnamed.creative.base.Readable; import team.unnamed.creative.base.Writable; import team.unnamed.creative.blockstate.BlockState; import team.unnamed.creative.equipment.Equipment; diff --git a/api/src/main/java/team/unnamed/creative/overlay/ResourceContainerImpl.java b/api/src/main/java/team/unnamed/creative/overlay/ResourceContainerImpl.java index 725bf9c0..8600a83f 100644 --- a/api/src/main/java/team/unnamed/creative/overlay/ResourceContainerImpl.java +++ b/api/src/main/java/team/unnamed/creative/overlay/ResourceContainerImpl.java @@ -29,7 +29,6 @@ import org.jetbrains.annotations.Nullable; import team.unnamed.creative.atlas.Atlas; import team.unnamed.creative.atlas.AtlasSource; -import team.unnamed.creative.base.Readable; import team.unnamed.creative.base.Writable; import team.unnamed.creative.blockstate.BlockState; import team.unnamed.creative.equipment.Equipment;