1
0
mirror of https://github.com/GeyserMC/Rainbow.git synced 2025-12-20 15:29:27 +00:00

Make BedrockPack more modular

This commit is contained in:
Eclipse
2025-10-14 09:53:45 +00:00
parent b741eac4c6
commit a38cbdf413
6 changed files with 261 additions and 112 deletions

View File

@@ -1,14 +1,40 @@
package org.geysermc.rainbow.client; package org.geysermc.rainbow.client;
import net.fabricmc.loader.api.FabricLoader;
import net.minecraft.client.Minecraft; 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 org.geysermc.rainbow.pack.BedrockPack;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer; import java.util.function.Consumer;
public final class PackManager { public final class PackManager {
private static final List<String> 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<BedrockPack> currentPack = Optional.empty(); private Optional<BedrockPack> currentPack = Optional.empty();
@@ -17,7 +43,13 @@ public final class PackManager {
throw new IllegalStateException("Already started a pack (" + currentPack.get().name() + ")"); 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<BedrockPack> consumer) { public void run(Consumer<BedrockPack> consumer) {
@@ -29,12 +61,69 @@ public final class PackManager {
} }
public Optional<Path> getExportPath() { public Optional<Path> getExportPath() {
return currentPack.map(BedrockPack::getExportPath); return currentPack.map(pack -> EXPORT_DIRECTORY.resolve(pack.name()));
} }
public Optional<Boolean> finish() { public Optional<Boolean> finish() {
Optional<Boolean> success = currentPack.map(BedrockPack::save); Optional<Boolean> 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(); currentPack = Optional.empty();
return success; 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<BedrockItem> 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;
}
} }

View File

@@ -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 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 // TODO output in a size bedrock likes
public class MinecraftGeometryRenderer implements GeometryRenderer { public class MinecraftGeometryRenderer implements GeometryRenderer {
public static final MinecraftGeometryRenderer INSTANCE = new MinecraftGeometryRenderer();
@Override @Override
public boolean render(ItemStack stack, Path path) { public boolean render(ItemStack stack, Path path) {

View File

@@ -284,7 +284,7 @@ public class BedrockItemMapper {
if (customModel.isPresent()) { if (customModel.isPresent()) {
texture = texture.withPath(path -> path + "_icon"); texture = texture.withPath(path -> path + "_icon");
// FIXME Bit of a hack, preferably render geometry at a later stage // 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); packContext.additionalTextureConsumer().accept(geometryTexture);
} }

View File

@@ -3,10 +3,11 @@ package org.geysermc.rainbow.mapping;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import org.geysermc.rainbow.mapping.geometry.GeometryRenderer; import org.geysermc.rainbow.mapping.geometry.GeometryRenderer;
import org.geysermc.rainbow.definition.GeyserMappings; import org.geysermc.rainbow.definition.GeyserMappings;
import org.geysermc.rainbow.pack.PackPaths;
import java.nio.file.Path;
import java.util.function.Consumer; import java.util.function.Consumer;
public record PackContext(GeyserMappings mappings, Path packPath, BedrockItemConsumer itemConsumer, AssetResolver assetResolver, public record PackContext(GeyserMappings mappings, PackPaths paths, BedrockItemConsumer itemConsumer, AssetResolver assetResolver,
GeometryRenderer geometryRenderer, Consumer<ResourceLocation> additionalTextureConsumer) { GeometryRenderer geometryRenderer, Consumer<ResourceLocation> additionalTextureConsumer,
boolean reportSuccesses) {
} }

View File

@@ -3,22 +3,22 @@ package org.geysermc.rainbow.pack;
import com.mojang.serialization.JsonOps; import com.mojang.serialization.JsonOps;
import it.unimi.dsi.fastutil.ints.IntOpenHashSet; import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
import it.unimi.dsi.fastutil.ints.IntSet; 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.core.component.DataComponents;
import net.minecraft.resources.RegistryOps; import net.minecraft.resources.RegistryOps;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.ProblemReporter; import net.minecraft.util.ProblemReporter;
import net.minecraft.util.RandomSource; import net.minecraft.world.item.Item;
import net.minecraft.util.StringUtil;
import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.component.CustomModelData; import net.minecraft.world.item.component.CustomModelData;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.geysermc.rainbow.CodecUtil; import org.geysermc.rainbow.CodecUtil;
import org.geysermc.rainbow.PackConstants; import org.geysermc.rainbow.PackConstants;
import org.geysermc.rainbow.Rainbow;
import org.geysermc.rainbow.mapping.AssetResolver; import org.geysermc.rainbow.mapping.AssetResolver;
import org.geysermc.rainbow.mapping.BedrockItemMapper; import org.geysermc.rainbow.mapping.BedrockItemMapper;
import org.geysermc.rainbow.mapping.PackContext; import org.geysermc.rainbow.mapping.PackContext;
import org.geysermc.rainbow.mapping.geometry.GeometryRenderer;
import org.geysermc.rainbow.mapping.geometry.NoopGeometryRenderer; import org.geysermc.rainbow.mapping.geometry.NoopGeometryRenderer;
import org.geysermc.rainbow.definition.GeyserMappings; import org.geysermc.rainbow.definition.GeyserMappings;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -27,7 +27,6 @@ import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
@@ -35,68 +34,38 @@ import java.util.Optional;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.UnaryOperator;
public class BedrockPack { public class BedrockPack {
private static final List<String> 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 String name;
private final Path exportPath; private final PackPaths paths;
private final Path packPath;
private final PackManifest manifest;
private final GeyserMappings mappings;
private final BedrockTextures.Builder itemTextures;
private final BedrockTextures.Builder itemTextures = BedrockTextures.builder();
private final Set<BedrockItem> bedrockItems = new HashSet<>(); private final Set<BedrockItem> bedrockItems = new HashSet<>();
private final Set<ResourceLocation> texturesToExport = new HashSet<>(); private final Set<ResourceLocation> texturesToExport = new HashSet<>();
private final Set<ResourceLocation> modelsMapped = new HashSet<>(); private final Set<ResourceLocation> modelsMapped = new HashSet<>();
private final IntSet customModelDataMapped = new IntOpenHashSet(); private final IntSet customModelDataMapped = new IntOpenHashSet();
private final PackContext context;
private final PackManifest manifest;
private final ProblemReporter.Collector reporter; private final ProblemReporter.Collector reporter;
private final PackContext context; public BedrockPack(String name, PackPaths paths, AssetResolver assetResolver,
GeometryRenderer geometryRenderer, ProblemReporter.Collector reporter,
public BedrockPack(String name, AssetResolver assetResolver) throws IOException { boolean reportSuccesses) {
this.name = name; this.name = name;
this.paths = paths;
// Not reading existing item mappings/texture atlas for now since that doesn't work all that well yet // Not reading existing item mappings/texture atlas for now since that doesn't work all that well yet
exportPath = createPackDirectory(name); this.context = new PackContext(new GeyserMappings(), paths, item -> {
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 -> {
itemTextures.withItemTexture(item); itemTextures.withItemTexture(item);
if (item.exportTexture()) { if (item.exportTexture()) {
texturesToExport.add(item.texture()); texturesToExport.add(item.texture());
} }
bedrockItems.add(item); bedrockItems.add(item);
}, assetResolver, NoopGeometryRenderer.INSTANCE, texturesToExport::add); }, assetResolver, geometryRenderer, texturesToExport::add, reportSuccesses);
manifest = defaultManifest(name);
this.reporter = reporter;
} }
public String name() { public String name() {
@@ -146,20 +115,26 @@ public class BedrockPack {
return problems.get() ? MappingResult.PROBLEMS_OCCURRED : MappingResult.MAPPED_SUCCESSFULLY; return problems.get() ? MappingResult.PROBLEMS_OCCURRED : MappingResult.MAPPED_SUCCESSFULLY;
} }
public MappingResult map(Holder<Item> item, DataComponentPatch patch) {
ItemStack stack = new ItemStack(item);
stack.applyComponents(patch);
return map(stack);
}
public boolean save() { public boolean save() {
boolean success = true; boolean success = true;
try { try {
CodecUtil.trySaveJson(GeyserMappings.CODEC, mappings, exportPath.resolve(MAPPINGS_FILE), RegistryOps.create(JsonOps.INSTANCE, context.assetResolver().registries())); CodecUtil.trySaveJson(GeyserMappings.CODEC, context.mappings(), paths.mappings(), RegistryOps.create(JsonOps.INSTANCE, context.assetResolver().registries()));
CodecUtil.trySaveJson(PackManifest.CODEC, manifest, packPath.resolve(MANIFEST_FILE)); CodecUtil.trySaveJson(PackManifest.CODEC, manifest, paths.manifest());
CodecUtil.trySaveJson(BedrockTextureAtlas.CODEC, BedrockTextureAtlas.itemAtlas(name, itemTextures), packPath.resolve(ITEM_ATLAS_FILE)); CodecUtil.trySaveJson(BedrockTextureAtlas.CODEC, BedrockTextureAtlas.itemAtlas(name, itemTextures), paths.itemAtlas());
} catch (IOException | NullPointerException exception) { } catch (IOException | NullPointerException exception) {
reporter.forChild(() -> "saving Geyser mappings, pack manifest, and texture atlas ").report(() -> "failed to save to pack: " + exception); reporter.forChild(() -> "saving Geyser mappings, pack manifest, and texture atlas ").report(() -> "failed to save to pack: " + exception);
success = false; success = false;
} }
for (BedrockItem item : bedrockItems) { for (BedrockItem item : bedrockItems) {
try { 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) { } catch (IOException exception) {
reporter.forChild(() -> "files for bedrock item " + item.identifier() + " ").report(() -> "failed to save to pack: " + exception); reporter.forChild(() -> "files for bedrock item " + item.identifier() + " ").report(() -> "failed to save to pack: " + exception);
success = false; success = false;
@@ -169,7 +144,7 @@ public class BedrockPack {
for (ResourceLocation texture : texturesToExport) { for (ResourceLocation texture : texturesToExport) {
texture = texture.withPath(path -> "textures/" + path + ".png"); texture = texture.withPath(path -> "textures/" + path + ".png");
try (InputStream inputTexture = context.assetResolver().getTexture(texture)) { try (InputStream inputTexture = context.assetResolver().getTexture(texture)) {
Path texturePath = packPath.resolve(texture.getPath()); Path texturePath = paths.packRoot().resolve(texture.getPath());
CodecUtil.ensureDirectoryExists(texturePath.getParent()); CodecUtil.ensureDirectoryExists(texturePath.getParent());
try (OutputStream outputTexture = new FileOutputStream(texturePath.toFile())) { try (OutputStream outputTexture = new FileOutputStream(texturePath.toFile())) {
IOUtils.copy(inputTexture, outputTexture); IOUtils.copy(inputTexture, outputTexture);
@@ -181,71 +156,35 @@ public class BedrockPack {
} }
} }
if (paths.zipOutput().isPresent()) {
try { try {
CodecUtil.tryZipDirectory(packPath, exportPath.resolve(PACK_ZIP_FILE)); CodecUtil.tryZipDirectory(paths.packRoot(), paths.zipOutput().get());
} catch (IOException exception) { } catch (IOException exception) {
success = false; success = false;
} }
try {
Files.writeString(exportPath.resolve(REPORT_FILE), createPackSummary());
} catch (IOException exception) {
// TODO log
} }
return success; return success;
} }
public Path getExportPath() { public int getMappings() {
return exportPath; return context.mappings().size();
} }
private String createPackSummary() { public Set<BedrockItem> getBedrockItems() {
String problems = reporter.getTreeReport(); return Set.copyOf(bedrockItems);
if (StringUtil.isBlank(problems)) {
problems = "Well that's odd... there's nothing here!";
} }
long attachables = bedrockItems.stream().filter(item -> item.attachable().isPresent()).count(); public int getItemTextureAtlasSize() {
long geometries = bedrockItems.stream().filter(item -> item.geometry().isPresent()).count(); return itemTextures.build().size();
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);
} }
private static String randomSummaryComment() { public int getAdditionalExportedTextures() {
if (RANDOM.nextDouble() < 0.6) { return texturesToExport.size();
/*SplashRenderer splash = Minecraft.getInstance().getSplashManager().getSplash();
if (splash == null) {
return "Undefined Undefined :(";
}
return ((SplashRendererAccessor) splash).getSplash();*/ // TODO
}
return randomBuiltinSummaryComment();
} }
private static String randomBuiltinSummaryComment() { public ProblemReporter.Collector getReporter() {
return PACK_SUMMARY_COMMENTS.get(RANDOM.nextInt(PACK_SUMMARY_COMMENTS.size())); return reporter;
}
private static Path createPackDirectory(String name) throws IOException {
Path path = EXPORT_DIRECTORY.resolve(name);
CodecUtil.ensureDirectoryExists(path);
return path;
} }
private static PackManifest defaultManifest(String name) { 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)))); 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<Path> attachablesPath = resolve(ATTACHABLES_DIRECTORY);
private UnaryOperator<Path> geometryPath = resolve(GEOMETRY_DIRECTORY);
private UnaryOperator<Path> animationPath = resolve(ANIMATION_DIRECTORY);
private UnaryOperator<Path> manifestPath = resolve(MANIFEST_FILE);
private UnaryOperator<Path> 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> path) {
attachablesPath = path;
return this;
}
public Builder withGeometryPath(Path absolute) {
return withGeometryPath(path -> absolute);
}
public Builder withGeometryPath(UnaryOperator<Path> path) {
geometryPath = path;
return this;
}
public Builder withAnimationPath(Path absolute) {
return withAnimationPath(path -> absolute);
}
public Builder withAnimationPath(UnaryOperator<Path> path) {
animationPath = path;
return this;
}
public Builder withManifestPath(Path absolute) {
return withManifestPath(path -> absolute);
}
public Builder withManifestPath(UnaryOperator<Path> path) {
manifestPath = path;
return this;
}
public Builder withItemAtlasPath(Path absolute) {
return withItemAtlasPath(path -> absolute);
}
public Builder withItemAtlasPath(UnaryOperator<Path> 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<Path> resolve(Path child) {
return root -> root.resolve(child);
}
}
public enum MappingResult { public enum MappingResult {
NONE_MAPPED, NONE_MAPPED,
MAPPED_SUCCESSFULLY, MAPPED_SUCCESSFULLY,

View File

@@ -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<Path> zipOutput) {
}