package net.minecraft.gametest.framework; import com.mojang.logging.LogUtils; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Optional; import java.util.function.Consumer; import java.util.stream.Stream; import joptsimple.OptionParser; import joptsimple.OptionSet; import joptsimple.OptionSpec; import net.minecraft.SuppressForbidden; import net.minecraft.Util; import net.minecraft.server.Bootstrap; import net.minecraft.server.MinecraftServer; import net.minecraft.server.packs.repository.PackRepository; import net.minecraft.server.packs.repository.ServerPacksSource; import net.minecraft.world.level.storage.LevelStorageSource; import org.apache.commons.io.FileUtils; import org.slf4j.Logger; public class GameTestMainUtil { private static final Logger LOGGER = LogUtils.getLogger(); private static final String DEFAULT_UNIVERSE_DIR = "gametestserver"; private static final String LEVEL_NAME = "gametestworld"; private static final OptionParser parser = new OptionParser(); private static final OptionSpec universe = parser.accepts( "universe", "The path to where the test server world will be created. Any existing folder will be replaced." ) .withRequiredArg() .defaultsTo("gametestserver"); private static final OptionSpec report = parser.accepts("report", "Exports results in a junit-like XML report at the given path.") .withRequiredArg() .ofType(File.class); private static final OptionSpec tests = parser.accepts("tests", "Which test(s) to run (namespaced ID selector using wildcards). Empty means run all.") .withRequiredArg(); private static final OptionSpec verify = parser.accepts( "verify", "Runs the tests specified with `test` or `testNamespace` 100 times for each 90 degree rotation step" ) .withRequiredArg() .ofType(Boolean.class) .defaultsTo(false); private static final OptionSpec packs = parser.accepts("packs", "A folder of datapacks to include in the world").withRequiredArg(); private static final OptionSpec help = parser.accepts("help").forHelp(); @SuppressForbidden( reason = "Using System.err due to no bootstrap" ) public static void runGameTestServer(String[] args, Consumer universeOutput) throws Exception { parser.allowsUnrecognizedOptions(); OptionSet optionSet = parser.parse(args); if (optionSet.has(help)) { parser.printHelpOn(System.err); } else { if (optionSet.valueOf(verify) && !optionSet.has(tests)) { LOGGER.error("Please specify a test selection to run the verify option. For example: --verify --tests example:test_something_*"); System.exit(-1); } LOGGER.info("Running GameTestMain with cwd '{}', universe path '{}'", System.getProperty("user.dir"), optionSet.valueOf(universe)); if (optionSet.has(report)) { GlobalTestReporter.replaceWith(new JUnitLikeTestReporter(report.value(optionSet))); } Bootstrap.bootStrap(); Util.startTimerHackThread(); String string = optionSet.valueOf(universe); createOrResetDir(string); universeOutput.accept(string); if (optionSet.has(packs)) { String string2 = optionSet.valueOf(packs); copyPacks(string, string2); } LevelStorageSource.LevelStorageAccess levelStorageAccess = LevelStorageSource.createDefault(Paths.get(string)).createAccess("gametestworld"); PackRepository packRepository = ServerPacksSource.createPackRepository(levelStorageAccess); MinecraftServer.spin( thread -> GameTestServer.create(thread, levelStorageAccess, packRepository, optionalFromOption(optionSet, tests), optionSet.has(verify)) ); } } private static Optional optionalFromOption(OptionSet options, OptionSpec option) { return options.has(option) ? Optional.of(options.valueOf(option)) : Optional.empty(); } private static void createOrResetDir(String dir) throws IOException { Path path = Paths.get(dir); if (Files.exists(path, new LinkOption[0])) { FileUtils.deleteDirectory(path.toFile()); } Files.createDirectories(path); } private static void copyPacks(String universe, String packs) throws IOException { Path path = Paths.get(universe).resolve("gametestworld").resolve("datapacks"); if (!Files.exists(path, new LinkOption[0])) { Files.createDirectories(path); } Path path2 = Paths.get(packs); if (Files.exists(path2, new LinkOption[0])) { Stream stream = Files.list(path2); try { for (Path path3 : stream.toList()) { Path path4 = path.resolve(path3.getFileName()); if (Files.isDirectory(path3, new LinkOption[0])) { if (Files.isRegularFile(path3.resolve("pack.mcmeta"), new LinkOption[0])) { FileUtils.copyDirectory(path3.toFile(), path4.toFile()); LOGGER.info("Included folder pack {}", path3.getFileName()); } } else if (path3.toString().endsWith(".zip")) { Files.copy(path3, path4); LOGGER.info("Included zip pack {}", path3.getFileName()); } } } catch (Throwable var9) { if (stream != null) { try { stream.close(); } catch (Throwable var8) { var9.addSuppressed(var8); } } throw var9; } if (stream != null) { stream.close(); } } } }