From 6a1fe997ba8c25ec817ea7942db10ae78610a9d2 Mon Sep 17 00:00:00 2001 From: Eclipse Date: Tue, 14 Oct 2025 10:59:57 +0000 Subject: [PATCH] Make pack saving abstract --- .../client/MinecraftAssetResolver.java | 19 ------ .../client/MinecraftPackSerializer.java | 60 +++++++++++++++++ .../geysermc/rainbow/client/PackManager.java | 15 +++-- .../client/command/PackGeneratorCommand.java | 15 ++--- .../rainbow/mapping/AssetResolver.java | 7 -- .../rainbow/mapping/PackSerializer.java | 14 ++++ .../geysermc/rainbow/pack/BedrockItem.java | 23 +++---- .../geysermc/rainbow/pack/BedrockPack.java | 66 +++++++------------ .../pack/animation/BedrockAnimation.java | 7 +- .../pack/attachable/BedrockAttachable.java | 8 +-- .../pack/geometry/BedrockGeometry.java | 7 +- 11 files changed, 137 insertions(+), 104 deletions(-) create mode 100644 client/src/main/java/org/geysermc/rainbow/client/MinecraftPackSerializer.java create mode 100644 rainbow/src/main/java/org/geysermc/rainbow/mapping/PackSerializer.java diff --git a/client/src/main/java/org/geysermc/rainbow/client/MinecraftAssetResolver.java b/client/src/main/java/org/geysermc/rainbow/client/MinecraftAssetResolver.java index 77a7b87..d3e2f7c 100644 --- a/client/src/main/java/org/geysermc/rainbow/client/MinecraftAssetResolver.java +++ b/client/src/main/java/org/geysermc/rainbow/client/MinecraftAssetResolver.java @@ -6,31 +6,22 @@ import net.minecraft.client.resources.model.EquipmentAssetManager; import net.minecraft.client.resources.model.EquipmentClientInfo; import net.minecraft.client.resources.model.ModelManager; import net.minecraft.client.resources.model.ResolvedModel; -import net.minecraft.core.HolderLookup; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; -import net.minecraft.server.packs.resources.ResourceManager; import net.minecraft.world.item.equipment.EquipmentAsset; import org.geysermc.rainbow.client.accessor.ResolvedModelAccessor; import org.geysermc.rainbow.client.mixin.EntityRenderDispatcherAccessor; import org.geysermc.rainbow.mapping.AssetResolver; -import java.io.IOException; -import java.io.InputStream; -import java.util.Objects; import java.util.Optional; public class MinecraftAssetResolver implements AssetResolver { private final ModelManager modelManager; private final EquipmentAssetManager equipmentAssetManager; - private final ResourceManager resourceManager; - private final HolderLookup.Provider registries; public MinecraftAssetResolver(Minecraft minecraft) { modelManager = minecraft.getModelManager(); equipmentAssetManager = ((EntityRenderDispatcherAccessor) minecraft.getEntityRenderDispatcher()).getEquipmentAssets(); - resourceManager = minecraft.getResourceManager(); - registries = Objects.requireNonNull(minecraft.level).registryAccess(); } @Override @@ -47,14 +38,4 @@ public class MinecraftAssetResolver implements AssetResolver { public Optional getEquipmentInfo(ResourceKey key) { return Optional.of(equipmentAssetManager.get(key)); } - - @Override - public InputStream getTexture(ResourceLocation location) throws IOException { - return resourceManager.open(location); - } - - @Override - public HolderLookup.Provider registries() { - return registries; - } } diff --git a/client/src/main/java/org/geysermc/rainbow/client/MinecraftPackSerializer.java b/client/src/main/java/org/geysermc/rainbow/client/MinecraftPackSerializer.java new file mode 100644 index 0000000..6ee5895 --- /dev/null +++ b/client/src/main/java/org/geysermc/rainbow/client/MinecraftPackSerializer.java @@ -0,0 +1,60 @@ +package org.geysermc.rainbow.client; + +import com.google.gson.JsonElement; +import com.mojang.serialization.Codec; +import com.mojang.serialization.DynamicOps; +import com.mojang.serialization.JsonOps; +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.core.HolderLookup; +import net.minecraft.resources.RegistryOps; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.server.packs.resources.ResourceManager; +import org.apache.commons.io.IOUtils; +import org.geysermc.rainbow.CodecUtil; +import org.geysermc.rainbow.mapping.PackSerializer; + +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.nio.file.Path; +import java.util.Objects; +import java.util.concurrent.CompletableFuture; + +public class MinecraftPackSerializer implements PackSerializer { + private final HolderLookup.Provider registries; + private final ResourceManager resourceManager; + + public MinecraftPackSerializer(Minecraft minecraft) { + registries = Objects.requireNonNull(minecraft.level).registryAccess(); + resourceManager = minecraft.getResourceManager(); + } + + @Override + public CompletableFuture saveJson(Codec codec, T object, Path path) { + DynamicOps ops = RegistryOps.create(JsonOps.INSTANCE, registries); + return CompletableFuture.runAsync(() -> { + try { + CodecUtil.trySaveJson(codec, object, path.resolveSibling(path.getFileName() + ".json"), ops); + } catch (IOException exception) { + // TODO log + } + }, Util.backgroundExecutor().forName("PackSerializer-saveJson")); + } + + @Override + public CompletableFuture saveTexture(ResourceLocation texture, Path path) { + return CompletableFuture.runAsync(() -> { + ResourceLocation texturePath = texture.withPath(p -> "textures/" + p + ".png"); + try (InputStream inputTexture = resourceManager.open(texturePath)) { + CodecUtil.ensureDirectoryExists(path.getParent()); + try (OutputStream outputTexture = new FileOutputStream(path.toFile())) { + IOUtils.copy(inputTexture, outputTexture); + } + } catch (IOException exception) { + // TODO log + } + }, Util.backgroundExecutor().forName("PackSerializer-saveTexture")); + } +} diff --git a/client/src/main/java/org/geysermc/rainbow/client/PackManager.java b/client/src/main/java/org/geysermc/rainbow/client/PackManager.java index 46d56d1..e81b348 100644 --- a/client/src/main/java/org/geysermc/rainbow/client/PackManager.java +++ b/client/src/main/java/org/geysermc/rainbow/client/PackManager.java @@ -18,6 +18,7 @@ import java.nio.file.Path; import java.util.List; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; public final class PackManager { @@ -32,7 +33,7 @@ public final class PackManager { private static final Path EXPORT_DIRECTORY = FabricLoader.getInstance().getGameDir().resolve(Rainbow.MOD_ID); private static final Path PACK_DIRECTORY = Path.of("pack"); - private static final Path MAPPINGS_FILE = Path.of("geyser_mappings.json"); + private static final Path MAPPINGS_FILE = Path.of("geyser_mappings"); private static final Path PACK_ZIP_FILE = Path.of("pack.zip"); private static final Path REPORT_FILE = Path.of("report.txt"); @@ -44,7 +45,8 @@ public final class PackManager { } Path packDirectory = createPackDirectory(name); - BedrockPack pack = BedrockPack.builder(name, packDirectory.resolve(MAPPINGS_FILE), packDirectory.resolve(PACK_DIRECTORY), new MinecraftAssetResolver(Minecraft.getInstance())) + BedrockPack pack = BedrockPack.builder(name, packDirectory.resolve(MAPPINGS_FILE), packDirectory.resolve(PACK_DIRECTORY), + new MinecraftPackSerializer(Minecraft.getInstance()), new MinecraftAssetResolver(Minecraft.getInstance())) .withPackZipFile(packDirectory.resolve(PACK_ZIP_FILE)) .withGeometryRenderer(MinecraftGeometryRenderer.INSTANCE) .reportSuccesses() @@ -64,17 +66,18 @@ public final class PackManager { return currentPack.map(pack -> EXPORT_DIRECTORY.resolve(pack.name())); } - public Optional finish() { - Optional success = currentPack.map(pack -> { + public boolean finish() { + currentPack.map(pack -> { try { Files.writeString(getExportPath().orElseThrow().resolve(REPORT_FILE), createPackSummary(pack)); } catch (IOException exception) { // TODO log } return pack.save(); - }); + }).ifPresent(CompletableFuture::join); + boolean wasPresent = currentPack.isPresent(); currentPack = Optional.empty(); - return success; + return wasPresent; } private static String createPackSummary(BedrockPack pack) { diff --git a/client/src/main/java/org/geysermc/rainbow/client/command/PackGeneratorCommand.java b/client/src/main/java/org/geysermc/rainbow/client/command/PackGeneratorCommand.java index adcc51f..7b36272 100644 --- a/client/src/main/java/org/geysermc/rainbow/client/command/PackGeneratorCommand.java +++ b/client/src/main/java/org/geysermc/rainbow/client/command/PackGeneratorCommand.java @@ -113,14 +113,13 @@ public class PackGeneratorCommand { .then(ClientCommandManager.literal("finish") .executes(context -> { Optional exportPath = packManager.getExportPath(); - packManager.finish().ifPresentOrElse(success -> { - if (!success) { - context.getSource().sendError(Component.translatable("commands.rainbow.pack_finished_error")); - } else { - context.getSource().sendFeedback(Component.translatable("commands.rainbow.pack_finished_successfully") - .withStyle(style -> style.withUnderlined(true).withClickEvent(new ClickEvent.OpenFile(exportPath.orElseThrow())))); - } - }, () -> context.getSource().sendError(NO_PACK_CREATED)); + if (packManager.finish()) { + // TODO error when exporting fails + context.getSource().sendFeedback(Component.translatable("commands.rainbow.pack_finished_successfully") + .withStyle(style -> style.withUnderlined(true).withClickEvent(new ClickEvent.OpenFile(exportPath.orElseThrow())))); + } else { + context.getSource().sendError(NO_PACK_CREATED); + } return 0; }) ) diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/AssetResolver.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/AssetResolver.java index b949268..53ee42b 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/AssetResolver.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/AssetResolver.java @@ -3,13 +3,10 @@ package org.geysermc.rainbow.mapping; import net.minecraft.client.renderer.item.ClientItem; import net.minecraft.client.resources.model.EquipmentClientInfo; import net.minecraft.client.resources.model.ResolvedModel; -import net.minecraft.core.HolderLookup; import net.minecraft.resources.ResourceKey; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.item.equipment.EquipmentAsset; -import java.io.IOException; -import java.io.InputStream; import java.util.Optional; public interface AssetResolver { @@ -19,8 +16,4 @@ public interface AssetResolver { Optional getClientItem(ResourceLocation location); Optional getEquipmentInfo(ResourceKey key); - - InputStream getTexture(ResourceLocation location) throws IOException; - - HolderLookup.Provider registries(); } diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/PackSerializer.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/PackSerializer.java new file mode 100644 index 0000000..5f74525 --- /dev/null +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/PackSerializer.java @@ -0,0 +1,14 @@ +package org.geysermc.rainbow.mapping; + +import com.mojang.serialization.Codec; +import net.minecraft.resources.ResourceLocation; + +import java.nio.file.Path; +import java.util.concurrent.CompletableFuture; + +public interface PackSerializer { + + CompletableFuture saveJson(Codec codec, T object, Path path); + + CompletableFuture saveTexture(ResourceLocation texture, Path path); +} diff --git a/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockItem.java b/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockItem.java index f2403cc..929260a 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockItem.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockItem.java @@ -2,26 +2,27 @@ package org.geysermc.rainbow.pack; import net.minecraft.resources.ResourceLocation; import org.geysermc.rainbow.Rainbow; +import org.geysermc.rainbow.mapping.PackSerializer; import org.geysermc.rainbow.pack.animation.BedrockAnimation; import org.geysermc.rainbow.pack.attachable.BedrockAttachable; import org.geysermc.rainbow.pack.geometry.BedrockGeometry; -import java.io.IOException; import java.nio.file.Path; +import java.util.List; import java.util.Optional; +import java.util.concurrent.CompletableFuture; +import java.util.stream.Stream; public record BedrockItem(ResourceLocation identifier, String textureName, ResourceLocation texture, boolean exportTexture, Optional attachable, Optional geometry, Optional animation) { - public void save(Path attachableDirectory, Path geometryDirectory, Path animationDirectory) throws IOException { - if (attachable.isPresent()) { - attachable.get().save(attachableDirectory); - } - if (geometry.isPresent()) { - geometry.get().save(geometryDirectory); - } - if (animation.isPresent()) { - animation.get().save(animationDirectory, Rainbow.fileSafeResourceLocation(identifier)); - } + public List> save(PackSerializer serializer, Path attachableDirectory, Path geometryDirectory, Path animationDirectory) { + return Stream.concat( + attachable.stream().map(present -> present.save(serializer, attachableDirectory)), + Stream.concat( + geometry.stream().map(present -> present.save(serializer, geometryDirectory)), + animation.stream().map(present -> present.save(serializer, animationDirectory, Rainbow.fileSafeResourceLocation(identifier))) + ) + ).toList(); } } diff --git a/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockPack.java b/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockPack.java index d2c2a9f..51f6d0a 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockPack.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockPack.java @@ -1,44 +1,42 @@ package org.geysermc.rainbow.pack; -import com.mojang.serialization.JsonOps; import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntSet; import net.minecraft.core.Holder; import net.minecraft.core.component.DataComponentPatch; import net.minecraft.core.component.DataComponents; -import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ProblemReporter; import net.minecraft.world.item.Item; import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.component.CustomModelData; -import org.apache.commons.io.IOUtils; import org.geysermc.rainbow.CodecUtil; import org.geysermc.rainbow.PackConstants; import org.geysermc.rainbow.mapping.AssetResolver; import org.geysermc.rainbow.mapping.BedrockItemMapper; import org.geysermc.rainbow.mapping.PackContext; +import org.geysermc.rainbow.mapping.PackSerializer; import org.geysermc.rainbow.mapping.geometry.GeometryRenderer; import org.geysermc.rainbow.mapping.geometry.NoopGeometryRenderer; import org.geysermc.rainbow.definition.GeyserMappings; import org.jetbrains.annotations.NotNull; -import java.io.FileOutputStream; import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; import java.nio.file.Path; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Optional; import java.util.Set; import java.util.UUID; +import java.util.concurrent.CompletableFuture; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.UnaryOperator; public class BedrockPack { private final String name; private final PackPaths paths; + private final PackSerializer serializer; private final BedrockTextures.Builder itemTextures = BedrockTextures.builder(); private final Set bedrockItems = new HashSet<>(); @@ -50,11 +48,12 @@ public class BedrockPack { private final PackManifest manifest; private final ProblemReporter.Collector reporter; - public BedrockPack(String name, PackPaths paths, AssetResolver assetResolver, + public BedrockPack(String name, PackPaths paths, PackSerializer serializer, AssetResolver assetResolver, GeometryRenderer geometryRenderer, ProblemReporter.Collector reporter, boolean reportSuccesses) { this.name = name; this.paths = paths; + this.serializer = serializer; // Not reading existing item mappings/texture atlas for now since that doesn't work all that well yet this.context = new PackContext(new GeyserMappings(), paths, item -> { @@ -121,50 +120,29 @@ public class BedrockPack { return map(stack); } - public boolean save() { - boolean success = true; + public CompletableFuture save() { + List> futures = new ArrayList<>(); - try { - CodecUtil.trySaveJson(GeyserMappings.CODEC, context.mappings(), paths.mappings(), RegistryOps.create(JsonOps.INSTANCE, context.assetResolver().registries())); - CodecUtil.trySaveJson(PackManifest.CODEC, manifest, paths.manifest()); - CodecUtil.trySaveJson(BedrockTextureAtlas.CODEC, BedrockTextureAtlas.itemAtlas(name, itemTextures), paths.itemAtlas()); - } catch (IOException | NullPointerException exception) { - reporter.forChild(() -> "saving Geyser mappings, pack manifest, and texture atlas ").report(() -> "failed to save to pack: " + exception); - success = false; - } + futures.add(serializer.saveJson(GeyserMappings.CODEC, context.mappings(), paths.mappings())); + futures.add(serializer.saveJson(PackManifest.CODEC, manifest, paths.manifest())); + futures.add(serializer.saveJson(BedrockTextureAtlas.CODEC, BedrockTextureAtlas.itemAtlas(name, itemTextures), paths.itemAtlas())); for (BedrockItem item : bedrockItems) { - try { - item.save(paths.attachables(), paths.geometry(), paths.animation()); - } catch (IOException exception) { - reporter.forChild(() -> "files for bedrock item " + item.identifier() + " ").report(() -> "failed to save to pack: " + exception); - success = false; - } + futures.addAll(item.save(serializer, paths.attachables(), paths.geometry(), paths.animation())); } for (ResourceLocation texture : texturesToExport) { - texture = texture.withPath(path -> "textures/" + path + ".png"); - try (InputStream inputTexture = context.assetResolver().getTexture(texture)) { - Path texturePath = paths.packRoot().resolve(texture.getPath()); - CodecUtil.ensureDirectoryExists(texturePath.getParent()); - try (OutputStream outputTexture = new FileOutputStream(texturePath.toFile())) { - IOUtils.copy(inputTexture, outputTexture); - } - } catch (IOException exception) { - ResourceLocation finalTexture = texture; - reporter.forChild(() -> "texture " + finalTexture + " ").report(() -> "failed to save to pack: " + exception); - success = false; - } + futures.add(serializer.saveTexture(texture, paths.packRoot().resolve(BedrockTextures.TEXTURES_FOLDER + texture.getPath() + ".png"))); } if (paths.zipOutput().isPresent()) { try { CodecUtil.tryZipDirectory(paths.packRoot(), paths.zipOutput().get()); } catch (IOException exception) { - success = false; + // TODO log } } - return success; + return CompletableFuture.allOf(futures.toArray(CompletableFuture[]::new)); } public int getMappings() { @@ -192,8 +170,8 @@ public class BedrockPack { List.of(new PackManifest.Module(name, PackConstants.DEFAULT_PACK_DESCRIPTION, UUID.randomUUID(), BedrockVersion.of(0)))); } - public static Builder builder(String name, Path mappingsPath, Path packRootPath, AssetResolver assetResolver) { - return new Builder(name, mappingsPath, packRootPath, assetResolver); + public static Builder builder(String name, Path mappingsPath, Path packRootPath, PackSerializer packSerializer, AssetResolver assetResolver) { + return new Builder(name, mappingsPath, packRootPath, packSerializer, assetResolver); } public static class Builder { @@ -201,12 +179,13 @@ public class BedrockPack { private static final Path GEOMETRY_DIRECTORY = Path.of("models/entity"); private static final Path ANIMATION_DIRECTORY = Path.of("animations"); - private static final Path MANIFEST_FILE = Path.of("manifest.json"); - private static final Path ITEM_ATLAS_FILE = Path.of("textures/item_texture.json"); + private static final Path MANIFEST_FILE = Path.of("manifest"); + private static final Path ITEM_ATLAS_FILE = Path.of("textures/item_texture"); private final String name; private final Path mappingsPath; private final Path packRootPath; + private final PackSerializer packSerializer; private final AssetResolver assetResolver; private UnaryOperator attachablesPath = resolve(ATTACHABLES_DIRECTORY); private UnaryOperator geometryPath = resolve(GEOMETRY_DIRECTORY); @@ -218,11 +197,12 @@ public class BedrockPack { private ProblemReporter.Collector reporter; private boolean reportSuccesses = false; - public Builder(String name, Path mappingsPath, Path packRootPath, AssetResolver assetResolver) { + public Builder(String name, Path mappingsPath, Path packRootPath, PackSerializer packSerializer, AssetResolver assetResolver) { this.name = name; this.mappingsPath = mappingsPath; this.packRootPath = packRootPath; this.reporter = new ProblemReporter.Collector(() -> "Bedrock pack " + name + " "); + this.packSerializer = packSerializer; this.assetResolver = assetResolver; } @@ -295,7 +275,7 @@ public class BedrockPack { PackPaths paths = new PackPaths(mappingsPath, packRootPath, attachablesPath.apply(packRootPath), geometryPath.apply(packRootPath), animationPath.apply(packRootPath), manifestPath.apply(packRootPath), itemAtlasPath.apply(packRootPath), Optional.ofNullable(packZipFile)); - return new BedrockPack(name, paths, assetResolver, geometryRenderer, reporter, reportSuccesses); + return new BedrockPack(name, paths, packSerializer, assetResolver, geometryRenderer, reporter, reportSuccesses); } private static UnaryOperator resolve(Path child) { diff --git a/rainbow/src/main/java/org/geysermc/rainbow/pack/animation/BedrockAnimation.java b/rainbow/src/main/java/org/geysermc/rainbow/pack/animation/BedrockAnimation.java index dbdf1fc..9131dad 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/pack/animation/BedrockAnimation.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/pack/animation/BedrockAnimation.java @@ -5,14 +5,15 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.DataResult; import com.mojang.serialization.codecs.RecordCodecBuilder; import org.geysermc.rainbow.CodecUtil; +import org.geysermc.rainbow.mapping.PackSerializer; import org.geysermc.rainbow.pack.BedrockVersion; import org.joml.Vector3fc; -import java.io.IOException; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; import java.util.Optional; +import java.util.concurrent.CompletableFuture; public record BedrockAnimation(BedrockVersion formatVersion, Map definitions) { public static final BedrockVersion FORMAT_VERSION = BedrockVersion.of(1, 8, 0); @@ -24,8 +25,8 @@ public record BedrockAnimation(BedrockVersion formatVersion, Map save(PackSerializer serializer, Path animationDirectory, String identifier) { + return serializer.saveJson(CODEC, this, animationDirectory.resolve(identifier + ".animation")); } public static Builder builder() { diff --git a/rainbow/src/main/java/org/geysermc/rainbow/pack/attachable/BedrockAttachable.java b/rainbow/src/main/java/org/geysermc/rainbow/pack/attachable/BedrockAttachable.java index a6e8b25..baf940f 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/pack/attachable/BedrockAttachable.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/pack/attachable/BedrockAttachable.java @@ -9,15 +9,14 @@ import net.minecraft.resources.ResourceLocation; import net.minecraft.util.ExtraCodecs; import net.minecraft.util.StringRepresentable; import net.minecraft.world.entity.EquipmentSlot; -import org.geysermc.rainbow.CodecUtil; import org.geysermc.rainbow.PackConstants; import org.geysermc.rainbow.Rainbow; +import org.geysermc.rainbow.mapping.PackSerializer; import org.geysermc.rainbow.pack.BedrockTextures; import org.geysermc.rainbow.pack.BedrockVersion; import org.geysermc.rainbow.pack.geometry.BedrockGeometry; import org.jetbrains.annotations.NotNull; -import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.EnumMap; @@ -25,6 +24,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.CompletableFuture; import java.util.stream.Stream; public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo info) { @@ -35,9 +35,9 @@ public record BedrockAttachable(BedrockVersion formatVersion, AttachableInfo inf ).apply(instance, BedrockAttachable::new) ); - public void save(Path attachablesDirectory) throws IOException { + public CompletableFuture save(PackSerializer serializer, Path attachablesDirectory) { // Get a safe attachable path by using Geyser's way of getting icons - CodecUtil.trySaveJson(CODEC, this, attachablesDirectory.resolve(Rainbow.fileSafeResourceLocation(info.identifier) + ".json")); + return serializer.saveJson(CODEC, this, attachablesDirectory.resolve(Rainbow.fileSafeResourceLocation(info.identifier))); } public static Builder builder(ResourceLocation identifier) { diff --git a/rainbow/src/main/java/org/geysermc/rainbow/pack/geometry/BedrockGeometry.java b/rainbow/src/main/java/org/geysermc/rainbow/pack/geometry/BedrockGeometry.java index 993abe0..665d445 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/pack/geometry/BedrockGeometry.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/pack/geometry/BedrockGeometry.java @@ -5,12 +5,12 @@ import com.mojang.serialization.Codec; import com.mojang.serialization.codecs.RecordCodecBuilder; import net.minecraft.core.Direction; import org.geysermc.rainbow.CodecUtil; +import org.geysermc.rainbow.mapping.PackSerializer; import org.geysermc.rainbow.pack.BedrockVersion; import org.joml.Vector2fc; import org.joml.Vector3f; import org.joml.Vector3fc; -import java.io.IOException; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; @@ -18,6 +18,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.concurrent.CompletableFuture; public record BedrockGeometry(BedrockVersion formatVersion, List definitions) { public static final BedrockVersion FORMAT_VERSION = BedrockVersion.of(1, 21, 0); @@ -31,8 +32,8 @@ public record BedrockGeometry(BedrockVersion formatVersion, List save(PackSerializer serializer, Path geometryDirectory) { + return serializer.saveJson(CODEC, this, geometryDirectory.resolve(definitions.getFirst().info.identifier + ".geo")); } public static BedrockGeometry of(GeometryDefinition... definitions) {