From a38cbdf4136e38602c44c02bc5e4e2be348d8b9b Mon Sep 17 00:00:00 2001 From: Eclipse Date: Tue, 14 Oct 2025 09:53:45 +0000 Subject: [PATCH] Make BedrockPack more modular --- .../geysermc/rainbow/client/PackManager.java | 95 ++++++- .../render/MinecraftGeometryRenderer.java | 1 + .../rainbow/mapping/BedrockItemMapper.java | 2 +- .../geysermc/rainbow/mapping/PackContext.java | 7 +- .../geysermc/rainbow/pack/BedrockPack.java | 260 +++++++++++------- .../org/geysermc/rainbow/pack/PackPaths.java | 8 + 6 files changed, 261 insertions(+), 112 deletions(-) create mode 100644 rainbow/src/main/java/org/geysermc/rainbow/pack/PackPaths.java 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 1b526b4..46d56d1 100644 --- a/client/src/main/java/org/geysermc/rainbow/client/PackManager.java +++ b/client/src/main/java/org/geysermc/rainbow/client/PackManager.java @@ -1,14 +1,40 @@ package org.geysermc.rainbow.client; +import net.fabricmc.loader.api.FabricLoader; import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.components.SplashRenderer; +import net.minecraft.util.RandomSource; +import net.minecraft.util.StringUtil; +import org.geysermc.rainbow.CodecUtil; +import org.geysermc.rainbow.Rainbow; +import org.geysermc.rainbow.client.mixin.SplashRendererAccessor; +import org.geysermc.rainbow.client.render.MinecraftGeometryRenderer; +import org.geysermc.rainbow.pack.BedrockItem; import org.geysermc.rainbow.pack.BedrockPack; import java.io.IOException; +import java.nio.file.Files; import java.nio.file.Path; +import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.function.Consumer; public final class PackManager { + private static final List PACK_SUMMARY_COMMENTS = List.of("Use the custom item API v2 build!", "bugrock moment", "RORY", + "use !!plshelp", "rm -rf --no-preserve-root /*", "welcome to the internet!", "beep beep. boop boop?", "FROG", "it is frog day", "it is cat day!", + "eclipse will hear about this.", "you must now say the word 'frog' in the #general channel", "You Just Lost The Game", "you are now breathing manually", + "you are now blinking manually", "you're eligible for a free hug token! <3", "don't mind me!", "hissss", "Gayser and Floodgayte, my favourite plugins.", + "meow", "we'll be done here soon™", "got anything else to say?", "we're done now!", "this will be fixed by v6053", "expect it to be done within 180 business days!", + "any colour you like", "someone tell Mojang about this", "you can't unbake baked models, so we'll store the unbaked models", "soon fully datagen ready", + "packconverter when", "codecs ftw"); + private static final RandomSource RANDOM = RandomSource.create(); + + 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 PACK_ZIP_FILE = Path.of("pack.zip"); + private static final Path REPORT_FILE = Path.of("report.txt"); private Optional currentPack = Optional.empty(); @@ -17,7 +43,13 @@ public final class PackManager { throw new IllegalStateException("Already started a pack (" + currentPack.get().name() + ")"); } - currentPack = Optional.of(new BedrockPack(name, new MinecraftAssetResolver(Minecraft.getInstance()))); + Path packDirectory = createPackDirectory(name); + BedrockPack pack = BedrockPack.builder(name, packDirectory.resolve(MAPPINGS_FILE), packDirectory.resolve(PACK_DIRECTORY), new MinecraftAssetResolver(Minecraft.getInstance())) + .withPackZipFile(packDirectory.resolve(PACK_ZIP_FILE)) + .withGeometryRenderer(MinecraftGeometryRenderer.INSTANCE) + .reportSuccesses() + .build(); + currentPack = Optional.of(pack); } public void run(Consumer consumer) { @@ -29,12 +61,69 @@ public final class PackManager { } public Optional getExportPath() { - return currentPack.map(BedrockPack::getExportPath); + return currentPack.map(pack -> EXPORT_DIRECTORY.resolve(pack.name())); } public Optional finish() { - Optional success = currentPack.map(BedrockPack::save); + Optional success = currentPack.map(pack -> { + try { + Files.writeString(getExportPath().orElseThrow().resolve(REPORT_FILE), createPackSummary(pack)); + } catch (IOException exception) { + // TODO log + } + return pack.save(); + }); currentPack = Optional.empty(); return success; } + + private static String createPackSummary(BedrockPack pack) { + String problems = pack.getReporter().getTreeReport(); + if (StringUtil.isBlank(problems)) { + problems = "Well that's odd... there's nothing here!"; + } + + Set bedrockItems = pack.getBedrockItems(); + long attachables = bedrockItems.stream().filter(item -> item.attachable().isPresent()).count(); + long geometries = bedrockItems.stream().filter(item -> item.geometry().isPresent()).count(); + long animations = bedrockItems.stream().filter(item -> item.animation().isPresent()).count(); + + return """ +-- PACK GENERATION REPORT -- +// %s + +Generated pack: %s +Mappings written: %d +Item texture atlas size: %d +Attachables tried to export: %d +Geometry files tried to export: %d +Animations tried to export: %d +Textures tried to export: %d + +-- MAPPING TREE REPORT -- +%s +""".formatted(randomSummaryComment(), pack.name(), pack.getMappings(), pack.getItemTextureAtlasSize(), + attachables, geometries, animations, pack.getAdditionalExportedTextures(), problems); + } + + private static String randomSummaryComment() { + if (RANDOM.nextDouble() < 0.5) { + SplashRenderer splash = Minecraft.getInstance().getSplashManager().getSplash(); + if (splash == null) { + return "Undefined Undefined :("; + } + return ((SplashRendererAccessor) splash).getSplash(); + } + return randomBuiltinSummaryComment(); + } + + private static String randomBuiltinSummaryComment() { + return PACK_SUMMARY_COMMENTS.get(RANDOM.nextInt(PACK_SUMMARY_COMMENTS.size())); + } + + private static Path createPackDirectory(String name) throws IOException { + Path path = EXPORT_DIRECTORY.resolve(name); + CodecUtil.ensureDirectoryExists(path); + return path; + } } diff --git a/client/src/main/java/org/geysermc/rainbow/client/render/MinecraftGeometryRenderer.java b/client/src/main/java/org/geysermc/rainbow/client/render/MinecraftGeometryRenderer.java index b8243fb..d7e8f19 100644 --- a/client/src/main/java/org/geysermc/rainbow/client/render/MinecraftGeometryRenderer.java +++ b/client/src/main/java/org/geysermc/rainbow/client/render/MinecraftGeometryRenderer.java @@ -26,6 +26,7 @@ import java.util.Objects; // TODO maybe just use this even for normal 2D items, not sure, could be useful for composite models and stuff // TODO output in a size bedrock likes public class MinecraftGeometryRenderer implements GeometryRenderer { + public static final MinecraftGeometryRenderer INSTANCE = new MinecraftGeometryRenderer(); @Override public boolean render(ItemStack stack, Path path) { diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/BedrockItemMapper.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/BedrockItemMapper.java index e6a5967..27c054d 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/BedrockItemMapper.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/BedrockItemMapper.java @@ -284,7 +284,7 @@ public class BedrockItemMapper { if (customModel.isPresent()) { texture = texture.withPath(path -> path + "_icon"); // FIXME Bit of a hack, preferably render geometry at a later stage - exportTexture = !packContext.geometryRenderer().render(stack, packContext.packPath().resolve(BedrockTextures.TEXTURES_FOLDER + texture.getPath() + ".png")); + exportTexture = !packContext.geometryRenderer().render(stack, packContext.paths().packRoot().resolve(BedrockTextures.TEXTURES_FOLDER + texture.getPath() + ".png")); packContext.additionalTextureConsumer().accept(geometryTexture); } diff --git a/rainbow/src/main/java/org/geysermc/rainbow/mapping/PackContext.java b/rainbow/src/main/java/org/geysermc/rainbow/mapping/PackContext.java index 8bee7e0..e32196a 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/mapping/PackContext.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/mapping/PackContext.java @@ -3,10 +3,11 @@ package org.geysermc.rainbow.mapping; import net.minecraft.resources.ResourceLocation; import org.geysermc.rainbow.mapping.geometry.GeometryRenderer; import org.geysermc.rainbow.definition.GeyserMappings; +import org.geysermc.rainbow.pack.PackPaths; -import java.nio.file.Path; import java.util.function.Consumer; -public record PackContext(GeyserMappings mappings, Path packPath, BedrockItemConsumer itemConsumer, AssetResolver assetResolver, - GeometryRenderer geometryRenderer, Consumer additionalTextureConsumer) { +public record PackContext(GeyserMappings mappings, PackPaths paths, BedrockItemConsumer itemConsumer, AssetResolver assetResolver, + GeometryRenderer geometryRenderer, Consumer additionalTextureConsumer, + boolean reportSuccesses) { } 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 5a765ab..d2c2a9f 100644 --- a/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockPack.java +++ b/rainbow/src/main/java/org/geysermc/rainbow/pack/BedrockPack.java @@ -3,22 +3,22 @@ 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.fabricmc.loader.api.FabricLoader; +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.util.RandomSource; -import net.minecraft.util.StringUtil; +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.Rainbow; import org.geysermc.rainbow.mapping.AssetResolver; import org.geysermc.rainbow.mapping.BedrockItemMapper; import org.geysermc.rainbow.mapping.PackContext; +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; @@ -27,7 +27,6 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.nio.file.Files; import java.nio.file.Path; import java.util.HashSet; import java.util.List; @@ -35,68 +34,38 @@ import java.util.Optional; import java.util.Set; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.UnaryOperator; public class BedrockPack { - private static final List PACK_SUMMARY_COMMENTS = List.of("Use the custom item API v2 build!", "bugrock moment", "RORY", - "use !!plshelp", "rm -rf --no-preserve-root /*", "welcome to the internet!", "beep beep. boop boop?", "FROG", "it is frog day", "it is cat day!", - "eclipse will hear about this.", "you must now say the word 'frog' in the #general channel", "You Just Lost The Game", "you are now breathing manually", - "you are now blinking manually", "you're eligible for a free hug token! <3", "don't mind me!", "hissss", "Gayser and Floodgayte, my favourite plugins.", - "meow", "we'll be done here soon™", "got anything else to say?", "we're done now!", "this will be fixed by v6053", "expect it to be done within 180 business days!", - "any colour you like", "someone tell Mojang about this", "you can't unbake baked models, so we'll store the unbaked models", "soon fully datagen ready", - "packconverter when", "codecs ftw"); - private static final RandomSource RANDOM = RandomSource.create(); - - 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 ATTACHABLES_DIRECTORY = Path.of("attachables"); - private static final Path GEOMETRY_DIRECTORY = Path.of("models/entity"); - private static final Path ANIMATION_DIRECTORY = Path.of("animations"); - - private static final Path MAPPINGS_FILE = Path.of("geyser_mappings.json"); - 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 PACK_ZIP_FILE = Path.of("pack.zip"); - private static final Path REPORT_FILE = Path.of("report.txt"); - private final String name; - private final Path exportPath; - private final Path packPath; - private final PackManifest manifest; - private final GeyserMappings mappings; - private final BedrockTextures.Builder itemTextures; + private final PackPaths paths; + private final BedrockTextures.Builder itemTextures = BedrockTextures.builder(); private final Set bedrockItems = new HashSet<>(); private final Set texturesToExport = new HashSet<>(); private final Set modelsMapped = new HashSet<>(); private final IntSet customModelDataMapped = new IntOpenHashSet(); + private final PackContext context; + private final PackManifest manifest; private final ProblemReporter.Collector reporter; - private final PackContext context; - - public BedrockPack(String name, AssetResolver assetResolver) throws IOException { + public BedrockPack(String name, PackPaths paths, AssetResolver assetResolver, + GeometryRenderer geometryRenderer, ProblemReporter.Collector reporter, + boolean reportSuccesses) { this.name = name; + this.paths = paths; // Not reading existing item mappings/texture atlas for now since that doesn't work all that well yet - exportPath = createPackDirectory(name); - packPath = exportPath.resolve(PACK_DIRECTORY); - //mappings = CodecUtil.readOrCompute(GeyserMappings.CODEC, exportPath.resolve(MAPPINGS_FILE), GeyserMappings::new); - mappings = new GeyserMappings(); - manifest = CodecUtil.readOrCompute(PackManifest.CODEC, packPath.resolve(MANIFEST_FILE), () -> defaultManifest(name)).increment(); - /*itemTextures = CodecUtil.readOrCompute(BedrockTextureAtlas.ITEM_ATLAS_CODEC, packPath.resolve(ITEM_ATLAS_FILE), - () -> BedrockTextureAtlas.itemAtlas(name, BedrockTextures.builder())).textures().toBuilder();*/ - itemTextures = BedrockTextures.builder(); - - reporter = new ProblemReporter.Collector(() -> "Bedrock pack " + name + " "); - - context = new PackContext(mappings, packPath, item -> { + this.context = new PackContext(new GeyserMappings(), paths, item -> { itemTextures.withItemTexture(item); if (item.exportTexture()) { texturesToExport.add(item.texture()); } bedrockItems.add(item); - }, assetResolver, NoopGeometryRenderer.INSTANCE, texturesToExport::add); + }, assetResolver, geometryRenderer, texturesToExport::add, reportSuccesses); + manifest = defaultManifest(name); + this.reporter = reporter; } public String name() { @@ -146,20 +115,26 @@ public class BedrockPack { return problems.get() ? MappingResult.PROBLEMS_OCCURRED : MappingResult.MAPPED_SUCCESSFULLY; } + public MappingResult map(Holder item, DataComponentPatch patch) { + ItemStack stack = new ItemStack(item); + stack.applyComponents(patch); + return map(stack); + } + public boolean save() { boolean success = true; try { - CodecUtil.trySaveJson(GeyserMappings.CODEC, mappings, exportPath.resolve(MAPPINGS_FILE), RegistryOps.create(JsonOps.INSTANCE, context.assetResolver().registries())); - CodecUtil.trySaveJson(PackManifest.CODEC, manifest, packPath.resolve(MANIFEST_FILE)); - CodecUtil.trySaveJson(BedrockTextureAtlas.CODEC, BedrockTextureAtlas.itemAtlas(name, itemTextures), packPath.resolve(ITEM_ATLAS_FILE)); + 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; } for (BedrockItem item : bedrockItems) { try { - item.save(packPath.resolve(ATTACHABLES_DIRECTORY), packPath.resolve(GEOMETRY_DIRECTORY), packPath.resolve(ANIMATION_DIRECTORY)); + 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; @@ -169,7 +144,7 @@ public class BedrockPack { for (ResourceLocation texture : texturesToExport) { texture = texture.withPath(path -> "textures/" + path + ".png"); try (InputStream inputTexture = context.assetResolver().getTexture(texture)) { - Path texturePath = packPath.resolve(texture.getPath()); + Path texturePath = paths.packRoot().resolve(texture.getPath()); CodecUtil.ensureDirectoryExists(texturePath.getParent()); try (OutputStream outputTexture = new FileOutputStream(texturePath.toFile())) { IOUtils.copy(inputTexture, outputTexture); @@ -181,71 +156,35 @@ public class BedrockPack { } } - try { - CodecUtil.tryZipDirectory(packPath, exportPath.resolve(PACK_ZIP_FILE)); - } catch (IOException exception) { - success = false; + if (paths.zipOutput().isPresent()) { + try { + CodecUtil.tryZipDirectory(paths.packRoot(), paths.zipOutput().get()); + } catch (IOException exception) { + success = false; + } } - try { - Files.writeString(exportPath.resolve(REPORT_FILE), createPackSummary()); - } catch (IOException exception) { - // TODO log - } return success; } - public Path getExportPath() { - return exportPath; + public int getMappings() { + return context.mappings().size(); } - private String createPackSummary() { - String problems = reporter.getTreeReport(); - if (StringUtil.isBlank(problems)) { - problems = "Well that's odd... there's nothing here!"; - } - - long attachables = bedrockItems.stream().filter(item -> item.attachable().isPresent()).count(); - long geometries = bedrockItems.stream().filter(item -> item.geometry().isPresent()).count(); - long animations = bedrockItems.stream().filter(item -> item.animation().isPresent()).count(); - - return """ --- PACK GENERATION REPORT -- -// %s - -Generated pack: %s -Mappings written: %d -Item texture atlas size: %d -Attachables tried to export: %d -Geometry files tried to export: %d -Animations tried to export: %d -Textures tried to export: %d - --- MAPPING TREE REPORT -- -%s -""".formatted(randomSummaryComment(), name, mappings.size(), itemTextures.build().size(), - attachables, geometries, animations, texturesToExport.size(), problems); + public Set getBedrockItems() { + return Set.copyOf(bedrockItems); } - private static String randomSummaryComment() { - if (RANDOM.nextDouble() < 0.6) { - /*SplashRenderer splash = Minecraft.getInstance().getSplashManager().getSplash(); - if (splash == null) { - return "Undefined Undefined :("; - } - return ((SplashRendererAccessor) splash).getSplash();*/ // TODO - } - return randomBuiltinSummaryComment(); + public int getItemTextureAtlasSize() { + return itemTextures.build().size(); } - private static String randomBuiltinSummaryComment() { - return PACK_SUMMARY_COMMENTS.get(RANDOM.nextInt(PACK_SUMMARY_COMMENTS.size())); + public int getAdditionalExportedTextures() { + return texturesToExport.size(); } - private static Path createPackDirectory(String name) throws IOException { - Path path = EXPORT_DIRECTORY.resolve(name); - CodecUtil.ensureDirectoryExists(path); - return path; + public ProblemReporter.Collector getReporter() { + return reporter; } private static PackManifest defaultManifest(String name) { @@ -253,6 +192,117 @@ Textures tried to export: %d 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 class Builder { + private static final Path ATTACHABLES_DIRECTORY = Path.of("attachables"); + 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 final String name; + private final Path mappingsPath; + private final Path packRootPath; + private final AssetResolver assetResolver; + private UnaryOperator attachablesPath = resolve(ATTACHABLES_DIRECTORY); + private UnaryOperator geometryPath = resolve(GEOMETRY_DIRECTORY); + private UnaryOperator animationPath = resolve(ANIMATION_DIRECTORY); + private UnaryOperator manifestPath = resolve(MANIFEST_FILE); + private UnaryOperator itemAtlasPath = resolve(ITEM_ATLAS_FILE); + private Path packZipFile = null; + private GeometryRenderer geometryRenderer = NoopGeometryRenderer.INSTANCE; + private ProblemReporter.Collector reporter; + private boolean reportSuccesses = false; + + public Builder(String name, Path mappingsPath, Path packRootPath, AssetResolver assetResolver) { + this.name = name; + this.mappingsPath = mappingsPath; + this.packRootPath = packRootPath; + this.reporter = new ProblemReporter.Collector(() -> "Bedrock pack " + name + " "); + this.assetResolver = assetResolver; + } + + public Builder withAttachablesPath(Path absolute) { + return withAttachablesPath(path -> absolute); + } + + public Builder withAttachablesPath(UnaryOperator path) { + attachablesPath = path; + return this; + } + + public Builder withGeometryPath(Path absolute) { + return withGeometryPath(path -> absolute); + } + + public Builder withGeometryPath(UnaryOperator path) { + geometryPath = path; + return this; + } + + public Builder withAnimationPath(Path absolute) { + return withAnimationPath(path -> absolute); + } + + public Builder withAnimationPath(UnaryOperator path) { + animationPath = path; + return this; + } + + public Builder withManifestPath(Path absolute) { + return withManifestPath(path -> absolute); + } + + public Builder withManifestPath(UnaryOperator path) { + manifestPath = path; + return this; + } + + public Builder withItemAtlasPath(Path absolute) { + return withItemAtlasPath(path -> absolute); + } + + public Builder withItemAtlasPath(UnaryOperator path) { + itemAtlasPath = path; + return this; + } + + public Builder withPackZipFile(Path absolute) { + packZipFile = absolute; + return this; + } + + public Builder withGeometryRenderer(GeometryRenderer renderer) { + geometryRenderer = renderer; + return this; + } + + public Builder withReporter(ProblemReporter.Collector reporter) { + this.reporter = reporter; + return this; + } + + public Builder reportSuccesses() { + this.reportSuccesses = true; + return this; + } + + public BedrockPack build() { + 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); + } + + private static UnaryOperator resolve(Path child) { + return root -> root.resolve(child); + } + } + public enum MappingResult { NONE_MAPPED, MAPPED_SUCCESSFULLY, diff --git a/rainbow/src/main/java/org/geysermc/rainbow/pack/PackPaths.java b/rainbow/src/main/java/org/geysermc/rainbow/pack/PackPaths.java new file mode 100644 index 0000000..16f101f --- /dev/null +++ b/rainbow/src/main/java/org/geysermc/rainbow/pack/PackPaths.java @@ -0,0 +1,8 @@ +package org.geysermc.rainbow.pack; + +import java.nio.file.Path; +import java.util.Optional; + +public record PackPaths(Path mappings, Path packRoot, Path attachables, Path geometry, Path animation, + Path manifest, Path itemAtlas, Optional zipOutput) { +}