mirror of
https://github.com/GeyserMC/Rainbow.git
synced 2025-12-19 14:59:16 +00:00
Start working on manifest.json generation
This commit is contained in:
52
src/main/java/org/geysermc/packgenerator/CodecUtil.java
Normal file
52
src/main/java/org/geysermc/packgenerator/CodecUtil.java
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package org.geysermc.packgenerator;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
|
import com.google.gson.GsonBuilder;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.DataResult;
|
||||||
|
import com.mojang.serialization.JsonOps;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
|
||||||
|
public class CodecUtil {
|
||||||
|
|
||||||
|
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
|
||||||
|
|
||||||
|
public static <O, T> RecordCodecBuilder<O, T> unitVerifyCodec(Codec<T> codec, String field, T value) {
|
||||||
|
return codec.validate(read -> {
|
||||||
|
if (!read.equals(value)) {
|
||||||
|
return DataResult.error(() -> field + " must equal " + value);
|
||||||
|
}
|
||||||
|
return DataResult.success(read);
|
||||||
|
}).fieldOf(field).forGetter(object -> value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> void trySaveJson(Codec<T> codec, T object, Path path) throws IOException {
|
||||||
|
JsonElement json = codec.encodeStart(JsonOps.INSTANCE, object).getOrThrow();
|
||||||
|
|
||||||
|
try {
|
||||||
|
ensureDirectoryExists(path.getParent());
|
||||||
|
Files.writeString(path, GSON.toJson(json));
|
||||||
|
} catch (IOException exception) {
|
||||||
|
GeyserMappingsGenerator.LOGGER.warn("Failed to write file " + path + "!", exception);
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void ensureDirectoryExists(Path directory) throws IOException {
|
||||||
|
if (!Files.isDirectory(directory)) {
|
||||||
|
try {
|
||||||
|
Files.createDirectories(directory);
|
||||||
|
} catch (IOException exception) {
|
||||||
|
GeyserMappingsGenerator.LOGGER.warn("Failed to create directory!", exception);
|
||||||
|
throw exception;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.geysermc.packgenerator;
|
package org.geysermc.packgenerator;
|
||||||
|
|
||||||
import com.mojang.brigadier.arguments.StringArgumentType;
|
import com.mojang.brigadier.arguments.StringArgumentType;
|
||||||
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
import com.mojang.logging.LogUtils;
|
import com.mojang.logging.LogUtils;
|
||||||
import net.fabricmc.api.ClientModInitializer;
|
import net.fabricmc.api.ClientModInitializer;
|
||||||
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
|
import net.fabricmc.fabric.api.client.command.v2.ClientCommandManager;
|
||||||
@@ -9,6 +10,8 @@ import net.minecraft.network.chat.Component;
|
|||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
public class GeyserMappingsGenerator implements ClientModInitializer {
|
public class GeyserMappingsGenerator implements ClientModInitializer {
|
||||||
|
|
||||||
public static final Logger LOGGER = LogUtils.getLogger();
|
public static final Logger LOGGER = LogUtils.getLogger();
|
||||||
@@ -22,7 +25,11 @@ public class GeyserMappingsGenerator implements ClientModInitializer {
|
|||||||
.then(ClientCommandManager.argument("name", StringArgumentType.word())
|
.then(ClientCommandManager.argument("name", StringArgumentType.word())
|
||||||
.executes(context -> {
|
.executes(context -> {
|
||||||
String name = StringArgumentType.getString(context, "name");
|
String name = StringArgumentType.getString(context, "name");
|
||||||
PackManager.getInstance().startPack(name);
|
try {
|
||||||
|
PackManager.getInstance().startPack(name);
|
||||||
|
} catch (IOException exception) {
|
||||||
|
throw new SimpleCommandExceptionType(Component.literal(exception.getMessage())).create();
|
||||||
|
}
|
||||||
context.getSource().sendFeedback(Component.literal("Created pack with name " + name));
|
context.getSource().sendFeedback(Component.literal("Created pack with name " + name));
|
||||||
return 0;
|
return 0;
|
||||||
})
|
})
|
||||||
@@ -50,7 +57,11 @@ public class GeyserMappingsGenerator implements ClientModInitializer {
|
|||||||
)
|
)
|
||||||
.then(ClientCommandManager.literal("finish")
|
.then(ClientCommandManager.literal("finish")
|
||||||
.executes(context -> {
|
.executes(context -> {
|
||||||
PackManager.getInstance().finish();
|
try {
|
||||||
|
PackManager.getInstance().finish();
|
||||||
|
} catch (IOException exception) {
|
||||||
|
throw new SimpleCommandExceptionType(Component.literal(exception.getMessage())).create();
|
||||||
|
}
|
||||||
context.getSource().sendFeedback(Component.literal("Wrote pack to disk"));
|
context.getSource().sendFeedback(Component.literal("Wrote pack to disk"));
|
||||||
return 0;
|
return 0;
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,39 +1,43 @@
|
|||||||
package org.geysermc.packgenerator;
|
package org.geysermc.packgenerator;
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
|
||||||
import com.google.gson.GsonBuilder;
|
|
||||||
import com.google.gson.JsonElement;
|
|
||||||
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
||||||
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
||||||
import com.mojang.serialization.JsonOps;
|
|
||||||
import net.fabricmc.loader.api.FabricLoader;
|
import net.fabricmc.loader.api.FabricLoader;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
import org.geysermc.packgenerator.mappings.GeyserMappings;
|
import org.geysermc.packgenerator.mappings.GeyserMappings;
|
||||||
|
import org.geysermc.packgenerator.pack.PackManifest;
|
||||||
|
|
||||||
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.UUID;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
public final class PackManager {
|
public final class PackManager {
|
||||||
public static final Path EXPORT_DIRECTORY = FabricLoader.getInstance().getGameDir()
|
private static final Path EXPORT_DIRECTORY = FabricLoader.getInstance().getGameDir().resolve("geyser");
|
||||||
.resolve("geyser");
|
private static final Function<Path, Path> PACK_DIRECTORY = path -> path.resolve("pack");
|
||||||
|
|
||||||
private static final PackManager INSTANCE = new PackManager();
|
private static final PackManager INSTANCE = new PackManager();
|
||||||
|
|
||||||
private String currentPackName;
|
private String currentPackName;
|
||||||
private Path exportPath;
|
private Path exportPath;
|
||||||
|
private Path packPath;
|
||||||
private GeyserMappings mappings;
|
private GeyserMappings mappings;
|
||||||
|
private PackManifest manifest;
|
||||||
|
|
||||||
private PackManager() {}
|
private PackManager() {}
|
||||||
|
|
||||||
public void startPack(String name) throws CommandSyntaxException {
|
public void startPack(String name) throws CommandSyntaxException, IOException {
|
||||||
if (currentPackName != null) {
|
if (currentPackName != null) {
|
||||||
throw new SimpleCommandExceptionType(Component.literal("Already started a pack with name " + currentPackName)).create();
|
throw new SimpleCommandExceptionType(Component.literal("Already started a pack with name " + currentPackName)).create();
|
||||||
}
|
}
|
||||||
currentPackName = name;
|
currentPackName = name;
|
||||||
exportPath = createPackDirectory(currentPackName);
|
exportPath = createPackDirectory(currentPackName);
|
||||||
|
packPath = PACK_DIRECTORY.apply(exportPath);
|
||||||
mappings = new GeyserMappings();
|
mappings = new GeyserMappings();
|
||||||
|
manifest = new PackManifest(new PackManifest.Header(name, "PLACEHOLDER", UUID.randomUUID(), "PLACEHOLDER"),
|
||||||
|
List.of(new PackManifest.Module(new PackManifest.Header(name, "PLACEHOLDER", UUID.randomUUID(), "PLACEHOLDER"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean map(ItemStack stack, boolean throwOnModelMissing) throws CommandSyntaxException {
|
public boolean map(ItemStack stack, boolean throwOnModelMissing) throws CommandSyntaxException {
|
||||||
@@ -51,19 +55,11 @@ public final class PackManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void finish() throws CommandSyntaxException {
|
public void finish() throws CommandSyntaxException, IOException {
|
||||||
ensurePackIsCreated();
|
ensurePackIsCreated();
|
||||||
|
|
||||||
JsonElement savedMappings = GeyserMappings.CODEC.encodeStart(JsonOps.INSTANCE, mappings)
|
CodecUtil.trySaveJson(GeyserMappings.CODEC, mappings, exportPath.resolve("geyser_mappings.json"));
|
||||||
.getOrThrow(error -> new SimpleCommandExceptionType(Component.literal("Failed to encode Geyser mappings! " + error)).create());
|
CodecUtil.trySaveJson(PackManifest.CODEC, manifest, packPath.resolve("manifest.json"));
|
||||||
|
|
||||||
Gson gson = new GsonBuilder().setPrettyPrinting().create();
|
|
||||||
try {
|
|
||||||
Files.writeString(exportPath.resolve("geyser_mappings.json"), gson.toJson(savedMappings));
|
|
||||||
} catch (IOException exception) {
|
|
||||||
GeyserMappingsGenerator.LOGGER.warn("Failed to write Geyser mappings to pack!", exception);
|
|
||||||
throw new SimpleCommandExceptionType(Component.literal("Failed to write Geyser mappings to pack!")).create();
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPackName = null;
|
currentPackName = null;
|
||||||
}
|
}
|
||||||
@@ -74,16 +70,9 @@ public final class PackManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Path createPackDirectory(String name) throws CommandSyntaxException {
|
private static Path createPackDirectory(String name) throws IOException {
|
||||||
Path path = EXPORT_DIRECTORY.resolve(name);
|
Path path = EXPORT_DIRECTORY.resolve(name);
|
||||||
if (!Files.isDirectory(path)) {
|
CodecUtil.ensureDirectoryExists(path);
|
||||||
try {
|
|
||||||
Files.createDirectories(path);
|
|
||||||
} catch (IOException exception) {
|
|
||||||
GeyserMappingsGenerator.LOGGER.warn("Failed to create pack export directory!", exception);
|
|
||||||
throw new SimpleCommandExceptionType(Component.literal("Failed to create pack export directory for pack " + name)).create();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import net.minecraft.core.component.DataComponents;
|
|||||||
import net.minecraft.resources.ResourceLocation;
|
import net.minecraft.resources.ResourceLocation;
|
||||||
import net.minecraft.world.item.Item;
|
import net.minecraft.world.item.Item;
|
||||||
import net.minecraft.world.item.ItemStack;
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.geysermc.packgenerator.CodecUtil;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
@@ -22,7 +23,7 @@ public class GeyserMappings {
|
|||||||
|
|
||||||
public static final Codec<GeyserMappings> CODEC = RecordCodecBuilder.create(instance ->
|
public static final Codec<GeyserMappings> CODEC = RecordCodecBuilder.create(instance ->
|
||||||
instance.group(
|
instance.group(
|
||||||
Codec.INT.fieldOf("format_version").forGetter(mappings -> 2),
|
CodecUtil.unitVerifyCodec(Codec.INT, "format_version", 2),
|
||||||
MAPPINGS_CODEC.fieldOf("items").forGetter(GeyserMappings::mappings)
|
MAPPINGS_CODEC.fieldOf("items").forGetter(GeyserMappings::mappings)
|
||||||
).apply(instance, (format, mappings) -> new GeyserMappings(mappings))
|
).apply(instance, (format, mappings) -> new GeyserMappings(mappings))
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package org.geysermc.packgenerator.pack;
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.MapCodec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
import net.minecraft.core.UUIDUtil;
|
||||||
|
import org.geysermc.packgenerator.CodecUtil;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
// TODO metadata
|
||||||
|
public record PackManifest(Header header, List<Module> modules) {
|
||||||
|
|
||||||
|
public static final Codec<PackManifest> CODEC = RecordCodecBuilder.create(instance ->
|
||||||
|
instance.group(
|
||||||
|
CodecUtil.unitVerifyCodec(Codec.INT, "format_version", 2),
|
||||||
|
Header.CODEC.fieldOf("header").forGetter(PackManifest::header),
|
||||||
|
Module.CODEC.listOf().fieldOf("modules").forGetter(PackManifest::modules)
|
||||||
|
).apply(instance, (formatVersion, header, modules) -> new PackManifest(header, modules))
|
||||||
|
);
|
||||||
|
|
||||||
|
public record Header(String name, String description, UUID uuid, String version) {
|
||||||
|
public static final MapCodec<Header> MAP_CODEC = RecordCodecBuilder.mapCodec(instance ->
|
||||||
|
instance.group(
|
||||||
|
Codec.STRING.fieldOf("name").forGetter(Header::name),
|
||||||
|
Codec.STRING.fieldOf("description").forGetter(Header::description),
|
||||||
|
UUIDUtil.STRING_CODEC.fieldOf("uuid").forGetter(Header::uuid),
|
||||||
|
Codec.STRING.fieldOf("version").forGetter(Header::version)
|
||||||
|
).apply(instance, Header::new)
|
||||||
|
);
|
||||||
|
public static final Codec<Header> CODEC = MAP_CODEC.codec();
|
||||||
|
}
|
||||||
|
|
||||||
|
public record Module(Header header) {
|
||||||
|
public static final Codec<Module> CODEC = RecordCodecBuilder.create(instance ->
|
||||||
|
instance.group(
|
||||||
|
CodecUtil.unitVerifyCodec(Codec.STRING, "type", "resources"),
|
||||||
|
Header.MAP_CODEC.forGetter(Module::header)
|
||||||
|
).apply(instance, (type, header) -> new Module(header))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user