Last active
December 30, 2025 17:11
-
-
Save mworzala/3063965073a848ce04b380aab853f89e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package net.hollowcube.multipart.resourcepack; | |
| import com.google.gson.JsonObject; | |
| import net.kyori.adventure.key.Key; | |
| /// Remaps resource pack keys from server data to the client. This should be used if you remap | |
| /// resource pack entries inside a [ResourcePackWriter] implementation. | |
| /// | |
| /// @see ResourcePackWriter#writeItem(Key, JsonObject) | |
| public interface ResourcePackMapper { | |
| /** | |
| * A no-op mapper that does not change the key. | |
| */ | |
| static ResourcePackMapper noop() { | |
| return (key) -> key; | |
| } | |
| Key remapItemKey(Key key); | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package net.hollowcube.multipart.resourcepack; | |
| import com.google.gson.JsonObject; | |
| import net.kyori.adventure.key.Key; | |
| import java.io.IOException; | |
| import java.nio.file.Path; | |
| /// Interface for writing resources into a resource pack-like structure. | |
| /// | |
| /// May be implemented to do key remapping or any other required processing. | |
| /// | |
| /// @see #direct(Path) direct(Path) for a reference implementation that writes to a resource pack directly. | |
| public interface ResourcePackWriter { | |
| /// Creates a writer that creates files in a vanilla resource pack structure. | |
| /// | |
| /// This is the default writer implementation and does not require a [ResourcePackMapper]. | |
| /// | |
| /// @param resourcePackRoot The root directory of the resource pack, where the `assets` directory is located. | |
| /// @return A new [ResourcePackWriter] that writes directly to the specified path. | |
| static ResourcePackWriter direct(Path resourcePackRoot) { | |
| return new DirectResourcePackWriter(resourcePackRoot); | |
| } | |
| /// Creates a new texture in the resource pack with the following content. | |
| /// | |
| /// It is valid to return a different key which will be used to reference this texture in other data. | |
| /// | |
| /// @param key The key for the texture, eg `my_server:item/my_model/my_texture.png` | |
| /// @param data The data for the texture | |
| /// @return The key for the texture, which may be different from the input key if | |
| /// the resource pack has a different naming scheme. | |
| Key writeTexture(Key key, byte[] data) throws IOException; | |
| /// Create a new model in the resource pack with the following content. | |
| /// | |
| /// It is valid to return a different key which will be used to reference this model in other data. | |
| /// | |
| /// @param key The key for the model, eg `my_server:item/my_model/my_model.json` | |
| /// @param model The model data in JSON format. | |
| /// @return The key for the model, which may be different from the input key if | |
| /// the resource pack has a different naming scheme. | |
| Key writeModel(Key key, JsonObject model) throws IOException; | |
| /// Create a new item model in the resource pack with the following content. | |
| /// | |
| /// Remapping the key for this model is OK, however you must keep track of the mapping | |
| /// of key into this function to the resulting key of the model on the client. Multipart | |
| /// will request the remapped key via a [ResourcePackMapper] at runtime. | |
| /// | |
| /// @param key The key for the item model, eg `my_server:item/my_model/my_item.json` | |
| /// @param item The item model data in JSON format. | |
| /// @return The key for the model, which may be different from the input key if | |
| /// the resource pack has a different naming scheme. | |
| /// @see ResourcePackMapper | |
| Key writeItem(Key key, JsonObject item) throws IOException; | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package net.hollowcube.multipart.demo; | |
| import com.google.gson.JsonArray; | |
| import com.google.gson.JsonElement; | |
| import com.google.gson.JsonObject; | |
| import net.hollowcube.multipart.resourcepack.ResourcePackWriter; | |
| import net.kyori.adventure.key.Key; | |
| import net.minestom.server.MinecraftServer; | |
| import net.minestom.server.utils.MajorMinorVersion; | |
| import java.io.ByteArrayOutputStream; | |
| import java.io.IOException; | |
| import java.nio.charset.StandardCharsets; | |
| import java.util.zip.ZipEntry; | |
| import java.util.zip.ZipOutputStream; | |
| public class ZipResourcePackWriter implements ResourcePackWriter, AutoCloseable { | |
| private final ByteArrayOutputStream output = new ByteArrayOutputStream(); | |
| private final ZipOutputStream zipOutput = new ZipOutputStream(output); | |
| private boolean closed = false; | |
| public ZipResourcePackWriter(String packName) throws IOException { | |
| final JsonObject packMeta = new JsonObject(); | |
| final JsonObject pack = new JsonObject(); | |
| pack.add("min_format", packVersion(MinecraftServer.RESOURCE_PACK_VERSION)); | |
| pack.add("max_format", packVersion(MinecraftServer.RESOURCE_PACK_VERSION)); | |
| pack.addProperty("description", packName); | |
| packMeta.add("pack", pack); | |
| writeEntry("pack.mcmeta", packMeta.toString().getBytes(StandardCharsets.UTF_8)); | |
| } | |
| public byte[] collect() throws IOException { | |
| if (!closed) zipOutput.close(); | |
| closed = true; | |
| return output.toByteArray(); | |
| } | |
| @Override | |
| public Key writeTexture(Key key, byte[] data) throws IOException { | |
| final var filePath = "assets/%s/textures/%s".formatted(key.namespace(), key.value()); | |
| writeEntry(filePath, data); | |
| return key; | |
| } | |
| @Override | |
| public Key writeModel(Key key, JsonObject model) throws IOException { | |
| final var filePath = "assets/%s/models/%s.json".formatted(key.namespace(), key.value()); | |
| writeEntry(filePath, model.toString().getBytes(StandardCharsets.UTF_8)); | |
| return key; | |
| } | |
| @Override | |
| public Key writeItem(Key key, JsonObject item) throws IOException { | |
| final var filePath = "assets/%s/items/%s.json".formatted(key.namespace(), key.value()); | |
| writeEntry(filePath, item.toString().getBytes(StandardCharsets.UTF_8)); | |
| return key; | |
| } | |
| @Override | |
| public void close() throws Exception { | |
| if (!closed) zipOutput.close(); | |
| closed = true; | |
| } | |
| private void writeEntry(String path, byte[] data) throws IOException { | |
| zipOutput.putNextEntry(new ZipEntry(path)); | |
| zipOutput.write(data); | |
| zipOutput.closeEntry(); | |
| } | |
| private JsonElement packVersion(MajorMinorVersion version) { | |
| final var array = new JsonArray(); | |
| array.add(version.major()); | |
| array.add(version.minor()); | |
| return array; | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment