minecraft-source/src/net/minecraft/server/commands/CloneCommands.java

178 lines
15 KiB
Java

package net.minecraft.server.commands;
import javax.annotation.Nullable;
import com.mojang.brigadier.Message;
import com.mojang.brigadier.context.CommandContext;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import java.util.Iterator;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.level.block.state.BlockState;
import java.util.Deque;
import java.util.List;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import java.util.Collection;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.Clearable;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.world.level.LevelReader;
import com.google.common.collect.Lists;
import net.minecraft.core.Vec3i;
import net.minecraft.world.level.levelgen.structure.BoundingBox;
import net.minecraft.core.BlockPos;
import net.minecraft.commands.arguments.blocks.BlockPredicateArgument;
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 net.minecraft.world.level.block.state.pattern.BlockInWorld;
import java.util.function.Predicate;
import com.mojang.brigadier.exceptions.Dynamic2CommandExceptionType;
import com.mojang.brigadier.exceptions.SimpleCommandExceptionType;
public class CloneCommands {
private static final SimpleCommandExceptionType ERROR_OVERLAP;
private static final Dynamic2CommandExceptionType ERROR_AREA_TOO_LARGE;
private static final SimpleCommandExceptionType ERROR_FAILED;
public static final Predicate<BlockInWorld> FILTER_AIR;
public static void register(final CommandDispatcher<CommandSourceStack> commandDispatcher) {
commandDispatcher.register((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.literal("clone").requires(cq -> cq.hasPermission(2))).then(Commands.argument("begin", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPosArgument.blockPos()).then(Commands.argument("end", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPosArgument.blockPos()).then(((RequiredArgumentBuilder)((RequiredArgumentBuilder)((RequiredArgumentBuilder)Commands.argument("destination", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPosArgument.blockPos()).executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), byk -> true, Mode.NORMAL))).then(((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.literal("replace").executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), byk -> true, Mode.NORMAL))).then(Commands.literal("force").executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), byk -> true, Mode.FORCE)))).then(Commands.literal("move").executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), byk -> true, Mode.MOVE)))).then(Commands.literal("normal").executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), byk -> true, Mode.NORMAL))))).then(((LiteralArgumentBuilder)((LiteralArgumentBuilder)((LiteralArgumentBuilder)Commands.literal("masked").executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), CloneCommands.FILTER_AIR, Mode.NORMAL))).then(Commands.literal("force").executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), CloneCommands.FILTER_AIR, Mode.FORCE)))).then(Commands.literal("move").executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), CloneCommands.FILTER_AIR, Mode.MOVE)))).then(Commands.literal("normal").executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), CloneCommands.FILTER_AIR, Mode.NORMAL))))).then(Commands.literal("filtered").then(((RequiredArgumentBuilder)((RequiredArgumentBuilder)((RequiredArgumentBuilder)Commands.argument("filter", (com.mojang.brigadier.arguments.ArgumentType<Object>)BlockPredicateArgument.blockPredicate()).executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), BlockPredicateArgument.getBlockPredicate((CommandContext<CommandSourceStack>)commandContext, "filter"), Mode.NORMAL))).then(Commands.literal("force").executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), BlockPredicateArgument.getBlockPredicate((CommandContext<CommandSourceStack>)commandContext, "filter"), Mode.FORCE)))).then(Commands.literal("move").executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), BlockPredicateArgument.getBlockPredicate((CommandContext<CommandSourceStack>)commandContext, "filter"), Mode.MOVE)))).then(Commands.literal("normal").executes(commandContext -> clone((CommandSourceStack)commandContext.getSource(), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "begin"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "end"), BlockPosArgument.getLoadedBlockPos((CommandContext<CommandSourceStack>)commandContext, "destination"), BlockPredicateArgument.getBlockPredicate((CommandContext<CommandSourceStack>)commandContext, "filter"), Mode.NORMAL)))))))));
}
private static int clone(final CommandSourceStack cq, final BlockPos fk2, final BlockPos fk3, final BlockPos fk4, final Predicate<BlockInWorld> predicate, final Mode b) throws CommandSyntaxException {
final BoundingBox cky7 = new BoundingBox(fk2, fk3);
final BlockPos fk5 = fk4.offset(cky7.getLength());
final BoundingBox cky8 = new BoundingBox(fk4, fk5);
if (!b.canOverlap() && cky8.intersects(cky7)) {
throw CloneCommands.ERROR_OVERLAP.create();
}
final int integer10 = cky7.getXSpan() * cky7.getYSpan() * cky7.getZSpan();
if (integer10 > 32768) {
throw CloneCommands.ERROR_AREA_TOO_LARGE.create(32768, integer10);
}
final ServerLevel xd11 = cq.getLevel();
if (!xd11.hasChunksAt(fk2, fk3) || !xd11.hasChunksAt(fk4, fk5)) {
throw BlockPosArgument.ERROR_NOT_LOADED.create();
}
final List<CloneBlockInfo> list12 = Lists.newArrayList();
final List<CloneBlockInfo> list13 = Lists.newArrayList();
final List<CloneBlockInfo> list14 = Lists.newArrayList();
final Deque<BlockPos> deque15 = Lists.newLinkedList();
final BlockPos fk6 = new BlockPos(cky8.x0 - cky7.x0, cky8.y0 - cky7.y0, cky8.z0 - cky7.z0);
for (int integer11 = cky7.z0; integer11 <= cky7.z1; ++integer11) {
for (int integer12 = cky7.y0; integer12 <= cky7.y1; ++integer12) {
for (int integer13 = cky7.x0; integer13 <= cky7.x1; ++integer13) {
final BlockPos fk7 = new BlockPos(integer13, integer12, integer11);
final BlockPos fk8 = fk7.offset(fk6);
final BlockInWorld byk22 = new BlockInWorld(xd11, fk7, false);
final BlockState byg23 = byk22.getState();
if (predicate.test(byk22)) {
final BlockEntity bwi24 = xd11.getBlockEntity(fk7);
if (bwi24 != null) {
final CompoundTag jt25 = bwi24.save(new CompoundTag());
list13.add(new CloneBlockInfo(fk8, byg23, jt25));
deque15.addLast(fk7);
}
else if (byg23.isSolidRender(xd11, fk7) || byg23.isCollisionShapeFullBlock(xd11, fk7)) {
list12.add(new CloneBlockInfo(fk8, byg23, null));
deque15.addLast(fk7);
}
else {
list14.add(new CloneBlockInfo(fk8, byg23, null));
deque15.addFirst(fk7);
}
}
}
}
}
if (b == Mode.MOVE) {
for (final BlockPos fk9 : deque15) {
final BlockEntity bwi25 = xd11.getBlockEntity(fk9);
Clearable.tryClear(bwi25);
xd11.setBlock(fk9, Blocks.BARRIER.defaultBlockState(), 2);
}
for (final BlockPos fk9 : deque15) {
xd11.setBlock(fk9, Blocks.AIR.defaultBlockState(), 3);
}
}
final List<CloneBlockInfo> list15 = Lists.newArrayList();
list15.addAll(list12);
list15.addAll(list13);
list15.addAll(list14);
final List<CloneBlockInfo> list16 = Lists.<CloneBlockInfo>reverse(list15);
for (final CloneBlockInfo a20 : list16) {
final BlockEntity bwi26 = xd11.getBlockEntity(a20.pos);
Clearable.tryClear(bwi26);
xd11.setBlock(a20.pos, Blocks.BARRIER.defaultBlockState(), 2);
}
int integer13 = 0;
for (final CloneBlockInfo a21 : list15) {
if (xd11.setBlock(a21.pos, a21.state, 2)) {
++integer13;
}
}
for (final CloneBlockInfo a21 : list13) {
final BlockEntity bwi27 = xd11.getBlockEntity(a21.pos);
if (a21.tag != null && bwi27 != null) {
a21.tag.putInt("x", a21.pos.getX());
a21.tag.putInt("y", a21.pos.getY());
a21.tag.putInt("z", a21.pos.getZ());
bwi27.load(a21.tag);
bwi27.setChanged();
}
xd11.setBlock(a21.pos, a21.state, 2);
}
for (final CloneBlockInfo a21 : list16) {
xd11.blockUpdated(a21.pos, a21.state.getBlock());
}
xd11.getBlockTicks().copy(cky7, fk6);
if (integer13 == 0) {
throw CloneCommands.ERROR_FAILED.create();
}
cq.sendSuccess(new TranslatableComponent("commands.clone.success", new Object[] { integer13 }), true);
return integer13;
}
static {
ERROR_OVERLAP = new SimpleCommandExceptionType((Message)new TranslatableComponent("commands.clone.overlap", new Object[0]));
ERROR_AREA_TOO_LARGE = new Dynamic2CommandExceptionType((object1, object2) -> new TranslatableComponent("commands.clone.toobig", new Object[] { object1, object2 }));
ERROR_FAILED = new SimpleCommandExceptionType((Message)new TranslatableComponent("commands.clone.failed", new Object[0]));
FILTER_AIR = (byk -> !byk.getState().isAir());
}
enum Mode {
FORCE(true),
MOVE(true),
NORMAL(false);
private final boolean canOverlap;
private Mode(final boolean boolean3) {
this.canOverlap = boolean3;
}
public boolean canOverlap() {
return this.canOverlap;
}
}
static class CloneBlockInfo {
public final BlockPos pos;
public final BlockState state;
@Nullable
public final CompoundTag tag;
public CloneBlockInfo(final BlockPos fk, final BlockState byg, @Nullable final CompoundTag jt) {
this.pos = fk;
this.state = byg;
this.tag = jt;
}
}
}