119 lines
8.8 KiB
Java
119 lines
8.8 KiB
Java
package net.minecraft.server.commands;
|
|
|
|
import net.minecraft.nbt.CompoundTag;
|
|
import net.minecraft.world.level.block.state.properties.Property;
|
|
import java.util.Collections;
|
|
import net.minecraft.world.level.block.Blocks;
|
|
import com.mojang.brigadier.Message;
|
|
import net.minecraft.core.Vec3i;
|
|
import com.mojang.brigadier.context.CommandContext;
|
|
import com.mojang.brigadier.exceptions.CommandSyntaxException;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.entity.BlockEntity;
|
|
import java.util.Iterator;
|
|
import net.minecraft.server.level.ServerLevel;
|
|
import java.util.List;
|
|
import net.minecraft.network.chat.Component;
|
|
import net.minecraft.network.chat.TranslatableComponent;
|
|
import net.minecraft.world.Clearable;
|
|
import net.minecraft.world.level.LevelReader;
|
|
import net.minecraft.core.BlockPos;
|
|
import com.google.common.collect.Lists;
|
|
import javax.annotation.Nullable;
|
|
import net.minecraft.world.level.block.state.pattern.BlockInWorld;
|
|
import java.util.function.Predicate;
|
|
import net.minecraft.world.level.levelgen.structure.BoundingBox;
|
|
import net.minecraft.commands.arguments.blocks.BlockPredicateArgument;
|
|
import net.minecraft.commands.arguments.blocks.BlockStateArgument;
|
|
import com.mojang.brigadier.builder.RequiredArgumentBuilder;
|
|
import com.mojang.brigadier.arguments.ArgumentType;
|
|
import net.minecraft.commands.arguments.coordinates.BlockPosArgument;
|
|
import net.minecraft.commands.Commands;
|
|
import com.mojang.brigadier.builder.LiteralArgumentBuilder;
|
|
import net.minecraft.commands.CommandSourceStack;
|
|
import com.mojang.brigadier.CommandDispatcher;
|
|
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
|
|
import net.minecraft.commands.arguments.blocks.BlockInput;
|
|
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
|
|
|
|
public class FillCommand {
|
|
private static final Dynamic2CommandExceptionType ERROR_AREA_TOO_LARGE;
|
|
private static final BlockInput HOLLOW_CORE;
|
|
private static final SimpleCommandExceptionType ERROR_FAILED;
|
|
|
|
public static void register(final CommandDispatcher<CommandSourceStack> commandDispatcher) {
|
|
commandDispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.literal("fill").requires(cq -> cq.hasPermission(2))).then(Commands.argument("from", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPosArgument.blockPos()).then(Commands.argument("to", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPosArgument.blockPos()).then(((RequiredArgumentBuilder)((RequiredArgumentBuilder)((RequiredArgumentBuilder)((RequiredArgumentBuilder)((RequiredArgumentBuilder)Commands.argument("block", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockStateArgument.block()).executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.REPLACE, null))).then(((LiteralArgumentBuilder)Commands.literal("replace").executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.REPLACE, null))).then(Commands.argument("filter", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPredicateArgument.blockPredicate()).executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.REPLACE, BlockPredicateArgument.getBlockPredicate((CommandContext<CommandSourceStack>)commandContext, "filter")))))).then(Commands.literal("keep").executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.REPLACE, byk -> byk.getLevel().isEmptyBlock(byk.getPos()))))).then(Commands.literal("outline").executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.OUTLINE, null)))).then(Commands.literal("hollow").executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.HOLLOW, null)))).then(Commands.literal("destroy").executes(commandContext -> fillBlocks((CommandSourceStack)commandContext.getSource(), new BoundingBox(BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "from"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "to")), BlockStateArgument.getBlock((CommandContext<CommandSourceStack>)commandContext, "block"), Mode.DESTROY, null)))))));
|
|
}
|
|
|
|
private static int fillBlocks(final CommandSourceStack cq, final BoundingBox cky, final BlockInput ds, final Mode a, @Nullable final Predicate<BlockInWorld> predicate) throws CommandSyntaxException {
|
|
final int integer6 = cky.getXSpan() * cky.getYSpan() * cky.getZSpan();
|
|
if (integer6 > 32768) {
|
|
throw FillCommand.ERROR_AREA_TOO_LARGE.create(32768, integer6);
|
|
}
|
|
final List<BlockPos> list7 = Lists.newArrayList();
|
|
final ServerLevel xd8 = cq.getLevel();
|
|
int integer7 = 0;
|
|
for (final BlockPos fk11 : BlockPos.betweenClosed(cky.x0, cky.y0, cky.z0, cky.x1, cky.y1, cky.z1)) {
|
|
if (predicate != null && !predicate.test(new BlockInWorld(xd8, fk11, true))) {
|
|
continue;
|
|
}
|
|
final BlockInput ds2 = a.filter.filter(cky, fk11, ds, xd8);
|
|
if (ds2 == null) {
|
|
continue;
|
|
}
|
|
final BlockEntity bwi13 = xd8.getBlockEntity(fk11);
|
|
Clearable.tryClear(bwi13);
|
|
if (!ds2.place(xd8, fk11, 2)) {
|
|
continue;
|
|
}
|
|
list7.add(fk11.immutable());
|
|
++integer7;
|
|
}
|
|
for (final BlockPos fk11 : list7) {
|
|
final Block bpe12 = xd8.getBlockState(fk11).getBlock();
|
|
xd8.blockUpdated(fk11, bpe12);
|
|
}
|
|
if (integer7 == 0) {
|
|
throw FillCommand.ERROR_FAILED.create();
|
|
}
|
|
cq.sendSuccess(new TranslatableComponent("commands.fill.success", new Object[] { integer7 }), true);
|
|
return integer7;
|
|
}
|
|
|
|
static {
|
|
ERROR_AREA_TOO_LARGE = new Dynamic2CommandExceptionType((object1, object2) -> new TranslatableComponent("commands.fill.toobig", new Object[] { object1, object2 }));
|
|
HOLLOW_CORE = new BlockInput(Blocks.AIR.defaultBlockState(), Collections.<Property<?>>emptySet(), null);
|
|
ERROR_FAILED = new SimpleCommandExceptionType((Message)new TranslatableComponent("commands.fill.failed", new Object[0]));
|
|
}
|
|
|
|
enum Mode {
|
|
REPLACE((cky, fk, ds, xd) -> ds),
|
|
OUTLINE((cky, fk, ds, xd) -> {
|
|
if (fk.getX() == cky.x0 || fk.getX() == cky.x1 || fk.getY() == cky.y0 || fk.getY() == cky.y1 || fk.getZ() == cky.z0 || fk.getZ() == cky.z1) {
|
|
return ds;
|
|
}
|
|
else {
|
|
return null;
|
|
}
|
|
}),
|
|
HOLLOW((cky, fk, ds, xd) -> {
|
|
if (fk.getX() == cky.x0 || fk.getX() == cky.x1 || fk.getY() == cky.y0 || fk.getY() == cky.y1 || fk.getZ() == cky.z0 || fk.getZ() == cky.z1) {
|
|
return ds;
|
|
}
|
|
else {
|
|
return FillCommand.HOLLOW_CORE;
|
|
}
|
|
}),
|
|
DESTROY((cky, fk, ds, xd) -> {
|
|
xd.destroyBlock(fk, true);
|
|
return ds;
|
|
});
|
|
|
|
public final SetBlockCommand.Filter filter;
|
|
|
|
private Mode(final SetBlockCommand.Filter a) {
|
|
this.filter = a;
|
|
}
|
|
}
|
|
}
|