TestCommand.java
net.minecraft.gametest.framework.TestCommand
信息
- 全限定名:net.minecraft.gametest.framework.TestCommand
- 类型:public class
- 包:net.minecraft.gametest.framework
- 源码路径:src/main/java/net/minecraft/gametest/framework/TestCommand.java
- 起始行号:L59
- 职责:
TODO
字段/常量
-
TEST_NEARBY_SEARCH_RADIUS- 类型:
int - 修饰符:
public static final - 源码定位:
L60 - 说明:
TODO
- 类型:
-
TEST_FULL_SEARCH_RADIUS- 类型:
int - 修饰符:
public static final - 源码定位:
L61 - 说明:
TODO
- 类型:
-
VERIFY_TEST_GRID_AXIS_SIZE- 类型:
int - 修饰符:
public static final - 源码定位:
L62 - 说明:
TODO
- 类型:
-
VERIFY_TEST_BATCH_SIZE- 类型:
int - 修饰符:
public static final - 源码定位:
L63 - 说明:
TODO
- 类型:
-
DEFAULT_CLEAR_RADIUS- 类型:
int - 修饰符:
private static final - 源码定位:
L64 - 说明:
TODO
- 类型:
-
MAX_CLEAR_RADIUS- 类型:
int - 修饰符:
private static final - 源码定位:
L65 - 说明:
TODO
- 类型:
-
TEST_POS_Z_OFFSET_FROM_PLAYER- 类型:
int - 修饰符:
private static final - 源码定位:
L66 - 说明:
TODO
- 类型:
-
DEFAULT_X_SIZE- 类型:
int - 修饰符:
private static final - 源码定位:
L67 - 说明:
TODO
- 类型:
-
DEFAULT_Y_SIZE- 类型:
int - 修饰符:
private static final - 源码定位:
L68 - 说明:
TODO
- 类型:
-
DEFAULT_Z_SIZE- 类型:
int - 修饰符:
private static final - 源码定位:
L69 - 说明:
TODO
- 类型:
-
CLEAR_NO_TESTS- 类型:
SimpleCommandExceptionType - 修饰符:
private static final - 源码定位:
L70 - 说明:
TODO
- 类型:
-
RESET_NO_TESTS- 类型:
SimpleCommandExceptionType - 修饰符:
private static final - 源码定位:
L73 - 说明:
TODO
- 类型:
-
TEST_INSTANCE_COULD_NOT_BE_FOUND- 类型:
SimpleCommandExceptionType - 修饰符:
private static final - 源码定位:
L76 - 说明:
TODO
- 类型:
-
NO_STRUCTURES_TO_EXPORT- 类型:
SimpleCommandExceptionType - 修饰符:
private static final - 源码定位:
L79 - 说明:
TODO
- 类型:
-
NO_TEST_INSTANCES- 类型:
SimpleCommandExceptionType - 修饰符:
private static final - 源码定位:
L82 - 说明:
TODO
- 类型:
-
NO_TEST_CONTAINING- 类型:
Dynamic3CommandExceptionType - 修饰符:
private static final - 源码定位:
L85 - 说明:
TODO
- 类型:
-
TOO_LARGE- 类型:
DynamicCommandExceptionType - 修饰符:
private static final - 源码定位:
L88 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.gametest.framework.TestCommand.TestBatchSummaryDisplayer- 类型:
record - 修饰符:
private - 源码定位:
L577 - 说明:
TODO
- 类型:
-
net.minecraft.gametest.framework.TestCommand.TestSummaryDisplayer- 类型:
record - 修饰符:
public - 源码定位:
L588 - 说明:
TODO
- 类型:
构造器
- 无
方法
下面的方法块按源码顺序生成。
private static int reset(TestFinder finder) @ L92
- 方法名:reset
- 源码定位:L92
- 返回类型:int
- 修饰符:private static
参数:
- finder: TestFinder
说明:
TODO
private static int clear(TestFinder finder) @ L103
- 方法名:clear
- 源码定位:L103
- 返回类型:int
- 修饰符:private static
参数:
- finder: TestFinder
说明:
TODO
private static int export(TestFinder finder) @ L125
- 方法名:export
- 源码定位:L125
- 返回类型:int
- 修饰符:private static
参数:
- finder: TestFinder
说明:
TODO
private static int verify(TestFinder finder) @ L151
- 方法名:verify
- 源码定位:L151
- 返回类型:int
- 修饰符:private static
参数:
- finder: TestFinder
说明:
TODO
private static int run(TestFinder finder, RetryOptions retryOptions, int extraRotationSteps, int testsPerRow) @ L189
- 方法名:run
- 源码定位:L189
- 返回类型:int
- 修饰符:private static
参数:
- finder: TestFinder
- retryOptions: RetryOptions
- extraRotationSteps: int
- testsPerRow: int
说明:
TODO
private static int locate(TestFinder finder) @ L211
- 方法名:locate
- 源码定位:L211
- 返回类型:int
- 修饰符:private static
参数:
- finder: TestFinder
说明:
TODO
private static ArgumentBuilder<CommandSourceStack,?> runWithRetryOptions(ArgumentBuilder<CommandSourceStack,?> runArgument, InCommandFunction<CommandContext<CommandSourceStack>,TestFinder> finder, Function<ArgumentBuilder<CommandSourceStack,?>,ArgumentBuilder<CommandSourceStack,?>> then) @ L250
- 方法名:runWithRetryOptions
- 源码定位:L250
- 返回类型:ArgumentBuilder<CommandSourceStack,?>
- 修饰符:private static
参数:
- runArgument: ArgumentBuilder<CommandSourceStack,?>
- finder: InCommandFunction<CommandContext
,TestFinder> - then: Function<ArgumentBuilder<CommandSourceStack,?>,ArgumentBuilder<CommandSourceStack,?>>
说明:
TODO
private static ArgumentBuilder<CommandSourceStack,?> runWithRetryOptions(ArgumentBuilder<CommandSourceStack,?> runArgument, InCommandFunction<CommandContext<CommandSourceStack>,TestFinder> finder) @ L275
- 方法名:runWithRetryOptions
- 源码定位:L275
- 返回类型:ArgumentBuilder<CommandSourceStack,?>
- 修饰符:private static
参数:
- runArgument: ArgumentBuilder<CommandSourceStack,?>
- finder: InCommandFunction<CommandContext
,TestFinder>
说明:
TODO
private static ArgumentBuilder<CommandSourceStack,?> runWithRetryOptionsAndBuildInfo(ArgumentBuilder<CommandSourceStack,?> runArgument, InCommandFunction<CommandContext<CommandSourceStack>,TestFinder> finder) @ L281
- 方法名:runWithRetryOptionsAndBuildInfo
- 源码定位:L281
- 返回类型:ArgumentBuilder<CommandSourceStack,?>
- 修饰符:private static
参数:
- runArgument: ArgumentBuilder<CommandSourceStack,?>
- finder: InCommandFunction<CommandContext
,TestFinder>
说明:
TODO
public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) @ L312
- 方法名:register
- 源码定位:L312
- 返回类型:void
- 修饰符:public static
参数:
- dispatcher: CommandDispatcher
- context: CommandBuildContext
说明:
TODO
public static CompletableFuture<Suggestions> suggestTestFunction(CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) @ L443
- 方法名:suggestTestFunction
- 源码定位:L443
- 返回类型:CompletableFuture
- 修饰符:public static
参数:
- context: CommandContext
- builder: SuggestionsBuilder
说明:
TODO
private static int resetGameTestInfo(CommandSourceStack source, GameTestInfo testInfo) @ L452
- 方法名:resetGameTestInfo
- 源码定位:L452
- 返回类型:int
- 修饰符:private static
参数:
- source: CommandSourceStack
- testInfo: GameTestInfo
说明:
TODO
private static Stream<GameTestInfo> toGameTestInfos(CommandSourceStack source, RetryOptions retryOptions, TestPosFinder finder) @ L458
- 方法名:toGameTestInfos
- 源码定位:L458
- 返回类型:Stream
- 修饰符:private static
参数:
- source: CommandSourceStack
- retryOptions: RetryOptions
- finder: TestPosFinder
说明:
TODO
private static Stream<GameTestInfo> toGameTestInfo(CommandSourceStack source, RetryOptions retryOptions, TestInstanceFinder finder, int rotationSteps) @ L462
- 方法名:toGameTestInfo
- 源码定位:L462
- 返回类型:Stream
- 修饰符:private static
参数:
- source: CommandSourceStack
- retryOptions: RetryOptions
- finder: TestInstanceFinder
- rotationSteps: int
说明:
TODO
private static Optional<GameTestInfo> createGameTestInfo(BlockPos testBlockPos, CommandSourceStack source, RetryOptions retryOptions) @ L472
- 方法名:createGameTestInfo
- 源码定位:L472
- 返回类型:Optional
- 修饰符:private static
参数:
- testBlockPos: BlockPos
- source: CommandSourceStack
- retryOptions: RetryOptions
说明:
TODO
private static int createNewStructure(CommandSourceStack source, Identifier id, int xSize, int ySize, int zSize) @ L494
- 方法名:createNewStructure
- 源码定位:L494
- 返回类型:int
- 修饰符:private static
参数:
- source: CommandSourceStack
- id: Identifier
- xSize: int
- ySize: int
- zSize: int
说明:
TODO
private static int showPos(CommandSourceStack source, String varName) @ L509
- 方法名:showPos
- 源码定位:L509
- 返回类型:int
- 修饰符:private static
参数:
- source: CommandSourceStack
- varName: String
说明:
TODO
private static int stopTests() @ L544
- 方法名:stopTests
- 源码定位:L544
- 返回类型:int
- 修饰符:private static
参数:
- 无
说明:
TODO
public static int trackAndStartRunner(CommandSourceStack source, GameTestRunner runner) @ L549
- 方法名:trackAndStartRunner
- 源码定位:L549
- 返回类型:int
- 修饰符:public static
参数:
- source: CommandSourceStack
- runner: GameTestRunner
说明:
TODO
private static int exportTestStructure(CommandSourceStack source, Holder<GameTestInstance> test) @ L558
- 方法名:exportTestStructure
- 源码定位:L558
- 返回类型:int
- 修饰符:private static
参数:
- source: CommandSourceStack
- test: Holder
说明:
TODO
private static boolean verifyStructureExists(CommandSourceStack source, Identifier structure) @ L562
- 方法名:verifyStructureExists
- 源码定位:L562
- 返回类型:boolean
- 修饰符:private static
参数:
- source: CommandSourceStack
- structure: Identifier
说明:
TODO
private static BlockPos createTestPositionAround(CommandSourceStack source) @ L571
- 方法名:createTestPositionAround
- 源码定位:L571
- 返回类型:BlockPos
- 修饰符:private static
参数:
- source: CommandSourceStack
说明:
TODO
代码
public class TestCommand {
public static final int TEST_NEARBY_SEARCH_RADIUS = 15;
public static final int TEST_FULL_SEARCH_RADIUS = 250;
public static final int VERIFY_TEST_GRID_AXIS_SIZE = 10;
public static final int VERIFY_TEST_BATCH_SIZE = 100;
private static final int DEFAULT_CLEAR_RADIUS = 250;
private static final int MAX_CLEAR_RADIUS = 1024;
private static final int TEST_POS_Z_OFFSET_FROM_PLAYER = 3;
private static final int DEFAULT_X_SIZE = 5;
private static final int DEFAULT_Y_SIZE = 5;
private static final int DEFAULT_Z_SIZE = 5;
private static final SimpleCommandExceptionType CLEAR_NO_TESTS = new SimpleCommandExceptionType(
Component.translatable("commands.test.clear.error.no_tests")
);
private static final SimpleCommandExceptionType RESET_NO_TESTS = new SimpleCommandExceptionType(
Component.translatable("commands.test.reset.error.no_tests")
);
private static final SimpleCommandExceptionType TEST_INSTANCE_COULD_NOT_BE_FOUND = new SimpleCommandExceptionType(
Component.translatable("commands.test.error.test_instance_not_found")
);
private static final SimpleCommandExceptionType NO_STRUCTURES_TO_EXPORT = new SimpleCommandExceptionType(
Component.literal("Could not find any structures to export")
);
private static final SimpleCommandExceptionType NO_TEST_INSTANCES = new SimpleCommandExceptionType(
Component.translatable("commands.test.error.no_test_instances")
);
private static final Dynamic3CommandExceptionType NO_TEST_CONTAINING = new Dynamic3CommandExceptionType(
(x, y, z) -> Component.translatableEscape("commands.test.error.no_test_containing_pos", x, y, z)
);
private static final DynamicCommandExceptionType TOO_LARGE = new DynamicCommandExceptionType(
size -> Component.translatableEscape("commands.test.error.too_large", size)
);
private static int reset(TestFinder finder) throws CommandSyntaxException {
stopTests();
int count = toGameTestInfos(finder.source(), RetryOptions.noRetries(), finder).map(info -> resetGameTestInfo(finder.source(), info)).toList().size();
if (count == 0) {
throw CLEAR_NO_TESTS.create();
} else {
finder.source().sendSuccess(() -> Component.translatable("commands.test.reset.success", count), true);
return count;
}
}
private static int clear(TestFinder finder) throws CommandSyntaxException {
stopTests();
CommandSourceStack source = finder.source();
ServerLevel level = source.getLevel();
List<TestInstanceBlockEntity> tests = finder.findTestPos()
.flatMap(pos -> level.getBlockEntity(pos, BlockEntityType.TEST_INSTANCE_BLOCK).stream())
.toList();
for (TestInstanceBlockEntity testInstanceBlockEntity : tests) {
StructureUtils.clearSpaceForStructure(testInstanceBlockEntity.getTestBoundingBox(), level);
testInstanceBlockEntity.removeBarriers();
level.destroyBlock(testInstanceBlockEntity.getBlockPos(), false);
}
if (tests.isEmpty()) {
throw CLEAR_NO_TESTS.create();
} else {
source.sendSuccess(() -> Component.translatable("commands.test.clear.success", tests.size()), true);
return tests.size();
}
}
private static int export(TestFinder finder) throws CommandSyntaxException {
CommandSourceStack source = finder.source();
ServerLevel level = source.getLevel();
int count = 0;
boolean allGood = true;
for (Iterator<BlockPos> iterator = finder.findTestPos().iterator(); iterator.hasNext(); count++) {
BlockPos pos = iterator.next();
if (!(level.getBlockEntity(pos) instanceof TestInstanceBlockEntity blockEntity)) {
throw TEST_INSTANCE_COULD_NOT_BE_FOUND.create();
}
if (!blockEntity.exportTest(source::sendSystemMessage)) {
allGood = false;
}
}
if (count == 0) {
throw NO_STRUCTURES_TO_EXPORT.create();
} else {
String message = "Exported " + count + " structures";
finder.source().sendSuccess(() -> Component.literal(message), true);
return allGood ? 0 : 1;
}
}
private static int verify(TestFinder finder) {
stopTests();
CommandSourceStack source = finder.source();
ServerLevel level = source.getLevel();
BlockPos testPos = createTestPositionAround(source);
Collection<GameTestInfo> infos = Stream.concat(
toGameTestInfos(source, RetryOptions.noRetries(), finder), toGameTestInfo(source, RetryOptions.noRetries(), finder, 0)
)
.toList();
FailedTestTracker.forgetFailedTests();
Collection<GameTestBatch> batches = new ArrayList<>();
for (GameTestInfo info : infos) {
for (Rotation rotation : Rotation.values()) {
Collection<GameTestInfo> transformedInfos = new ArrayList<>();
for (int i = 0; i < 100; i++) {
GameTestInfo copyInfo = new GameTestInfo(info.getTestHolder(), rotation, level, new RetryOptions(1, true));
copyInfo.setTestBlockPos(info.getTestBlockPos());
transformedInfos.add(copyInfo);
}
GameTestBatch batch = GameTestBatchFactory.toGameTestBatch(transformedInfos, info.getTest().batch(), rotation.ordinal());
batches.add(batch);
}
}
StructureGridSpawner spawner = new StructureGridSpawner(testPos, 10, true);
GameTestRunner runner = GameTestRunner.Builder.fromBatches(batches, level)
.batcher(GameTestBatchFactory.fromGameTestInfo(100))
.newStructureSpawner(spawner)
.existingStructureSpawner(spawner)
.haltOnError()
.clearBetweenBatches()
.build();
return trackAndStartRunner(source, runner);
}
private static int run(TestFinder finder, RetryOptions retryOptions, int extraRotationSteps, int testsPerRow) {
stopTests();
CommandSourceStack source = finder.source();
ServerLevel level = source.getLevel();
BlockPos testPos = createTestPositionAround(source);
Collection<GameTestInfo> infos = Stream.concat(
toGameTestInfos(source, retryOptions, finder), toGameTestInfo(source, retryOptions, finder, extraRotationSteps)
)
.toList();
if (infos.isEmpty()) {
source.sendSuccess(() -> Component.translatable("commands.test.no_tests"), false);
return 0;
} else {
FailedTestTracker.forgetFailedTests();
source.sendSuccess(() -> Component.translatable("commands.test.run.running", infos.size()), false);
GameTestRunner runner = GameTestRunner.Builder.fromInfo(infos, level)
.newStructureSpawner(new StructureGridSpawner(testPos, testsPerRow, false))
.build();
return trackAndStartRunner(source, runner);
}
}
private static int locate(TestFinder finder) throws CommandSyntaxException {
finder.source().sendSystemMessage(Component.translatable("commands.test.locate.started"));
MutableInt structuresFound = new MutableInt(0);
BlockPos sourcePos = BlockPos.containing(finder.source().getPosition());
finder.findTestPos()
.forEach(
structurePos -> {
if (finder.source().getLevel().getBlockEntity(structurePos) instanceof TestInstanceBlockEntity testBlock) {
Direction var13 = testBlock.getRotation().rotate(Direction.NORTH);
BlockPos telportPosition = testBlock.getBlockPos().relative(var13, 2);
int teleportYRot = (int)var13.getOpposite().toYRot();
String tpCommand = String.format(
Locale.ROOT, "/tp @s %d %d %d %d 0", telportPosition.getX(), telportPosition.getY(), telportPosition.getZ(), teleportYRot
);
int dx = sourcePos.getX() - structurePos.getX();
int dz = sourcePos.getZ() - structurePos.getZ();
int distance = Mth.floor(Mth.sqrt(dx * dx + dz * dz));
MutableComponent coordinates = ComponentUtils.wrapInSquareBrackets(
Component.translatable("chat.coordinates", structurePos.getX(), structurePos.getY(), structurePos.getZ())
)
.withStyle(
s -> s.withColor(ChatFormatting.GREEN)
.withClickEvent(new ClickEvent.SuggestCommand(tpCommand))
.withHoverEvent(new HoverEvent.ShowText(Component.translatable("chat.coordinates.tooltip")))
);
finder.source().sendSuccess(() -> Component.translatable("commands.test.locate.found", coordinates, distance), false);
structuresFound.increment();
}
}
);
int structures = structuresFound.intValue();
if (structures == 0) {
throw NO_TEST_INSTANCES.create();
} else {
finder.source().sendSuccess(() -> Component.translatable("commands.test.locate.done", structures), true);
return structures;
}
}
private static ArgumentBuilder<CommandSourceStack, ?> runWithRetryOptions(
ArgumentBuilder<CommandSourceStack, ?> runArgument,
InCommandFunction<CommandContext<CommandSourceStack>, TestFinder> finder,
Function<ArgumentBuilder<CommandSourceStack, ?>, ArgumentBuilder<CommandSourceStack, ?>> then
) {
return runArgument.executes(c -> run(finder.apply(c), RetryOptions.noRetries(), 0, 8))
.then(
Commands.argument("numberOfTimes", IntegerArgumentType.integer(0))
.executes(c -> run(finder.apply(c), new RetryOptions(IntegerArgumentType.getInteger(c, "numberOfTimes"), false), 0, 8))
.then(
then.apply(
Commands.argument("untilFailed", BoolArgumentType.bool())
.executes(
c -> run(
finder.apply(c),
new RetryOptions(IntegerArgumentType.getInteger(c, "numberOfTimes"), BoolArgumentType.getBool(c, "untilFailed")),
0,
8
)
)
)
)
);
}
private static ArgumentBuilder<CommandSourceStack, ?> runWithRetryOptions(
ArgumentBuilder<CommandSourceStack, ?> runArgument, InCommandFunction<CommandContext<CommandSourceStack>, TestFinder> finder
) {
return runWithRetryOptions(runArgument, finder, a -> a);
}
private static ArgumentBuilder<CommandSourceStack, ?> runWithRetryOptionsAndBuildInfo(
ArgumentBuilder<CommandSourceStack, ?> runArgument, InCommandFunction<CommandContext<CommandSourceStack>, TestFinder> finder
) {
return runWithRetryOptions(
runArgument,
finder,
then -> then.then(
Commands.argument("rotationSteps", IntegerArgumentType.integer())
.executes(
c -> run(
finder.apply(c),
new RetryOptions(IntegerArgumentType.getInteger(c, "numberOfTimes"), BoolArgumentType.getBool(c, "untilFailed")),
IntegerArgumentType.getInteger(c, "rotationSteps"),
8
)
)
.then(
Commands.argument("testsPerRow", IntegerArgumentType.integer())
.executes(
c -> run(
finder.apply(c),
new RetryOptions(IntegerArgumentType.getInteger(c, "numberOfTimes"), BoolArgumentType.getBool(c, "untilFailed")),
IntegerArgumentType.getInteger(c, "rotationSteps"),
IntegerArgumentType.getInteger(c, "testsPerRow")
)
)
)
)
);
}
public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) {
ArgumentBuilder<CommandSourceStack, ?> runFailedWithRequiredTestsFlag = runWithRetryOptionsAndBuildInfo(
Commands.argument("onlyRequiredTests", BoolArgumentType.bool()),
c -> TestFinder.builder().failedTests(c, BoolArgumentType.getBool(c, "onlyRequiredTests"))
);
LiteralArgumentBuilder<CommandSourceStack> testCommand = Commands.literal("test")
.requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
.then(
Commands.literal("run")
.then(
runWithRetryOptionsAndBuildInfo(
Commands.argument("tests", ResourceSelectorArgument.resourceSelector(context, Registries.TEST_INSTANCE)),
c -> TestFinder.builder().byResourceSelection(c, ResourceSelectorArgument.getSelectedResources(c, "tests"))
)
)
)
.then(
Commands.literal("runmultiple")
.then(
Commands.argument("tests", ResourceSelectorArgument.resourceSelector(context, Registries.TEST_INSTANCE))
.executes(
c -> run(
TestFinder.builder().byResourceSelection(c, ResourceSelectorArgument.getSelectedResources(c, "tests")),
RetryOptions.noRetries(),
0,
8
)
)
.then(
Commands.argument("amount", IntegerArgumentType.integer())
.executes(
c -> run(
TestFinder.builder()
.createMultipleCopies(IntegerArgumentType.getInteger(c, "amount"))
.byResourceSelection(c, ResourceSelectorArgument.getSelectedResources(c, "tests")),
RetryOptions.noRetries(),
0,
8
)
)
)
)
)
.then(runWithRetryOptions(Commands.literal("runthese"), TestFinder.builder()::allNearby))
.then(runWithRetryOptions(Commands.literal("runclosest"), TestFinder.builder()::nearest))
.then(runWithRetryOptions(Commands.literal("runthat"), TestFinder.builder()::lookedAt))
.then(runWithRetryOptionsAndBuildInfo(Commands.literal("runfailed").then(runFailedWithRequiredTestsFlag), TestFinder.builder()::failedTests))
.then(
Commands.literal("verify")
.then(
Commands.argument("tests", ResourceSelectorArgument.resourceSelector(context, Registries.TEST_INSTANCE))
.executes(c -> verify(TestFinder.builder().byResourceSelection(c, ResourceSelectorArgument.getSelectedResources(c, "tests"))))
)
)
.then(
Commands.literal("locate")
.then(
Commands.argument("tests", ResourceSelectorArgument.resourceSelector(context, Registries.TEST_INSTANCE))
.executes(c -> locate(TestFinder.builder().byResourceSelection(c, ResourceSelectorArgument.getSelectedResources(c, "tests"))))
)
)
.then(Commands.literal("resetclosest").executes(c -> reset(TestFinder.builder().nearest(c))))
.then(Commands.literal("resetthese").executes(c -> reset(TestFinder.builder().allNearby(c))))
.then(Commands.literal("resetthat").executes(c -> reset(TestFinder.builder().lookedAt(c))))
.then(Commands.literal("clearthat").executes(c -> clear(TestFinder.builder().lookedAt(c))))
.then(Commands.literal("clearthese").executes(c -> clear(TestFinder.builder().allNearby(c))))
.then(
Commands.literal("clearall")
.executes(c -> clear(TestFinder.builder().radius(c, 250)))
.then(
Commands.argument("radius", IntegerArgumentType.integer())
.executes(c -> clear(TestFinder.builder().radius(c, Mth.clamp(IntegerArgumentType.getInteger(c, "radius"), 0, 1024))))
)
)
.then(Commands.literal("stop").executes(c -> stopTests()))
.then(
Commands.literal("pos")
.executes(c -> showPos(c.getSource(), "pos"))
.then(Commands.argument("var", StringArgumentType.word()).executes(c -> showPos(c.getSource(), StringArgumentType.getString(c, "var"))))
)
.then(
Commands.literal("create")
.then(
Commands.argument("id", IdentifierArgument.id())
.suggests(TestCommand::suggestTestFunction)
.executes(c -> createNewStructure(c.getSource(), IdentifierArgument.getId(c, "id"), 5, 5, 5))
.then(
Commands.argument("width", IntegerArgumentType.integer())
.executes(
c -> createNewStructure(
c.getSource(),
IdentifierArgument.getId(c, "id"),
IntegerArgumentType.getInteger(c, "width"),
IntegerArgumentType.getInteger(c, "width"),
IntegerArgumentType.getInteger(c, "width")
)
)
.then(
Commands.argument("height", IntegerArgumentType.integer())
.then(
Commands.argument("depth", IntegerArgumentType.integer())
.executes(
c -> createNewStructure(
c.getSource(),
IdentifierArgument.getId(c, "id"),
IntegerArgumentType.getInteger(c, "width"),
IntegerArgumentType.getInteger(c, "height"),
IntegerArgumentType.getInteger(c, "depth")
)
)
)
)
)
)
);
if (SharedConstants.IS_RUNNING_IN_IDE) {
testCommand = testCommand.then(
Commands.literal("export")
.then(
Commands.argument("test", ResourceArgument.resource(context, Registries.TEST_INSTANCE))
.executes(c -> exportTestStructure(c.getSource(), ResourceArgument.getResource(c, "test", Registries.TEST_INSTANCE)))
)
)
.then(Commands.literal("exportclosest").executes(c -> export(TestFinder.builder().nearest(c))))
.then(Commands.literal("exportthese").executes(c -> export(TestFinder.builder().allNearby(c))))
.then(Commands.literal("exportthat").executes(c -> export(TestFinder.builder().lookedAt(c))));
}
dispatcher.register(testCommand);
}
public static CompletableFuture<Suggestions> suggestTestFunction(CommandContext<CommandSourceStack> context, SuggestionsBuilder builder) {
Stream<String> testNamesStream = context.getSource()
.registryAccess()
.lookupOrThrow(Registries.TEST_FUNCTION)
.listElements()
.map(Holder::getRegisteredName);
return SharedSuggestionProvider.suggest(testNamesStream, builder);
}
private static int resetGameTestInfo(CommandSourceStack source, GameTestInfo testInfo) {
TestInstanceBlockEntity blockEntity = testInfo.getTestInstanceBlockEntity();
blockEntity.resetTest(source::sendSystemMessage);
return 1;
}
private static Stream<GameTestInfo> toGameTestInfos(CommandSourceStack source, RetryOptions retryOptions, TestPosFinder finder) {
return finder.findTestPos().map(pos -> createGameTestInfo(pos, source, retryOptions)).flatMap(Optional::stream);
}
private static Stream<GameTestInfo> toGameTestInfo(CommandSourceStack source, RetryOptions retryOptions, TestInstanceFinder finder, int rotationSteps) {
return finder.findTests()
.filter(test -> verifyStructureExists(source, test.value().structure()))
.map(
test -> new GameTestInfo(
(Holder.Reference<GameTestInstance>)test, StructureUtils.getRotationForRotationSteps(rotationSteps), source.getLevel(), retryOptions
)
);
}
private static Optional<GameTestInfo> createGameTestInfo(BlockPos testBlockPos, CommandSourceStack source, RetryOptions retryOptions) {
ServerLevel level = source.getLevel();
if (level.getBlockEntity(testBlockPos) instanceof TestInstanceBlockEntity blockEntity) {
Optional<Holder.Reference<GameTestInstance>> maybeTest = blockEntity.test()
.flatMap(source.registryAccess().lookupOrThrow(Registries.TEST_INSTANCE)::get);
if (maybeTest.isEmpty()) {
source.sendFailure(Component.translatable("commands.test.error.non_existant_test", blockEntity.getTestName()));
return Optional.empty();
} else {
Holder.Reference<GameTestInstance> test = maybeTest.get();
GameTestInfo testInfo = new GameTestInfo(test, blockEntity.getRotation(), level, retryOptions);
testInfo.setTestBlockPos(testBlockPos);
return !verifyStructureExists(source, testInfo.getStructure()) ? Optional.empty() : Optional.of(testInfo);
}
} else {
source.sendFailure(
Component.translatable("commands.test.error.test_instance_not_found.position", testBlockPos.getX(), testBlockPos.getY(), testBlockPos.getZ())
);
return Optional.empty();
}
}
private static int createNewStructure(CommandSourceStack source, Identifier id, int xSize, int ySize, int zSize) throws CommandSyntaxException {
if (xSize <= 48 && ySize <= 48 && zSize <= 48) {
ServerLevel level = source.getLevel();
BlockPos testPos = createTestPositionAround(source);
TestInstanceBlockEntity test = StructureUtils.createNewEmptyTest(id, testPos, new Vec3i(xSize, ySize, zSize), Rotation.NONE, level);
BlockPos low = test.getStructurePos();
BlockPos high = low.offset(xSize - 1, 0, zSize - 1);
BlockPos.betweenClosedStream(low, high).forEach(blockPos -> level.setBlockAndUpdate(blockPos, Blocks.BEDROCK.defaultBlockState()));
source.sendSuccess(() -> Component.translatable("commands.test.create.success", test.getTestName()), true);
return 1;
} else {
throw TOO_LARGE.create(48);
}
}
private static int showPos(CommandSourceStack source, String varName) throws CommandSyntaxException {
ServerPlayer player = source.getPlayerOrException();
BlockHitResult pick = (BlockHitResult)player.pick(10.0, 1.0F, false);
BlockPos targetPosAbsolute = pick.getBlockPos();
ServerLevel level = source.getLevel();
Optional<BlockPos> testBlockPos = StructureUtils.findTestContainingPos(targetPosAbsolute, 15, level);
if (testBlockPos.isEmpty()) {
testBlockPos = StructureUtils.findTestContainingPos(targetPosAbsolute, 250, level);
}
if (testBlockPos.isEmpty()) {
throw NO_TEST_CONTAINING.create(targetPosAbsolute.getX(), targetPosAbsolute.getY(), targetPosAbsolute.getZ());
} else if (level.getBlockEntity(testBlockPos.get()) instanceof TestInstanceBlockEntity testBlockEntity) {
BlockPos var13 = testBlockEntity.getStructurePos();
BlockPos targetPosRelative = targetPosAbsolute.subtract(var13);
String targetPosDescription = targetPosRelative.getX() + ", " + targetPosRelative.getY() + ", " + targetPosRelative.getZ();
String testName = testBlockEntity.getTestName().getString();
MutableComponent coords = Component.translatable(
"commands.test.coordinates", targetPosRelative.getX(), targetPosRelative.getY(), targetPosRelative.getZ()
)
.setStyle(
Style.EMPTY
.withBold(true)
.withColor(ChatFormatting.GREEN)
.withHoverEvent(new HoverEvent.ShowText(Component.translatable("commands.test.coordinates.copy")))
.withClickEvent(new ClickEvent.CopyToClipboard("final BlockPos " + varName + " = new BlockPos(" + targetPosDescription + ");"))
);
source.sendSuccess(() -> Component.translatable("commands.test.relative_position", testName, coords), false);
player.connection.send(new ClientboundGameTestHighlightPosPacket(targetPosAbsolute, targetPosRelative));
return 1;
} else {
throw TEST_INSTANCE_COULD_NOT_BE_FOUND.create();
}
}
private static int stopTests() {
GameTestTicker.SINGLETON.clear();
return 1;
}
public static int trackAndStartRunner(CommandSourceStack source, GameTestRunner runner) {
runner.addListener(new TestCommand.TestBatchSummaryDisplayer(source));
MultipleTestTracker tracker = new MultipleTestTracker(runner.getTestInfos());
tracker.addListener(new TestCommand.TestSummaryDisplayer(source, tracker));
tracker.addFailureListener(testInfo -> FailedTestTracker.rememberFailedTest(testInfo.getTestHolder()));
runner.start();
return 1;
}
private static int exportTestStructure(CommandSourceStack source, Holder<GameTestInstance> test) {
return !TestInstanceBlockEntity.export(source.getLevel(), test.value().structure(), source::sendSystemMessage) ? 0 : 1;
}
private static boolean verifyStructureExists(CommandSourceStack source, Identifier structure) {
if (source.getLevel().getStructureManager().get(structure).isEmpty()) {
source.sendFailure(Component.translatable("commands.test.error.structure_not_found", Component.translationArg(structure)));
return false;
} else {
return true;
}
}
private static BlockPos createTestPositionAround(CommandSourceStack source) {
BlockPos playerPos = BlockPos.containing(source.getPosition());
int surfaceY = source.getLevel().getHeightmapPos(Heightmap.Types.WORLD_SURFACE, playerPos).getY();
return new BlockPos(playerPos.getX(), surfaceY, playerPos.getZ() + 3);
}
private record TestBatchSummaryDisplayer(CommandSourceStack source) implements GameTestBatchListener {
@Override
public void testBatchStarting(GameTestBatch batch) {
this.source.sendSuccess(() -> Component.translatable("commands.test.batch.starting", batch.environment().getRegisteredName(), batch.index()), true);
}
@Override
public void testBatchFinished(GameTestBatch batch) {
}
}
public record TestSummaryDisplayer(CommandSourceStack source, MultipleTestTracker tracker) implements GameTestListener {
@Override
public void testStructureLoaded(GameTestInfo testInfo) {
}
@Override
public void testPassed(GameTestInfo testInfo, GameTestRunner runner) {
this.showTestSummaryIfAllDone();
}
@Override
public void testFailed(GameTestInfo testInfo, GameTestRunner runner) {
this.showTestSummaryIfAllDone();
}
@Override
public void testAddedForRerun(GameTestInfo original, GameTestInfo copy, GameTestRunner runner) {
this.tracker.addTestToTrack(copy);
}
private void showTestSummaryIfAllDone() {
if (this.tracker.isDone()) {
this.source
.sendSuccess(() -> Component.translatable("commands.test.summary", this.tracker.getTotalCount()).withStyle(ChatFormatting.WHITE), true);
if (this.tracker.hasFailedRequired()) {
this.source.sendFailure(Component.translatable("commands.test.summary.failed", this.tracker.getFailedRequiredCount()));
} else {
this.source.sendSuccess(() -> Component.translatable("commands.test.summary.all_required_passed").withStyle(ChatFormatting.GREEN), true);
}
if (this.tracker.hasFailedOptional()) {
this.source.sendSystemMessage(Component.translatable("commands.test.summary.optional_failed", this.tracker.getFailedOptionalCount()));
}
}
}
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/返回值
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Commands.argument(), Commands.hasPermission(), Commands.literal()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
SharedSuggestionProvider.suggest()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
IdentifierArgument.getId(), IdentifierArgument.id()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ResourceArgument.getResource(), ResourceArgument.resource()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ResourceSelectorArgument.getSelectedResources(), ResourceSelectorArgument.resourceSelector()
- 引用位置:
-
- 引用位置:
参数/方法调用/构造调用/返回值 - 关联成员:
BlockPos(), BlockPos.betweenClosedStream(), BlockPos.containing()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
Vec3i()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
FailedTestTracker.forgetFailedTests(), FailedTestTracker.rememberFailedTest()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
GameTestBatchFactory.fromGameTestInfo(), GameTestBatchFactory.toGameTestBatch()
- 引用位置:
-
- 引用位置:
参数/构造调用/返回值 - 关联成员:
GameTestInfo()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/方法调用 - 关联成员:
GameTestRunner.Builder.fromBatches(), GameTestRunner.Builder.fromInfo()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
MultipleTestTracker()
- 引用位置:
-
- 引用位置:
参数/方法调用/构造调用 - 关联成员:
RetryOptions(), RetryOptions.noRetries()
- 引用位置:
-
- 引用位置:
构造调用 - 关联成员:
StructureGridSpawner()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
StructureUtils.clearSpaceForStructure(), StructureUtils.createNewEmptyTest(), StructureUtils.findTestContainingPos(), StructureUtils.getRotationForRotationSteps()
- 引用位置:
-
- 引用位置:
参数/方法调用 - 关联成员:
TestFinder.builder()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用/构造调用 - 关联成员:
ClickEvent.CopyToClipboard(), ClickEvent.SuggestCommand(), CopyToClipboard(), SuggestCommand()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Component.literal(), Component.translatable(), Component.translatableEscape(), Component.translationArg()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
ComponentUtils.wrapInSquareBrackets()
- 引用位置:
-
- 引用位置:
方法调用/构造调用 - 关联成员:
HoverEvent.ShowText(), ShowText()
- 引用位置:
-
ClientboundGameTestHighlightPosPacket
- 引用位置:
构造调用 - 关联成员:
ClientboundGameTestHighlightPosPacket()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Mth.clamp(), Mth.floor(), Mth.sqrt()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Rotation.values()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
TestInstanceBlockEntity.export()
- 引用位置: