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:
@@ -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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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) {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user