FillCommand.java
net.minecraft.server.commands.FillCommand
信息
- 全限定名:net.minecraft.server.commands.FillCommand
- 类型:public class
- 包:net.minecraft.server.commands
- 源码路径:src/main/java/net/minecraft/server/commands/FillCommand.java
- 起始行号:L30
- 职责:
TODO
字段/常量
-
ERROR_AREA_TOO_LARGE- 类型:
Dynamic2CommandExceptionType - 修饰符:
private static final - 源码定位:
L31 - 说明:
TODO
- 类型:
-
HOLLOW_CORE- 类型:
BlockInput - 修饰符:
private static final - 源码定位:
L34 - 说明:
TODO
- 类型:
-
ERROR_FAILED- 类型:
SimpleCommandExceptionType - 修饰符:
private static final - 源码定位:
L35 - 说明:
TODO
- 类型:
内部类/嵌套类型
-
net.minecraft.server.commands.FillCommand.UpdatedPosition- 类型:
record - 修饰符:
package-private - 源码定位:
L165 - 说明:
TODO
- 类型:
-
net.minecraft.server.commands.FillCommand.Affector- 类型:
interface - 修饰符:
public - 源码定位:
L218 - 说明:
TODO
- 类型:
-
net.minecraft.server.commands.FillCommand.Filter- 类型:
interface - 修饰符:
public - 源码定位:
L225 - 说明:
TODO
- 类型:
-
net.minecraft.server.commands.FillCommand.Mode- 类型:
enum - 修饰符:
private static - 源码定位:
L231 - 说明:
TODO
- 类型:
-
net.minecraft.server.commands.FillCommand.NullableCommandFunction- 类型:
interface - 修饰符:
private - 源码定位:
L267 - 说明:
TODO
- 类型:
构造器
- 无
方法
下面的方法块按源码顺序生成。
public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) @ L37
- 方法名:register
- 源码定位:L37
- 返回类型:void
- 修饰符:public static
参数:
- dispatcher: CommandDispatcher
- context: CommandBuildContext
说明:
TODO
private static ArgumentBuilder<CommandSourceStack,?> wrapWithMode(CommandBuildContext context, ArgumentBuilder<CommandSourceStack,?> builder, InCommandFunction<CommandContext<CommandSourceStack>,BlockPos> from, InCommandFunction<CommandContext<CommandSourceStack>,BlockPos> to, InCommandFunction<CommandContext<CommandSourceStack>,BlockInput> block, FillCommand.NullableCommandFunction<CommandContext<CommandSourceStack>,Predicate<BlockInWorld>> filter) @ L100
- 方法名:wrapWithMode
- 源码定位:L100
- 返回类型:ArgumentBuilder<CommandSourceStack,?>
- 修饰符:private static
参数:
- context: CommandBuildContext
- builder: ArgumentBuilder<CommandSourceStack,?>
- from: InCommandFunction<CommandContext
,BlockPos> - to: InCommandFunction<CommandContext
,BlockPos> - block: InCommandFunction<CommandContext
,BlockInput> - filter: FillCommand.NullableCommandFunction<CommandContext
,Predicate >
说明:
TODO
private static int fillBlocks(CommandSourceStack source, BoundingBox region, BlockInput target, FillCommand.Mode mode, Predicate<BlockInWorld> predicate, boolean strict) @ L157
- 方法名:fillBlocks
- 源码定位:L157
- 返回类型:int
- 修饰符:private static
参数:
- source: CommandSourceStack
- region: BoundingBox
- target: BlockInput
- mode: FillCommand.Mode
- predicate: Predicate
- strict: boolean
说明:
TODO
代码
public class FillCommand {
private static final Dynamic2CommandExceptionType ERROR_AREA_TOO_LARGE = new Dynamic2CommandExceptionType(
(max, count) -> Component.translatableEscape("commands.fill.toobig", max, count)
);
private static final BlockInput HOLLOW_CORE = new BlockInput(Blocks.AIR.defaultBlockState(), Collections.emptySet(), null);
private static final SimpleCommandExceptionType ERROR_FAILED = new SimpleCommandExceptionType(Component.translatable("commands.fill.failed"));
public static void register(CommandDispatcher<CommandSourceStack> dispatcher, CommandBuildContext context) {
dispatcher.register(
Commands.literal("fill")
.requires(Commands.hasPermission(Commands.LEVEL_GAMEMASTERS))
.then(
Commands.argument("from", BlockPosArgument.blockPos())
.then(
Commands.argument("to", BlockPosArgument.blockPos())
.then(
wrapWithMode(
context,
Commands.argument("block", BlockStateArgument.block(context)),
c -> BlockPosArgument.getLoadedBlockPos(c, "from"),
c -> BlockPosArgument.getLoadedBlockPos(c, "to"),
c -> BlockStateArgument.getBlock(c, "block"),
c -> null
)
.then(
Commands.literal("replace")
.executes(
c -> fillBlocks(
c.getSource(),
BoundingBox.fromCorners(
BlockPosArgument.getLoadedBlockPos(c, "from"), BlockPosArgument.getLoadedBlockPos(c, "to")
),
BlockStateArgument.getBlock(c, "block"),
FillCommand.Mode.REPLACE,
null,
false
)
)
.then(
wrapWithMode(
context,
Commands.argument("filter", BlockPredicateArgument.blockPredicate(context)),
c -> BlockPosArgument.getLoadedBlockPos(c, "from"),
c -> BlockPosArgument.getLoadedBlockPos(c, "to"),
c -> BlockStateArgument.getBlock(c, "block"),
c -> BlockPredicateArgument.getBlockPredicate(c, "filter")
)
)
)
.then(
Commands.literal("keep")
.executes(
c -> fillBlocks(
c.getSource(),
BoundingBox.fromCorners(
BlockPosArgument.getLoadedBlockPos(c, "from"), BlockPosArgument.getLoadedBlockPos(c, "to")
),
BlockStateArgument.getBlock(c, "block"),
FillCommand.Mode.REPLACE,
b -> b.getLevel().isEmptyBlock(b.getPos()),
false
)
)
)
)
)
)
);
}
private static ArgumentBuilder<CommandSourceStack, ?> wrapWithMode(
CommandBuildContext context,
ArgumentBuilder<CommandSourceStack, ?> builder,
InCommandFunction<CommandContext<CommandSourceStack>, BlockPos> from,
InCommandFunction<CommandContext<CommandSourceStack>, BlockPos> to,
InCommandFunction<CommandContext<CommandSourceStack>, BlockInput> block,
FillCommand.NullableCommandFunction<CommandContext<CommandSourceStack>, Predicate<BlockInWorld>> filter
) {
return builder.executes(
c -> fillBlocks(
c.getSource(), BoundingBox.fromCorners(from.apply(c), to.apply(c)), block.apply(c), FillCommand.Mode.REPLACE, filter.apply(c), false
)
)
.then(
Commands.literal("outline")
.executes(
c -> fillBlocks(
c.getSource(),
BoundingBox.fromCorners(from.apply(c), to.apply(c)),
block.apply(c),
FillCommand.Mode.OUTLINE,
filter.apply(c),
false
)
)
)
.then(
Commands.literal("hollow")
.executes(
c -> fillBlocks(
c.getSource(), BoundingBox.fromCorners(from.apply(c), to.apply(c)), block.apply(c), FillCommand.Mode.HOLLOW, filter.apply(c), false
)
)
)
.then(
Commands.literal("destroy")
.executes(
c -> fillBlocks(
c.getSource(),
BoundingBox.fromCorners(from.apply(c), to.apply(c)),
block.apply(c),
FillCommand.Mode.DESTROY,
filter.apply(c),
false
)
)
)
.then(
Commands.literal("strict")
.executes(
c -> fillBlocks(
c.getSource(), BoundingBox.fromCorners(from.apply(c), to.apply(c)), block.apply(c), FillCommand.Mode.REPLACE, filter.apply(c), true
)
)
);
}
private static int fillBlocks(
CommandSourceStack source, BoundingBox region, BlockInput target, FillCommand.Mode mode, @Nullable Predicate<BlockInWorld> predicate, boolean strict
) throws CommandSyntaxException {
long area = (long)region.getXSpan() * region.getYSpan() * region.getZSpan();
int limit = source.getLevel().getGameRules().get(GameRules.MAX_BLOCK_MODIFICATIONS);
if (area > limit) {
throw ERROR_AREA_TOO_LARGE.create(limit, area);
} else {
record UpdatedPosition(BlockPos pos, BlockState oldState) {
}
List<UpdatedPosition> updatePositions = Lists.newArrayList();
ServerLevel level = source.getLevel();
if (level.isDebug()) {
throw ERROR_FAILED.create();
} else {
int count = 0;
for (BlockPos pos : BlockPos.betweenClosed(region.minX(), region.minY(), region.minZ(), region.maxX(), region.maxY(), region.maxZ())) {
if (predicate == null || predicate.test(new BlockInWorld(level, pos, true))) {
BlockState oldState = level.getBlockState(pos);
boolean affected = false;
if (mode.affector.affect(level, pos)) {
affected = true;
}
BlockInput block = mode.filter.filter(region, pos, target, level);
if (block == null) {
if (affected) {
count++;
}
} else if (!block.place(level, pos, 2 | (strict ? 816 : 256))) {
if (affected) {
count++;
}
} else {
if (!strict) {
updatePositions.add(new UpdatedPosition(pos.immutable(), oldState));
}
count++;
}
}
}
for (UpdatedPosition posx : updatePositions) {
level.updateNeighboursOnBlockSet(posx.pos, posx.oldState);
}
if (count == 0) {
throw ERROR_FAILED.create();
} else {
int finalCount = count;
source.sendSuccess(() -> Component.translatable("commands.fill.success", finalCount), true);
return count;
}
}
}
}
@FunctionalInterface
public interface Affector {
FillCommand.Affector NOOP = (l, p) -> false;
boolean affect(final ServerLevel level, final BlockPos pos);
}
@FunctionalInterface
public interface Filter {
FillCommand.Filter NOOP = (r, p, b, l) -> b;
@Nullable BlockInput filter(final BoundingBox region, final BlockPos pos, final BlockInput block, final ServerLevel level);
}
private static enum Mode {
REPLACE(FillCommand.Affector.NOOP, FillCommand.Filter.NOOP),
OUTLINE(
FillCommand.Affector.NOOP,
(r, p, b, l) -> p.getX() != r.minX()
&& p.getX() != r.maxX()
&& p.getY() != r.minY()
&& p.getY() != r.maxY()
&& p.getZ() != r.minZ()
&& p.getZ() != r.maxZ()
? null
: b
),
HOLLOW(
FillCommand.Affector.NOOP,
(r, p, b, l) -> p.getX() != r.minX()
&& p.getX() != r.maxX()
&& p.getY() != r.minY()
&& p.getY() != r.maxY()
&& p.getZ() != r.minZ()
&& p.getZ() != r.maxZ()
? FillCommand.HOLLOW_CORE
: b
),
DESTROY((l, p) -> l.destroyBlock(p, true), FillCommand.Filter.NOOP);
public final FillCommand.Filter filter;
public final FillCommand.Affector affector;
private Mode(FillCommand.Affector affector, FillCommand.Filter filter) {
this.affector = affector;
this.filter = filter;
}
}
@FunctionalInterface
private interface NullableCommandFunction<T, R> {
@Nullable R apply(T t) throws CommandSyntaxException;
}
}引用的其他类
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/返回值
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Commands.argument(), Commands.hasPermission(), Commands.literal()
- 引用位置:
-
- 引用位置:
参数/字段/构造调用 - 关联成员:
BlockInput()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
BlockPredicateArgument.blockPredicate(), BlockPredicateArgument.getBlockPredicate()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
BlockStateArgument.block(), BlockStateArgument.getBlock()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
BlockPosArgument.blockPos(), BlockPosArgument.getLoadedBlockPos()
- 引用位置:
-
- 引用位置:
参数/方法调用 - 关联成员:
BlockPos.betweenClosed()
- 引用位置:
-
- 引用位置:
方法调用 - 关联成员:
Component.translatable(), Component.translatableEscape()
- 引用位置:
-
- 引用位置:
参数
- 引用位置:
-
- 引用位置:
参数/构造调用 - 关联成员:
BlockInWorld()
- 引用位置:
-
- 引用位置:
参数/方法调用 - 关联成员:
BoundingBox.fromCorners()
- 引用位置: