minecraft-source/src/net/minecraft/gametest/framework/TestCommand.java

280 lines
17 KiB
Java

package net.minecraft.gametest.framework;
import com.mojang.brigadier.context.CommandContext;
import net.minecraft.server.level.ServerPlayer;
import java.io.OutputStream;
import java.io.BufferedReader;
import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.TagParser;
import java.nio.file.OpenOption;
import java.io.Reader;
import org.apache.commons.io.IOUtils;
import java.nio.file.Path;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.attribute.FileAttribute;
import net.minecraft.data.structures.NbtToSnbt;
import net.minecraft.resources.ResourceLocation;
import java.nio.file.Paths;
import java.util.function.Consumer;
import net.minecraft.util.Mth;
import javax.annotation.Nullable;
import java.util.Collection;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.Optional;
import net.minecraft.network.protocol.game.DebugPackets;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.HoverEvent;
import net.minecraft.ChatFormatting;
import net.minecraft.network.chat.Style;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.block.entity.StructureBlockEntity;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.level.block.Block;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.block.state.properties.Property;
import java.util.Set;
import net.minecraft.commands.arguments.blocks.BlockInput;
import java.util.Collections;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.core.BlockPos;
import com.mojang.brigadier.arguments.IntegerArgumentType;
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.arguments.ArgumentType;
import net.minecraft.commands.Commands;
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
import net.minecraft.commands.CommandSourceStack;
import com.mojang.brigadier.CommandDispatcher;
public class TestCommand {
public static void register(final CommandDispatcher<CommandSourceStack> commandDispatcher) {
commandDispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.literal("test").then(Commands.literal("runthis").executes(commandContext -> runNearbyTest((CommandSourceStack)commandContext.getSource())))).then(Commands.literal("runthese").executes(commandContext -> runAllNearbyTests((CommandSourceStack)commandContext.getSource())))).then(Commands.literal("run").then(Commands.argument("testName", (com.mojang.brigadier.arguments.ArgumentType<Object>)TestFunctionArgument.testFunctionArgument()).executes(commandContext -> runTest((CommandSourceStack)commandContext.getSource(), TestFunctionArgument.getTestFunction((CommandContext<CommandSourceStack>)commandContext, "testName")))))).then(((LiteralArgumentBuilder)Commands.literal("runall").executes(commandContext -> runAllTests((CommandSourceStack)commandContext.getSource()))).then(Commands.argument("testClassName", (com.mojang.brigadier.arguments.ArgumentType<Object>)TestClassNameArgument.testClassName()).executes(commandContext -> runAllTestsInClass((CommandSourceStack)commandContext.getSource(), TestClassNameArgument.getTestClassName((CommandContext<CommandSourceStack>)commandContext, "testClassName")))))).then(Commands.literal("export").then(Commands.argument("testName", (com.mojang.brigadier.arguments.ArgumentType<Object>)StringArgumentType.word()).executes(commandContext -> exportTestStructure((CommandSourceStack)commandContext.getSource(), StringArgumentType.getString(commandContext, "testName")))))).then(Commands.literal("import").then(Commands.argument("testName", (com.mojang.brigadier.arguments.ArgumentType<Object>)StringArgumentType.word()).executes(commandContext -> importTestStructure((CommandSourceStack)commandContext.getSource(), StringArgumentType.getString(commandContext, "testName")))))).then(((LiteralArgumentBuilder)Commands.literal("pos").executes(commandContext -> showPos((CommandSourceStack)commandContext.getSource(), "pos"))).then(Commands.argument("var", (com.mojang.brigadier.arguments.ArgumentType<Object>)StringArgumentType.word()).executes(commandContext -> showPos((CommandSourceStack)commandContext.getSource(), StringArgumentType.getString(commandContext, "var")))))).then(Commands.literal("create").then(((RequiredArgumentBuilder)Commands.argument("testName", (com.mojang.brigadier.arguments.ArgumentType<Object>)StringArgumentType.word()).executes(commandContext -> createNewStructure((CommandSourceStack)commandContext.getSource(), StringArgumentType.getString(commandContext, "testName"), 5, 5, 5))).then(((RequiredArgumentBuilder)Commands.argument("width", (com.mojang.brigadier.arguments.ArgumentType<Object>)IntegerArgumentType.integer()).executes(commandContext -> createNewStructure((CommandSourceStack)commandContext.getSource(), StringArgumentType.getString(commandContext, "testName"), IntegerArgumentType.getInteger(commandContext, "width"), IntegerArgumentType.getInteger(commandContext, "width"), IntegerArgumentType.getInteger(commandContext, "width")))).then(Commands.argument("height", (com.mojang.brigadier.arguments.ArgumentType<Object>)IntegerArgumentType.integer()).then(Commands.argument("depth", (com.mojang.brigadier.arguments.ArgumentType<Object>)IntegerArgumentType.integer()).executes(commandContext -> createNewStructure((CommandSourceStack)commandContext.getSource(), StringArgumentType.getString(commandContext, "testName"), IntegerArgumentType.getInteger(commandContext, "width"), IntegerArgumentType.getInteger(commandContext, "height"), IntegerArgumentType.getInteger(commandContext, "depth"))))))))).then(((LiteralArgumentBuilder)Commands.literal("clearall").executes(commandContext -> clearAllTests((CommandSourceStack)commandContext.getSource(), 200))).then(Commands.argument("radius", (com.mojang.brigadier.arguments.ArgumentType<Object>)IntegerArgumentType.integer()).executes(commandContext -> clearAllTests((CommandSourceStack)commandContext.getSource(), IntegerArgumentType.getInteger(commandContext, "radius"))))));
}
private static int createNewStructure(final CommandSourceStack cq, final String string, final int integer3, final int integer4, final int integer5) {
if (integer3 > 32 || integer4 > 32 || integer5 > 32) {
throw new IllegalArgumentException("The structure must be less than 32 blocks big in each axis");
}
final ServerLevel xd6 = cq.getLevel();
final BlockPos fk7 = new BlockPos(cq.getPosition());
final BlockPos fk8 = new BlockPos(fk7.getX(), cq.getLevel().getHeightmapPos(Heightmap.Types.WORLD_SURFACE, fk7).getY(), fk7.getZ() + 3);
StructureUtils.createNewEmptyStructureBlock(string.toLowerCase(), fk8, new BlockPos(integer3, integer4, integer5), 2, xd6);
for (int integer6 = 0; integer6 < integer3; ++integer6) {
for (int integer7 = 0; integer7 < integer5; ++integer7) {
final BlockPos fk9 = new BlockPos(fk8.getX() + integer6, fk8.getY() + 1, fk8.getZ() + integer7);
final Block bpe12 = Blocks.POLISHED_ANDESITE;
final BlockInput ds13 = new BlockInput(bpe12.defaultBlockState(), Collections.EMPTY_SET, null);
ds13.place(xd6, fk9, 2);
}
}
StructureUtils.addCommandBlockAndButtonToStartTest(fk8.offset(1, 0, -1), xd6);
return 0;
}
private static int showPos(final CommandSourceStack cq, final String string) throws CommandSyntaxException {
final BlockHitResult cvd3 = (BlockHitResult)cq.getPlayerOrException().pick(10.0, 1.0f, false);
final BlockPos fk4 = cvd3.getBlockPos();
final ServerLevel xd5 = cq.getLevel();
Optional<BlockPos> optional6 = StructureUtils.findStructureBlockContainingPos(fk4, 15, xd5);
if (!optional6.isPresent()) {
optional6 = StructureUtils.findStructureBlockContainingPos(fk4, 200, xd5);
}
if (!optional6.isPresent()) {
cq.sendFailure(new TextComponent("Can't find a structure block that contains the targeted pos " + fk4));
return 0;
}
final StructureBlockEntity bxi7 = (StructureBlockEntity)xd5.getBlockEntity(optional6.get());
final BlockPos fk5 = fk4.subtract(optional6.get());
final String string2 = fk5.getX() + ", " + fk5.getY() + ", " + fk5.getZ();
final String string3 = bxi7.getStructurePath();
final Component lf11 = new TextComponent(string2).setStyle(new Style().setBold(true).setColor(ChatFormatting.GREEN).setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponent("Click to copy to clipboard"))).setClickEvent(new ClickEvent(ClickEvent.Action.COPY_TO_CLIPBOARD, "final BlockPos " + string + " = new BlockPos(" + string2 + ");")));
cq.sendSuccess(new TextComponent("Position relative to " + string3 + ": ").append(lf11), false);
DebugPackets.sendGameTestAddMarker(xd5, new BlockPos(fk4), string2, -2147418368, 10000);
return 1;
}
private static int runNearbyTest(final CommandSourceStack cq) {
final BlockPos fk2 = new BlockPos(cq.getPosition());
final ServerLevel xd3 = cq.getLevel();
final BlockPos fk3 = StructureUtils.findNearestStructureBlock(fk2, 15, xd3);
if (fk3 == null) {
say(xd3, "Couldn't find any structure block within 15 radius", ChatFormatting.RED);
return 0;
}
GameTestRunner.clearMarkers(xd3);
runTest(xd3, fk3, null);
return 1;
}
private static int runAllNearbyTests(final CommandSourceStack cq) {
final BlockPos fk2 = new BlockPos(cq.getPosition());
final ServerLevel xd3 = cq.getLevel();
final Collection<BlockPos> collection4 = StructureUtils.findStructureBlocks(fk2, 200, xd3);
if (collection4.isEmpty()) {
say(xd3, "Couldn't find any structure blocks within 200 block radius", ChatFormatting.RED);
return 1;
}
GameTestRunner.clearMarkers(xd3);
say(cq, "Running " + collection4.size() + " tests...");
final MultipleTestTracker jf5 = new MultipleTestTracker();
collection4.forEach(fk -> runTest(xd3, fk, jf5));
return 1;
}
private static void runTest(final ServerLevel xd, final BlockPos fk, @Nullable final MultipleTestTracker jf) {
final StructureBlockEntity bxi4 = (StructureBlockEntity)xd.getBlockEntity(fk);
final String string5 = bxi4.getStructurePath();
final TestFunction jk6 = GameTestRegistry.getTestFunction(string5);
final GameTestInfo iw7 = new GameTestInfo(jk6, fk, xd);
if (jf != null) {
jf.add(iw7);
iw7.addListener(new TestSummaryDisplayer(xd, jf));
}
runTestPreparation(jk6, xd);
GameTestRunner.runTest(iw7, GameTestTicker.singleton);
}
private static void showTestSummaryIfAllDone(final ServerLevel xd, final MultipleTestTracker jf) {
if (jf.isDone()) {
say(xd, "GameTest done! " + jf.getTotalCount() + " tests were run", ChatFormatting.WHITE);
if (jf.hasFailedRequired()) {
say(xd, "" + jf.getFailedRequiredCount() + " required tests failed :(", ChatFormatting.RED);
}
else {
say(xd, "All required tests passed :)", ChatFormatting.GREEN);
}
if (jf.hasFailedOptional()) {
say(xd, "" + jf.getFailedOptionalCount() + " optional tests failed", ChatFormatting.GRAY);
}
}
}
private static int clearAllTests(final CommandSourceStack cq, final int integer) {
final ServerLevel xd3 = cq.getLevel();
GameTestRunner.clearMarkers(xd3);
final BlockPos fk4 = new BlockPos(cq.getPosition().x, cq.getLevel().getHeightmapPos(Heightmap.Types.WORLD_SURFACE, new BlockPos(cq.getPosition())).getY(), cq.getPosition().z);
GameTestRunner.clearAllTests(xd3, fk4, GameTestTicker.singleton, Mth.clamp(integer, 0, 1024));
return 1;
}
private static int runTest(final CommandSourceStack cq, final TestFunction jk) {
final ServerLevel xd3 = cq.getLevel();
final BlockPos fk4 = new BlockPos(cq.getPosition());
final BlockPos fk5 = new BlockPos(fk4.getX(), cq.getLevel().getHeightmapPos(Heightmap.Types.WORLD_SURFACE, fk4).getY(), fk4.getZ() + 3);
GameTestRunner.clearMarkers(xd3);
runTestPreparation(jk, xd3);
final GameTestInfo iw6 = new GameTestInfo(jk, fk5, xd3);
GameTestRunner.runTest(iw6, GameTestTicker.singleton);
return 1;
}
private static void runTestPreparation(final TestFunction jk, final ServerLevel xd) {
final Consumer<ServerLevel> consumer3 = GameTestRegistry.getBeforeBatchFunction(jk.getBatchName());
if (consumer3 != null) {
consumer3.accept(xd);
}
}
private static int runAllTests(final CommandSourceStack cq) {
GameTestRunner.clearMarkers(cq.getLevel());
runTests(cq, GameTestRegistry.getAllTestFunctions());
return 1;
}
private static int runAllTestsInClass(final CommandSourceStack cq, final String string) {
final Collection<TestFunction> collection3 = GameTestRegistry.getTestFunctionsForClassName(string);
GameTestRunner.clearMarkers(cq.getLevel());
runTests(cq, collection3);
return 1;
}
private static void runTests(final CommandSourceStack cq, final Collection<TestFunction> collection) {
final BlockPos fk3 = new BlockPos(cq.getPosition());
final BlockPos fk4 = new BlockPos(fk3.getX(), cq.getLevel().getHeightmapPos(Heightmap.Types.WORLD_SURFACE, fk3).getY(), fk3.getZ() + 3);
final ServerLevel xd5 = cq.getLevel();
say(cq, "Running " + collection.size() + " tests...");
final Collection<GameTestInfo> collection2 = GameTestRunner.runTests(collection, fk4, xd5, GameTestTicker.singleton);
final MultipleTestTracker jf7 = new MultipleTestTracker(collection2);
jf7.setListener(new TestSummaryDisplayer(xd5, jf7));
}
private static void say(final CommandSourceStack cq, final String string) {
cq.sendSuccess(new TextComponent(string), false);
}
private static int exportTestStructure(final CommandSourceStack cq, final String string) {
final Path path3 = Paths.get(StructureUtils.testStructuresDir);
final ResourceLocation sm4 = new ResourceLocation("minecraft", string);
final Path path4 = cq.getLevel().getStructureManager().createPathToStructure(sm4, ".nbt");
final Path path5 = NbtToSnbt.convertStructure(path4, string, path3);
if (path5 == null) {
say(cq, "Failed to export " + path4);
return 1;
}
try {
Files.createDirectories(path5.getParent(), new FileAttribute[0]);
}
catch (IOException iOException7) {
say(cq, "Could not create folder " + path5.getParent());
iOException7.printStackTrace();
return 1;
}
say(cq, "Exported to " + path5.toAbsolutePath());
return 0;
}
private static int importTestStructure(final CommandSourceStack cq, final String string) {
final Path path3 = Paths.get(StructureUtils.testStructuresDir, string + ".snbt");
final ResourceLocation sm4 = new ResourceLocation("minecraft", string);
final Path path4 = cq.getLevel().getStructureManager().createPathToStructure(sm4, ".nbt");
try {
final BufferedReader bufferedReader6 = Files.newBufferedReader(path3);
final String string2 = IOUtils.toString((Reader)bufferedReader6);
Files.createDirectories(path4.getParent(), new FileAttribute[0]);
final OutputStream outputStream8 = Files.newOutputStream(path4);
NbtIo.writeCompressed(TagParser.parseTag(string2), outputStream8);
say(cq, "Imported to " + path4.toAbsolutePath());
return 0;
}
catch (IOException | CommandSyntaxException ex2) {
final Exception ex;
final Exception exception6 = ex;
System.err.println("Failed to load structure " + string);
exception6.printStackTrace();
return 1;
}
}
private static void say(final ServerLevel xd, final String string, final ChatFormatting g) {
final TextComponent lf;
xd.getPlayers(xe -> true).forEach(xe -> {
new TextComponent(g + string);
xe.sendMessage(lf);
});
}
static class TestSummaryDisplayer implements GameTestListener {
private final ServerLevel level;
private final MultipleTestTracker tracker;
public TestSummaryDisplayer(final ServerLevel xd, final MultipleTestTracker jf) {
this.level = xd;
this.tracker = jf;
}
@Override
public void testStructureLoaded(final GameTestInfo iw) {
}
@Override
public void testFailed(final GameTestInfo iw) {
showTestSummaryIfAllDone(this.level, this.tracker);
}
}
}