From 9b7b8d5111add986da9b73fc072a399561268e2b Mon Sep 17 00:00:00 2001 From: Misode Date: Fri, 27 Sep 2024 00:13:33 +0200 Subject: [PATCH] Add option to generate commands.json report --- .../io/github/misode/packtest/PackTest.java | 71 +++++++++++++++++-- .../packtest/mixin/server/MainMixin.java | 5 ++ 2 files changed, 70 insertions(+), 6 deletions(-) diff --git a/src/main/java/io/github/misode/packtest/PackTest.java b/src/main/java/io/github/misode/packtest/PackTest.java index a6a494d..29fd5c3 100644 --- a/src/main/java/io/github/misode/packtest/PackTest.java +++ b/src/main/java/io/github/misode/packtest/PackTest.java @@ -1,16 +1,37 @@ package io.github.misode.packtest; +import com.google.gson.JsonObject; +import com.google.gson.stream.JsonWriter; +import com.mojang.brigadier.CommandDispatcher; import io.github.misode.packtest.commands.*; +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap; import net.fabricmc.api.ModInitializer; import net.fabricmc.fabric.api.command.v2.CommandRegistrationCallback; +import net.minecraft.FileUtil; +import net.minecraft.Util; +import net.minecraft.commands.CommandBuildContext; +import net.minecraft.commands.CommandSourceStack; +import net.minecraft.commands.Commands; +import net.minecraft.commands.synchronization.ArgumentUtils; import net.minecraft.core.BlockPos; +import net.minecraft.data.registries.VanillaRegistries; import net.minecraft.gametest.framework.GameTestServer; import net.minecraft.server.packs.repository.PackRepository; +import net.minecraft.util.GsonHelper; import net.minecraft.world.level.storage.LevelStorageSource; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Comparator; import java.util.List; +import java.util.function.ToIntFunction; public class PackTest implements ModInitializer { public static final Logger LOGGER = LoggerFactory.getLogger(PackTest.class); @@ -27,15 +48,53 @@ public static boolean isAnnotationsEnabled() { return isAutoEnabled() && System.getProperty("packtest.auto.annotations") != null; } + public static boolean shouldGenerateCommands() { + return System.getProperty("packtest.generate.commands") != null; + } + @Override public void onInitialize() { - CommandRegistrationCallback.EVENT.register((dispatcher, buildContext, environment) -> { - AssertCommand.register(dispatcher, buildContext); - AwaitCommand.register(dispatcher, buildContext); - FailCommand.register(dispatcher, buildContext); - DummyCommand.register(dispatcher); - SucceedCommand.register(dispatcher); + CommandRegistrationCallback.EVENT.register((dispatcher, buildContext, environment) -> + registerCommands(dispatcher, buildContext) + ); + } + + public static void generateCommandsReport() { + Path path = Paths.get("generated", "reports", "commands.json"); + CommandDispatcher dispatcher = new CommandDispatcher<>(); + registerCommands(dispatcher, Commands.createValidationContext(VanillaRegistries.createLookup())); + JsonObject data = ArgumentUtils.serializeNodeToJson(dispatcher, dispatcher.getRoot()); + ToIntFunction fixedOrderFields = Util.make(new Object2IntOpenHashMap<>(), map -> { + map.put("type", 0); + map.put("parser", 1); + map.put("properties", 2); + map.put("executable", 3); + map.put("redirect", 4); + map.put("children", 5); + map.defaultReturnValue(6); }); + Comparator keyComparator = Comparator.comparingInt(fixedOrderFields).thenComparing(string -> string); + try { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + try (JsonWriter writer = new JsonWriter(new OutputStreamWriter(outputStream, StandardCharsets.UTF_8))) { + writer.setSerializeNulls(false); + writer.setIndent(" "); + GsonHelper.writeValue(writer, data, keyComparator); + } + FileUtil.createDirectoriesSafe(path.getParent()); + Files.write(path, outputStream.toByteArray()); + LOGGER.info("Saved file to {}", path); + } catch (IOException e) { + LOGGER.error("Failed to save file to {}", path, e); + } + } + + private static void registerCommands(CommandDispatcher dispatcher, CommandBuildContext buildContext) { + AssertCommand.register(dispatcher, buildContext); + AwaitCommand.register(dispatcher, buildContext); + FailCommand.register(dispatcher, buildContext); + DummyCommand.register(dispatcher); + SucceedCommand.register(dispatcher); } public static void runHeadlessServer(LevelStorageSource.LevelStorageAccess storage, PackRepository packRepository) { diff --git a/src/main/java/io/github/misode/packtest/mixin/server/MainMixin.java b/src/main/java/io/github/misode/packtest/mixin/server/MainMixin.java index c141abc..36c85b6 100644 --- a/src/main/java/io/github/misode/packtest/mixin/server/MainMixin.java +++ b/src/main/java/io/github/misode/packtest/mixin/server/MainMixin.java @@ -17,8 +17,13 @@ public class MainMixin { @Inject(method = "main", cancellable = true, at = @At(value = "INVOKE_ASSIGN", target = "Lnet/minecraft/server/packs/repository/ServerPacksSource;createPackRepository(Lnet/minecraft/world/level/storage/LevelStorageSource$LevelStorageAccess;)Lnet/minecraft/server/packs/repository/PackRepository;", shift = At.Shift.AFTER)) private static void mainStartServer(String[] args, CallbackInfo ci, @Local LevelStorageSource.LevelStorageAccess storage, @Local PackRepository packRepository) { + if (PackTest.shouldGenerateCommands()) { + PackTest.generateCommandsReport(); + } if (PackTest.isAutoEnabled()) { PackTest.runHeadlessServer(storage, packRepository); + } + if (PackTest.shouldGenerateCommands() || PackTest.isAutoEnabled()) { ci.cancel(); } }