mirror of
https://github.com/plexusorg/Plex-FAWE.git
synced 2025-07-02 19:36:41 +00:00
Switch to Gradle. Use git log --follow for history.
This converts the project into a multi-module Gradle build. By default, Git does not show history past a rename, so use git log --follow to see further history.
This commit is contained in:
@ -0,0 +1,209 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.FlatRegionFunction;
|
||||
import com.sk89q.worldedit.function.FlatRegionMaskingFilter;
|
||||
import com.sk89q.worldedit.function.biome.BiomeReplace;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.Mask2D;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.visitor.FlatRegionVisitor;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.FlatRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.Regions;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import com.sk89q.worldedit.world.biome.BiomeData;
|
||||
import com.sk89q.worldedit.world.registry.BiomeRegistry;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
|
||||
/**
|
||||
* Implements biome-related commands such as "/biomelist".
|
||||
*/
|
||||
public class BiomeCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public BiomeCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "biomelist", "biomels" },
|
||||
usage = "[page]",
|
||||
desc = "Gets all biomes available.",
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.biome.list")
|
||||
public void biomeList(Player player, CommandContext args) throws WorldEditException {
|
||||
int page;
|
||||
int offset;
|
||||
int count = 0;
|
||||
|
||||
if (args.argsLength() == 0 || (page = args.getInteger(0)) < 2) {
|
||||
page = 1;
|
||||
offset = 0;
|
||||
} else {
|
||||
offset = (page - 1) * 19;
|
||||
}
|
||||
|
||||
BiomeRegistry biomeRegistry = player.getWorld().getWorldData().getBiomeRegistry();
|
||||
List<BaseBiome> biomes = biomeRegistry.getBiomes();
|
||||
int totalPages = biomes.size() / 19 + 1;
|
||||
player.print("Available Biomes (page " + page + "/" + totalPages + ") :");
|
||||
for (BaseBiome biome : biomes) {
|
||||
if (offset > 0) {
|
||||
offset--;
|
||||
} else {
|
||||
BiomeData data = biomeRegistry.getData(biome);
|
||||
if (data != null) {
|
||||
player.print(" " + data.getName());
|
||||
if (++count == 19) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
player.print(" <unknown #" + biome.getId() + ">");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "biomeinfo" },
|
||||
flags = "pt",
|
||||
desc = "Get the biome of the targeted block.",
|
||||
help =
|
||||
"Get the biome of the block.\n" +
|
||||
"By default use all the blocks contained in your selection.\n" +
|
||||
"-t use the block you are looking at.\n" +
|
||||
"-p use the block you are currently in",
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.biome.info")
|
||||
public void biomeInfo(Player player, LocalSession session, CommandContext args) throws WorldEditException {
|
||||
BiomeRegistry biomeRegistry = player.getWorld().getWorldData().getBiomeRegistry();
|
||||
Set<BaseBiome> biomes = new HashSet<BaseBiome>();
|
||||
String qualifier;
|
||||
|
||||
if (args.hasFlag('t')) {
|
||||
Vector blockPosition = player.getBlockTrace(300);
|
||||
if (blockPosition == null) {
|
||||
player.printError("No block in sight!");
|
||||
return;
|
||||
}
|
||||
|
||||
BaseBiome biome = player.getWorld().getBiome(blockPosition.toVector2D());
|
||||
biomes.add(biome);
|
||||
|
||||
qualifier = "at line of sight point";
|
||||
} else if (args.hasFlag('p')) {
|
||||
BaseBiome biome = player.getWorld().getBiome(player.getPosition().toVector2D());
|
||||
biomes.add(biome);
|
||||
|
||||
qualifier = "at your position";
|
||||
} else {
|
||||
World world = player.getWorld();
|
||||
Region region = session.getSelection(world);
|
||||
|
||||
if (region instanceof FlatRegion) {
|
||||
for (Vector2D pt : ((FlatRegion) region).asFlatRegion()) {
|
||||
biomes.add(world.getBiome(pt));
|
||||
}
|
||||
} else {
|
||||
for (Vector pt : region) {
|
||||
biomes.add(world.getBiome(pt.toVector2D()));
|
||||
}
|
||||
}
|
||||
|
||||
qualifier = "in your selection";
|
||||
}
|
||||
|
||||
player.print(biomes.size() != 1 ? "Biomes " + qualifier + ":" : "Biome " + qualifier + ":");
|
||||
for (BaseBiome biome : biomes) {
|
||||
BiomeData data = biomeRegistry.getData(biome);
|
||||
if (data != null) {
|
||||
player.print(" " + data.getName());
|
||||
} else {
|
||||
player.print(" <unknown #" + biome.getId() + ">");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/setbiome" },
|
||||
usage = "<biome>",
|
||||
flags = "p",
|
||||
desc = "Sets the biome of the player's current block or region.",
|
||||
help =
|
||||
"Set the biome of the region.\n" +
|
||||
"By default use all the blocks contained in your selection.\n" +
|
||||
"-p use the block you are currently in"
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.biome.set")
|
||||
public void setBiome(Player player, LocalSession session, EditSession editSession, BaseBiome target, @Switch('p') boolean atPosition) throws WorldEditException {
|
||||
World world = player.getWorld();
|
||||
Region region;
|
||||
Mask mask = editSession.getMask();
|
||||
Mask2D mask2d = mask != null ? mask.toMask2D() : null;
|
||||
|
||||
if (atPosition) {
|
||||
region = new CuboidRegion(player.getPosition(), player.getPosition());
|
||||
} else {
|
||||
region = session.getSelection(world);
|
||||
}
|
||||
|
||||
FlatRegionFunction replace = new BiomeReplace(editSession, target);
|
||||
if (mask2d != null) {
|
||||
replace = new FlatRegionMaskingFilter(mask2d, replace);
|
||||
}
|
||||
FlatRegionVisitor visitor = new FlatRegionVisitor(Regions.asFlatRegion(region), replace);
|
||||
Operations.completeLegacy(visitor);
|
||||
|
||||
player.print("Biomes were changed in " + visitor.getAffected() + " columns. You may have to rejoin your game (or close and reopen your world) to see a change.");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,273 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.command.tool.BrushTool;
|
||||
import com.sk89q.worldedit.command.tool.brush.ButcherBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.ClipboardBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.CylinderBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.GravityBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.HollowCylinderBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.HollowSphereBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.SmoothBrush;
|
||||
import com.sk89q.worldedit.command.tool.brush.SphereBrush;
|
||||
import com.sk89q.worldedit.command.util.CreatureButcher;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.mask.BlockMask;
|
||||
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Commands to set brush shape.
|
||||
*/
|
||||
public class BrushCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public BrushCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "sphere", "s" },
|
||||
usage = "<pattern> [radius]",
|
||||
flags = "h",
|
||||
desc = "Choose the sphere brush",
|
||||
help =
|
||||
"Chooses the sphere brush.\n" +
|
||||
"The -h flag creates hollow spheres instead.",
|
||||
min = 1,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.sphere")
|
||||
public void sphereBrush(Player player, LocalSession session, EditSession editSession, Pattern fill,
|
||||
@Optional("2") double radius, @Switch('h') boolean hollow) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand());
|
||||
tool.setFill(fill);
|
||||
tool.setSize(radius);
|
||||
|
||||
if (hollow) {
|
||||
tool.setBrush(new HollowSphereBrush(), "worldedit.brush.sphere");
|
||||
} else {
|
||||
tool.setBrush(new SphereBrush(), "worldedit.brush.sphere");
|
||||
}
|
||||
|
||||
player.print(String.format("Sphere brush shape equipped (%.0f).", radius));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "cylinder", "cyl", "c" },
|
||||
usage = "<block> [radius] [height]",
|
||||
flags = "h",
|
||||
desc = "Choose the cylinder brush",
|
||||
help =
|
||||
"Chooses the cylinder brush.\n" +
|
||||
"The -h flag creates hollow cylinders instead.",
|
||||
min = 1,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.cylinder")
|
||||
public void cylinderBrush(Player player, LocalSession session, EditSession editSession, Pattern fill,
|
||||
@Optional("2") double radius, @Optional("1") int height, @Switch('h') boolean hollow) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
worldEdit.checkMaxBrushRadius(height);
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand());
|
||||
tool.setFill(fill);
|
||||
tool.setSize(radius);
|
||||
|
||||
if (hollow) {
|
||||
tool.setBrush(new HollowCylinderBrush(height), "worldedit.brush.cylinder");
|
||||
} else {
|
||||
tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder");
|
||||
}
|
||||
|
||||
player.print(String.format("Cylinder brush shape equipped (%.0f by %d).", radius, height));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "clipboard", "copy" },
|
||||
usage = "",
|
||||
desc = "Choose the clipboard brush",
|
||||
help =
|
||||
"Chooses the clipboard brush.\n" +
|
||||
"The -a flag makes it not paste air.\n" +
|
||||
"Without the -p flag, the paste will appear centered at the target location. " +
|
||||
"With the flag, then the paste will appear relative to where you had " +
|
||||
"stood relative to the copied area when you copied it."
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.clipboard")
|
||||
public void clipboardBrush(Player player, LocalSession session, EditSession editSession, @Switch('a') boolean ignoreAir, @Switch('p') boolean usingOrigin) throws WorldEditException {
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
|
||||
Vector size = clipboard.getDimensions();
|
||||
|
||||
worldEdit.checkMaxBrushRadius(size.getBlockX());
|
||||
worldEdit.checkMaxBrushRadius(size.getBlockY());
|
||||
worldEdit.checkMaxBrushRadius(size.getBlockZ());
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand());
|
||||
tool.setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin), "worldedit.brush.clipboard");
|
||||
|
||||
player.print("Clipboard brush shape equipped.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "smooth" },
|
||||
usage = "[size] [iterations]",
|
||||
flags = "n",
|
||||
desc = "Choose the terrain softener brush",
|
||||
help =
|
||||
"Chooses the terrain softener brush.\n" +
|
||||
"The -n flag makes it only consider naturally occurring blocks.",
|
||||
min = 0,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.smooth")
|
||||
public void smoothBrush(Player player, LocalSession session, EditSession editSession,
|
||||
@Optional("2") double radius, @Optional("4") int iterations, @Switch('n')
|
||||
boolean naturalBlocksOnly) throws WorldEditException {
|
||||
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand());
|
||||
tool.setSize(radius);
|
||||
tool.setBrush(new SmoothBrush(iterations, naturalBlocksOnly), "worldedit.brush.smooth");
|
||||
|
||||
player.print(String.format("Smooth brush equipped (%.0f x %dx, using " + (naturalBlocksOnly ? "natural blocks only" : "any block") + ").",
|
||||
radius, iterations));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "ex", "extinguish" },
|
||||
usage = "[radius]",
|
||||
desc = "Shortcut fire extinguisher brush",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.ex")
|
||||
public void extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand());
|
||||
Pattern fill = new BlockPattern(new BaseBlock(0));
|
||||
tool.setFill(fill);
|
||||
tool.setSize(radius);
|
||||
tool.setMask(new BlockMask(editSession, new BaseBlock(BlockID.FIRE)));
|
||||
tool.setBrush(new SphereBrush(), "worldedit.brush.ex");
|
||||
|
||||
player.print(String.format("Extinguisher equipped (%.0f).", radius));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "gravity", "grav" },
|
||||
usage = "[radius]",
|
||||
flags = "h",
|
||||
desc = "Gravity brush",
|
||||
help =
|
||||
"This brush simulates the affect of gravity.\n" +
|
||||
"The -h flag makes it affect blocks starting at the world's max y, " +
|
||||
"instead of the clicked block's y + radius.",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.gravity")
|
||||
public void gravityBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius, @Switch('h') boolean fromMaxY) throws WorldEditException {
|
||||
worldEdit.checkMaxBrushRadius(radius);
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand());
|
||||
tool.setSize(radius);
|
||||
tool.setBrush(new GravityBrush(fromMaxY), "worldedit.brush.gravity");
|
||||
|
||||
player.print(String.format("Gravity brush equipped (%.0f).",
|
||||
radius));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "butcher", "kill" },
|
||||
usage = "[radius]",
|
||||
flags = "plangbtf",
|
||||
desc = "Butcher brush",
|
||||
help = "Kills nearby mobs within the specified radius.\n" +
|
||||
"Flags:" +
|
||||
" -p also kills pets.\n" +
|
||||
" -n also kills NPCs.\n" +
|
||||
" -g also kills Golems.\n" +
|
||||
" -a also kills animals.\n" +
|
||||
" -b also kills ambient mobs.\n" +
|
||||
" -t also kills mobs with name tags.\n" +
|
||||
" -f compounds all previous flags.\n" +
|
||||
" -l currently does nothing.",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.butcher")
|
||||
public void butcherBrush(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
double radius = args.argsLength() > 0 ? args.getDouble(0) : 5;
|
||||
double maxRadius = config.maxBrushRadius;
|
||||
// hmmmm not horribly worried about this because -1 is still rather efficient,
|
||||
// the problem arises when butcherMaxRadius is some really high number but not infinite
|
||||
// - original idea taken from https://github.com/sk89q/worldedit/pull/198#issuecomment-6463108
|
||||
if (player.hasPermission("worldedit.butcher")) {
|
||||
maxRadius = Math.max(config.maxBrushRadius, config.butcherMaxRadius);
|
||||
}
|
||||
if (radius > maxRadius) {
|
||||
player.printError("Maximum allowed brush radius: " + maxRadius);
|
||||
return;
|
||||
}
|
||||
|
||||
CreatureButcher flags = new CreatureButcher(player);
|
||||
flags.fromCommand(args);
|
||||
|
||||
BrushTool tool = session.getBrushTool(player.getItemInHand());
|
||||
tool.setSize(radius);
|
||||
tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher");
|
||||
|
||||
player.print(String.format("Butcher brush equipped (%.0f).", radius));
|
||||
}
|
||||
}
|
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.math.MathUtils;
|
||||
import com.sk89q.worldedit.world.storage.LegacyChunkStore;
|
||||
import com.sk89q.worldedit.world.storage.McRegionChunkStore;
|
||||
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
|
||||
/**
|
||||
* Commands for working with chunks.
|
||||
*/
|
||||
public class ChunkCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
public ChunkCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "chunkinfo" },
|
||||
usage = "",
|
||||
desc = "Get information about the chunk that you are inside",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.chunkinfo")
|
||||
public void chunkInfo(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
Vector pos = player.getBlockIn();
|
||||
int chunkX = (int) Math.floor(pos.getBlockX() / 16.0);
|
||||
int chunkZ = (int) Math.floor(pos.getBlockZ() / 16.0);
|
||||
|
||||
String folder1 = Integer.toString(MathUtils.divisorMod(chunkX, 64), 36);
|
||||
String folder2 = Integer.toString(MathUtils.divisorMod(chunkZ, 64), 36);
|
||||
String filename = "c." + Integer.toString(chunkX, 36)
|
||||
+ "." + Integer.toString(chunkZ, 36) + ".dat";
|
||||
|
||||
player.print("Chunk: " + chunkX + ", " + chunkZ);
|
||||
player.print("Old format: " + folder1 + "/" + folder2 + "/" + filename);
|
||||
player.print("McRegion: region/" + McRegionChunkStore.getFilename(
|
||||
new Vector2D(chunkX, chunkZ)));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "listchunks" },
|
||||
usage = "",
|
||||
desc = "List chunks that your selection includes",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.listchunks")
|
||||
public void listChunks(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
Set<Vector2D> chunks = session.getSelection(player.getWorld()).getChunks();
|
||||
|
||||
for (Vector2D chunk : chunks) {
|
||||
player.print(LegacyChunkStore.getFilename(chunk));
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "delchunks" },
|
||||
usage = "",
|
||||
desc = "Delete chunks that your selection includes",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.delchunks")
|
||||
@Logging(REGION)
|
||||
public void deleteChunks(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
player.print("Note that this command does not yet support the mcregion format.");
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
Set<Vector2D> chunks = session.getSelection(player.getWorld()).getChunks();
|
||||
FileOutputStream out = null;
|
||||
|
||||
if (config.shellSaveType == null) {
|
||||
player.printError("Shell script type must be configured: 'bat' or 'bash' expected.");
|
||||
} else if (config.shellSaveType.equalsIgnoreCase("bat")) {
|
||||
try {
|
||||
out = new FileOutputStream("worldedit-delchunks.bat");
|
||||
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
|
||||
writer.write("@ECHO off\r\n");
|
||||
writer.write("ECHO This batch file was generated by WorldEdit.\r\n");
|
||||
writer.write("ECHO It contains a list of chunks that were in the selected region\r\n");
|
||||
writer.write("ECHO at the time that the /delchunks command was used. Run this file\r\n");
|
||||
writer.write("ECHO in order to delete the chunk files listed in this file.\r\n");
|
||||
writer.write("ECHO.\r\n");
|
||||
writer.write("PAUSE\r\n");
|
||||
|
||||
for (Vector2D chunk : chunks) {
|
||||
String filename = LegacyChunkStore.getFilename(chunk);
|
||||
writer.write("ECHO " + filename + "\r\n");
|
||||
writer.write("DEL \"world/" + filename + "\"\r\n");
|
||||
}
|
||||
|
||||
writer.write("ECHO Complete.\r\n");
|
||||
writer.write("PAUSE\r\n");
|
||||
writer.close();
|
||||
player.print("worldedit-delchunks.bat written. Run it when no one is near the region.");
|
||||
} catch (IOException e) {
|
||||
player.printError("Error occurred: " + e.getMessage());
|
||||
} finally {
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException ignored) { }
|
||||
}
|
||||
}
|
||||
} else if (config.shellSaveType.equalsIgnoreCase("bash")) {
|
||||
try {
|
||||
out = new FileOutputStream("worldedit-delchunks.sh");
|
||||
OutputStreamWriter writer = new OutputStreamWriter(out, "UTF-8");
|
||||
writer.write("#!/bin/bash\n");
|
||||
writer.write("echo This shell file was generated by WorldEdit.\n");
|
||||
writer.write("echo It contains a list of chunks that were in the selected region\n");
|
||||
writer.write("echo at the time that the /delchunks command was used. Run this file\n");
|
||||
writer.write("echo in order to delete the chunk files listed in this file.\n");
|
||||
writer.write("echo\n");
|
||||
writer.write("read -p \"Press any key to continue...\"\n");
|
||||
|
||||
for (Vector2D chunk : chunks) {
|
||||
String filename = LegacyChunkStore.getFilename(chunk);
|
||||
writer.write("echo " + filename + "\n");
|
||||
writer.write("rm \"world/" + filename + "\"\n");
|
||||
}
|
||||
|
||||
writer.write("echo Complete.\n");
|
||||
writer.write("read -p \"Press any key to continue...\"\n");
|
||||
writer.close();
|
||||
player.print("worldedit-delchunks.sh written. Run it when no one is near the region.");
|
||||
player.print("You will have to chmod it to be executable.");
|
||||
} catch (IOException e) {
|
||||
player.printError("Error occurred: " + e.getMessage());
|
||||
} finally {
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
player.printError("Shell script type must be configured: 'bat' or 'bash' expected.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,258 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.block.BlockReplace;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.annotation.Direction;
|
||||
import com.sk89q.worldedit.internal.annotation.Selection;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
|
||||
/**
|
||||
* Clipboard commands.
|
||||
*/
|
||||
public class ClipboardCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public ClipboardCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/copy" },
|
||||
flags = "em",
|
||||
desc = "Copy the selection to the clipboard",
|
||||
help = "Copy the selection to the clipboard\n" +
|
||||
"Flags:\n" +
|
||||
" -e controls whether entities are copied\n" +
|
||||
" -m sets a source mask so that excluded blocks become air\n" +
|
||||
"WARNING: Pasting entities cannot yet be undone!",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.copy")
|
||||
public void copy(Player player, LocalSession session, EditSession editSession,
|
||||
@Selection Region region, @Switch('e') boolean copyEntities,
|
||||
@Switch('m') Mask mask) throws WorldEditException {
|
||||
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
clipboard.setOrigin(session.getPlacementPosition(player));
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
|
||||
if (mask != null) {
|
||||
copy.setSourceMask(mask);
|
||||
}
|
||||
Operations.completeLegacy(copy);
|
||||
session.setClipboard(new ClipboardHolder(clipboard, editSession.getWorld().getWorldData()));
|
||||
|
||||
player.print(region.getArea() + " block(s) were copied.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/cut" },
|
||||
flags = "em",
|
||||
usage = "[leave-id]",
|
||||
desc = "Cut the selection to the clipboard",
|
||||
help = "Copy the selection to the clipboard\n" +
|
||||
"Flags:\n" +
|
||||
" -e controls whether entities are copied\n" +
|
||||
" -m sets a source mask so that excluded blocks become air\n" +
|
||||
"WARNING: Cutting and pasting entities cannot yet be undone!",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.cut")
|
||||
@Logging(REGION)
|
||||
public void cut(Player player, LocalSession session, EditSession editSession,
|
||||
@Selection Region region, @Optional("air") Pattern leavePattern, @Switch('e') boolean copyEntities,
|
||||
@Switch('m') Mask mask) throws WorldEditException {
|
||||
|
||||
BlockArrayClipboard clipboard = new BlockArrayClipboard(region);
|
||||
clipboard.setOrigin(session.getPlacementPosition(player));
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(editSession, region, clipboard, region.getMinimumPoint());
|
||||
copy.setSourceFunction(new BlockReplace(editSession, leavePattern));
|
||||
if (mask != null) {
|
||||
copy.setSourceMask(mask);
|
||||
}
|
||||
Operations.completeLegacy(copy);
|
||||
session.setClipboard(new ClipboardHolder(clipboard, editSession.getWorld().getWorldData()));
|
||||
|
||||
player.print(region.getArea() + " block(s) were copied.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/paste" },
|
||||
usage = "",
|
||||
flags = "sao",
|
||||
desc = "Paste the clipboard's contents",
|
||||
help =
|
||||
"Pastes the clipboard's contents.\n" +
|
||||
"Flags:\n" +
|
||||
" -a skips air blocks\n" +
|
||||
" -o pastes at the original position\n" +
|
||||
" -s selects the region after pasting",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.paste")
|
||||
@Logging(PLACEMENT)
|
||||
public void paste(Player player, LocalSession session, EditSession editSession,
|
||||
@Switch('a') boolean ignoreAirBlocks, @Switch('o') boolean atOrigin,
|
||||
@Switch('s') boolean selectPasted) throws WorldEditException {
|
||||
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
Region region = clipboard.getRegion();
|
||||
|
||||
Vector to = atOrigin ? clipboard.getOrigin() : session.getPlacementPosition(player);
|
||||
Operation operation = holder
|
||||
.createPaste(editSession, editSession.getWorld().getWorldData())
|
||||
.to(to)
|
||||
.ignoreAirBlocks(ignoreAirBlocks)
|
||||
.build();
|
||||
Operations.completeLegacy(operation);
|
||||
|
||||
if (selectPasted) {
|
||||
Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint()));
|
||||
RegionSelector selector = new CuboidRegionSelector(player.getWorld(), to, max);
|
||||
session.setRegionSelector(player.getWorld(), selector);
|
||||
selector.learnChanges();
|
||||
selector.explainRegionAdjust(player, session);
|
||||
}
|
||||
|
||||
player.print("The clipboard has been pasted at " + to);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/rotate" },
|
||||
usage = "<y-axis> [<x-axis>] [<z-axis>]",
|
||||
desc = "Rotate the contents of the clipboard",
|
||||
help = "Non-destructively rotate the contents of the clipboard.\n" +
|
||||
"Angles are provided in degrees and a positive angle will result in a clockwise rotation. " +
|
||||
"Multiple rotations can be stacked. Interpolation is not performed so angles should be a multiple of 90 degrees.\n"
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.rotate")
|
||||
public void rotate(Player player, LocalSession session, Double yRotate, @Optional Double xRotate, @Optional Double zRotate) throws WorldEditException {
|
||||
if ((yRotate != null && Math.abs(yRotate % 90) > 0.001) ||
|
||||
xRotate != null && Math.abs(xRotate % 90) > 0.001 ||
|
||||
zRotate != null && Math.abs(zRotate % 90) > 0.001) {
|
||||
player.printDebug("Note: Interpolation is not yet supported, so angles that are multiples of 90 is recommended.");
|
||||
}
|
||||
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
AffineTransform transform = new AffineTransform();
|
||||
transform = transform.rotateY(-(yRotate != null ? yRotate : 0));
|
||||
transform = transform.rotateX(-(xRotate != null ? xRotate : 0));
|
||||
transform = transform.rotateZ(-(zRotate != null ? zRotate : 0));
|
||||
holder.setTransform(holder.getTransform().combine(transform));
|
||||
player.print("The clipboard copy has been rotated.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/flip" },
|
||||
usage = "[<direction>]",
|
||||
desc = "Flip the contents of the clipboard",
|
||||
help =
|
||||
"Flips the contents of the clipboard across the point from which the copy was made.\n",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.flip")
|
||||
public void flip(Player player, LocalSession session, EditSession editSession,
|
||||
@Optional(Direction.AIM) @Direction Vector direction) throws WorldEditException {
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
AffineTransform transform = new AffineTransform();
|
||||
transform = transform.scale(direction.positive().multiply(-2).add(1, 1, 1));
|
||||
holder.setTransform(holder.getTransform().combine(transform));
|
||||
player.print("The clipboard copy has been flipped.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/load" },
|
||||
usage = "<filename>",
|
||||
desc = "Load a schematic into your clipboard",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@Deprecated
|
||||
@CommandPermissions("worldedit.clipboard.load")
|
||||
public void load(Actor actor) {
|
||||
actor.printError("This command is no longer used. See //schematic load.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/save" },
|
||||
usage = "<filename>",
|
||||
desc = "Save a schematic into your clipboard",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@Deprecated
|
||||
@CommandPermissions("worldedit.clipboard.save")
|
||||
public void save(Actor actor) {
|
||||
actor.printError("This command is no longer used. See //schematic save.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "clearclipboard" },
|
||||
usage = "",
|
||||
desc = "Clear your clipboard",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.clipboard.clear")
|
||||
public void clearClipboard(Player player, LocalSession session, EditSession editSession) throws WorldEditException {
|
||||
session.setClipboard(null);
|
||||
player.print("Clipboard cleared.");
|
||||
}
|
||||
}
|
@ -0,0 +1,143 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
|
||||
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import com.sk89q.worldedit.math.transform.CombinedTransform;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.registry.WorldData;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Helper class to 'bake' a transform into a clipboard.
|
||||
*
|
||||
* <p>This class needs a better name and may need to be made more generic.</p>
|
||||
*
|
||||
* @see Clipboard
|
||||
* @see Transform
|
||||
*/
|
||||
class FlattenedClipboardTransform {
|
||||
|
||||
private final Clipboard original;
|
||||
private final Transform transform;
|
||||
private final WorldData worldData;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param original the original clipboard
|
||||
* @param transform the transform
|
||||
* @param worldData the world data instance
|
||||
*/
|
||||
private FlattenedClipboardTransform(Clipboard original, Transform transform, WorldData worldData) {
|
||||
checkNotNull(original);
|
||||
checkNotNull(transform);
|
||||
checkNotNull(worldData);
|
||||
this.original = original;
|
||||
this.transform = transform;
|
||||
this.worldData = worldData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the transformed region.
|
||||
*
|
||||
* @return the transformed region
|
||||
*/
|
||||
public Region getTransformedRegion() {
|
||||
Region region = original.getRegion();
|
||||
Vector minimum = region.getMinimumPoint();
|
||||
Vector maximum = region.getMaximumPoint();
|
||||
|
||||
Transform transformAround =
|
||||
new CombinedTransform(
|
||||
new AffineTransform().translate(original.getOrigin().multiply(-1)),
|
||||
transform,
|
||||
new AffineTransform().translate(original.getOrigin()));
|
||||
|
||||
Vector[] corners = new Vector[] {
|
||||
minimum,
|
||||
maximum,
|
||||
minimum.setX(maximum.getX()),
|
||||
minimum.setY(maximum.getY()),
|
||||
minimum.setZ(maximum.getZ()),
|
||||
maximum.setX(minimum.getX()),
|
||||
maximum.setY(minimum.getY()),
|
||||
maximum.setZ(minimum.getZ()) };
|
||||
|
||||
for (int i = 0; i < corners.length; i++) {
|
||||
corners[i] = transformAround.apply(corners[i]);
|
||||
}
|
||||
|
||||
Vector newMinimum = corners[0];
|
||||
Vector newMaximum = corners[0];
|
||||
|
||||
for (int i = 1; i < corners.length; i++) {
|
||||
newMinimum = Vector.getMinimum(newMinimum, corners[i]);
|
||||
newMaximum = Vector.getMaximum(newMaximum, corners[i]);
|
||||
}
|
||||
|
||||
// After transformation, the points may not really sit on a block,
|
||||
// so we should expand the region for edge cases
|
||||
newMinimum = newMinimum.setX(Math.floor(newMinimum.getX()));
|
||||
newMinimum = newMinimum.setY(Math.floor(newMinimum.getY()));
|
||||
newMinimum = newMinimum.setZ(Math.floor(newMinimum.getZ()));
|
||||
|
||||
newMaximum = newMaximum.setX(Math.ceil(newMaximum.getX()));
|
||||
newMaximum = newMaximum.setY(Math.ceil(newMaximum.getY()));
|
||||
newMaximum = newMaximum.setZ(Math.ceil(newMaximum.getZ()));
|
||||
|
||||
return new CuboidRegion(newMinimum, newMaximum);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an operation to copy from the original clipboard to the given extent.
|
||||
*
|
||||
* @param target the target
|
||||
* @return the operation
|
||||
*/
|
||||
public Operation copyTo(Extent target) {
|
||||
BlockTransformExtent extent = new BlockTransformExtent(original, transform, worldData.getBlockRegistry());
|
||||
ForwardExtentCopy copy = new ForwardExtentCopy(extent, original.getRegion(), original.getOrigin(), target, original.getOrigin());
|
||||
copy.setTransform(transform);
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance to bake the transform with.
|
||||
*
|
||||
* @param original the original clipboard
|
||||
* @param transform the transform
|
||||
* @param worldData the world data instance
|
||||
* @return a builder
|
||||
*/
|
||||
public static FlattenedClipboardTransform transform(Clipboard original, Transform transform, WorldData worldData) {
|
||||
return new FlattenedClipboardTransform(original, transform, worldData);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,225 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* General WorldEdit commands.
|
||||
*/
|
||||
public class GeneralCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public GeneralCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/limit" },
|
||||
usage = "<limit>",
|
||||
desc = "Modify block change limit",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.limit")
|
||||
public void limit(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
boolean mayDisable = player.hasPermission("worldedit.limit.unrestricted");
|
||||
|
||||
int limit = Math.max(-1, args.getInteger(0));
|
||||
if (!mayDisable && config.maxChangeLimit > -1) {
|
||||
if (limit > config.maxChangeLimit) {
|
||||
player.printError("Your maximum allowable limit is " + config.maxChangeLimit + ".");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
session.setBlockChangeLimit(limit);
|
||||
|
||||
if (limit != -1) {
|
||||
player.print("Block change limit set to " + limit + ". (Use //limit -1 to go back to the default.)");
|
||||
} else {
|
||||
player.print("Block change limit set to " + limit + ".");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/fast" },
|
||||
usage = "[on|off]",
|
||||
desc = "Toggle fast mode",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.fast")
|
||||
public void fast(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
String newState = args.getString(0, null);
|
||||
if (session.hasFastMode()) {
|
||||
if ("on".equals(newState)) {
|
||||
player.printError("Fast mode already enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.setFastMode(false);
|
||||
player.print("Fast mode disabled.");
|
||||
} else {
|
||||
if ("off".equals(newState)) {
|
||||
player.printError("Fast mode already disabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.setFastMode(true);
|
||||
player.print("Fast mode enabled. Lighting in the affected chunks may be wrong and/or you may need to rejoin to see changes.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/gmask", "gmask" },
|
||||
usage = "[mask]",
|
||||
desc = "Set the global mask",
|
||||
min = 0,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.global-mask")
|
||||
public void gmask(Player player, LocalSession session, EditSession editSession, @Optional Mask mask) throws WorldEditException {
|
||||
if (mask == null) {
|
||||
session.setMask((Mask) null);
|
||||
player.print("Global mask disabled.");
|
||||
} else {
|
||||
session.setMask(mask);
|
||||
player.print("Global mask set.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/toggleplace", "toggleplace" },
|
||||
usage = "",
|
||||
desc = "Switch between your position and pos1 for placement",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
public void togglePlace(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
if (session.togglePlacementPosition()) {
|
||||
player.print("Now placing at pos #1.");
|
||||
} else {
|
||||
player.print("Now placing at the block you stand in.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/searchitem", "/l", "/search", "searchitem" },
|
||||
usage = "<query>",
|
||||
flags = "bi",
|
||||
desc = "Search for an item",
|
||||
help =
|
||||
"Searches for an item.\n" +
|
||||
"Flags:\n" +
|
||||
" -b only search for blocks\n" +
|
||||
" -i only search for items",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
public void searchItem(Actor actor, CommandContext args) throws WorldEditException {
|
||||
|
||||
String query = args.getString(0).trim().toLowerCase();
|
||||
boolean blocksOnly = args.hasFlag('b');
|
||||
boolean itemsOnly = args.hasFlag('i');
|
||||
|
||||
try {
|
||||
int id = Integer.parseInt(query);
|
||||
|
||||
ItemType type = ItemType.fromID(id);
|
||||
|
||||
if (type != null) {
|
||||
actor.print("#" + type.getID() + " (" + type.getName() + ")");
|
||||
} else {
|
||||
actor.printError("No item found by ID " + id);
|
||||
}
|
||||
|
||||
return;
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
|
||||
if (query.length() <= 2) {
|
||||
actor.printError("Enter a longer search string (len > 2).");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!blocksOnly && !itemsOnly) {
|
||||
actor.print("Searching for: " + query);
|
||||
} else if (blocksOnly && itemsOnly) {
|
||||
actor.printError("You cannot use both the 'b' and 'i' flags simultaneously.");
|
||||
return;
|
||||
} else if (blocksOnly) {
|
||||
actor.print("Searching for blocks: " + query);
|
||||
} else {
|
||||
actor.print("Searching for items: " + query);
|
||||
}
|
||||
|
||||
int found = 0;
|
||||
|
||||
for (ItemType type : ItemType.values()) {
|
||||
if (found >= 15) {
|
||||
actor.print("Too many results!");
|
||||
break;
|
||||
}
|
||||
|
||||
if (blocksOnly && type.getID() > 255) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itemsOnly && type.getID() <= 255) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (String alias : type.getAliases()) {
|
||||
if (alias.contains(query)) {
|
||||
actor.print("#" + type.getID() + " (" + type.getName() + ")");
|
||||
++found;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found == 0) {
|
||||
actor.printError("No items found.");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,382 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.pattern.Patterns;
|
||||
import com.sk89q.worldedit.internal.annotation.Selection;
|
||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||
import com.sk89q.worldedit.util.command.binding.Range;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.binding.Text;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
|
||||
|
||||
/**
|
||||
* Commands for the generation of shapes and other objects.
|
||||
*/
|
||||
public class GenerationCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public GenerationCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hcyl" },
|
||||
usage = "<pattern> <radius>[,<radius>] [height]",
|
||||
desc = "Generates a hollow cylinder.",
|
||||
help =
|
||||
"Generates a hollow cylinder.\n" +
|
||||
"By specifying 2 radii, separated by a comma,\n" +
|
||||
"you can generate elliptical cylinders.\n" +
|
||||
"The 1st radius is north/south, the 2nd radius is east/west.",
|
||||
min = 2,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.cylinder")
|
||||
@Logging(PLACEMENT)
|
||||
public void hcyl(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("1") int height) throws WorldEditException {
|
||||
cyl(player, session, editSession, pattern, radiusString, height, true);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/cyl" },
|
||||
usage = "<block> <radius>[,<radius>] [height]",
|
||||
flags = "h",
|
||||
desc = "Generates a cylinder.",
|
||||
help =
|
||||
"Generates a cylinder.\n" +
|
||||
"By specifying 2 radii, separated by a comma,\n" +
|
||||
"you can generate elliptical cylinders.\n" +
|
||||
"The 1st radius is north/south, the 2nd radius is east/west.",
|
||||
min = 2,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.cylinder")
|
||||
@Logging(PLACEMENT)
|
||||
public void cyl(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("1") int height, @Switch('h') boolean hollow) throws WorldEditException {
|
||||
String[] radii = radiusString.split(",");
|
||||
final double radiusX, radiusZ;
|
||||
switch (radii.length) {
|
||||
case 1:
|
||||
radiusX = radiusZ = Math.max(1, Double.parseDouble(radii[0]));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
radiusX = Math.max(1, Double.parseDouble(radii[0]));
|
||||
radiusZ = Math.max(1, Double.parseDouble(radii[1]));
|
||||
break;
|
||||
|
||||
default:
|
||||
player.printError("You must either specify 1 or 2 radius values.");
|
||||
return;
|
||||
}
|
||||
|
||||
worldEdit.checkMaxRadius(radiusX);
|
||||
worldEdit.checkMaxRadius(radiusZ);
|
||||
worldEdit.checkMaxRadius(height);
|
||||
|
||||
Vector pos = session.getPlacementPosition(player);
|
||||
int affected = editSession.makeCylinder(pos, Patterns.wrap(pattern), radiusX, radiusZ, height, !hollow);
|
||||
player.print(affected + " block(s) have been created.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hsphere" },
|
||||
usage = "<block> <radius>[,<radius>,<radius>] [raised?]",
|
||||
desc = "Generates a hollow sphere.",
|
||||
help =
|
||||
"Generates a hollow sphere.\n" +
|
||||
"By specifying 3 radii, separated by commas,\n" +
|
||||
"you can generate an ellipsoid. The order of the ellipsoid radii\n" +
|
||||
"is north/south, up/down, east/west.",
|
||||
min = 2,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.sphere")
|
||||
@Logging(PLACEMENT)
|
||||
public void hsphere(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("false") boolean raised) throws WorldEditException {
|
||||
sphere(player, session, editSession, pattern, radiusString, raised, true);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/sphere" },
|
||||
usage = "<block> <radius>[,<radius>,<radius>] [raised?]",
|
||||
flags = "h",
|
||||
desc = "Generates a filled sphere.",
|
||||
help =
|
||||
"Generates a filled sphere.\n" +
|
||||
"By specifying 3 radii, separated by commas,\n" +
|
||||
"you can generate an ellipsoid. The order of the ellipsoid radii\n" +
|
||||
"is north/south, up/down, east/west.",
|
||||
min = 2,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.sphere")
|
||||
@Logging(PLACEMENT)
|
||||
public void sphere(Player player, LocalSession session, EditSession editSession, Pattern pattern, String radiusString, @Optional("false") boolean raised, @Switch('h') boolean hollow) throws WorldEditException {
|
||||
String[] radii = radiusString.split(",");
|
||||
final double radiusX, radiusY, radiusZ;
|
||||
switch (radii.length) {
|
||||
case 1:
|
||||
radiusX = radiusY = radiusZ = Math.max(1, Double.parseDouble(radii[0]));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
radiusX = Math.max(1, Double.parseDouble(radii[0]));
|
||||
radiusY = Math.max(1, Double.parseDouble(radii[1]));
|
||||
radiusZ = Math.max(1, Double.parseDouble(radii[2]));
|
||||
break;
|
||||
|
||||
default:
|
||||
player.printError("You must either specify 1 or 3 radius values.");
|
||||
return;
|
||||
}
|
||||
|
||||
worldEdit.checkMaxRadius(radiusX);
|
||||
worldEdit.checkMaxRadius(radiusY);
|
||||
worldEdit.checkMaxRadius(radiusZ);
|
||||
|
||||
Vector pos = session.getPlacementPosition(player);
|
||||
if (raised) {
|
||||
pos = pos.add(0, radiusY, 0);
|
||||
}
|
||||
|
||||
int affected = editSession.makeSphere(pos, Patterns.wrap(pattern), radiusX, radiusY, radiusZ, !hollow);
|
||||
player.findFreePosition();
|
||||
player.print(affected + " block(s) have been created.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "forestgen" },
|
||||
usage = "[size] [type] [density]",
|
||||
desc = "Generate a forest",
|
||||
min = 0,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.forest")
|
||||
@Logging(POSITION)
|
||||
@SuppressWarnings("deprecation")
|
||||
public void forestGen(Player player, LocalSession session, EditSession editSession, @Optional("10") int size, @Optional("tree") TreeType type, @Optional("5") double density) throws WorldEditException {
|
||||
density = density / 100;
|
||||
int affected = editSession.makeForest(session.getPlacementPosition(player), size, density, new TreeGenerator(type));
|
||||
player.print(affected + " trees created.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "pumpkins" },
|
||||
usage = "[size]",
|
||||
desc = "Generate pumpkin patches",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.pumpkins")
|
||||
@Logging(POSITION)
|
||||
public void pumpkins(Player player, LocalSession session, EditSession editSession, @Optional("10") int apothem) throws WorldEditException {
|
||||
int affected = editSession.makePumpkinPatches(session.getPlacementPosition(player), apothem);
|
||||
player.print(affected + " pumpkin patches created.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hpyramid" },
|
||||
usage = "<block> <size>",
|
||||
desc = "Generate a hollow pyramid",
|
||||
min = 2,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.pyramid")
|
||||
@Logging(PLACEMENT)
|
||||
public void hollowPyramid(Player player, LocalSession session, EditSession editSession, Pattern pattern, @Range(min = 1) int size) throws WorldEditException {
|
||||
pyramid(player, session, editSession, pattern, size, true);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/pyramid" },
|
||||
usage = "<block> <size>",
|
||||
flags = "h",
|
||||
desc = "Generate a filled pyramid",
|
||||
min = 2,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.pyramid")
|
||||
@Logging(PLACEMENT)
|
||||
public void pyramid(Player player, LocalSession session, EditSession editSession, Pattern pattern, @Range(min = 1) int size, @Switch('h') boolean hollow) throws WorldEditException {
|
||||
Vector pos = session.getPlacementPosition(player);
|
||||
worldEdit.checkMaxRadius(size);
|
||||
int affected = editSession.makePyramid(pos, Patterns.wrap(pattern), size, !hollow);
|
||||
player.findFreePosition();
|
||||
player.print(affected + " block(s) have been created.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/generate", "/gen", "/g" },
|
||||
usage = "<block> <expression>",
|
||||
desc = "Generates a shape according to a formula.",
|
||||
help =
|
||||
"Generates a shape according to a formula that is expected to\n" +
|
||||
"return positive numbers (true) if the point is inside the shape\n" +
|
||||
"Optionally set type/data to the desired block.\n" +
|
||||
"Flags:\n" +
|
||||
" -h to generate a hollow shape\n" +
|
||||
" -r to use raw minecraft coordinates\n" +
|
||||
" -o is like -r, except offset from placement.\n" +
|
||||
" -c is like -r, except offset selection center.\n" +
|
||||
"If neither -r nor -o is given, the selection is mapped to -1..1\n" +
|
||||
"See also tinyurl.com/wesyntax.",
|
||||
flags = "hroc",
|
||||
min = 2,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.generation.shape")
|
||||
@Logging(ALL)
|
||||
public void generate(Player player, LocalSession session, EditSession editSession,
|
||||
@Selection Region region,
|
||||
Pattern pattern,
|
||||
@Text String expression,
|
||||
@Switch('h') boolean hollow,
|
||||
@Switch('r') boolean useRawCoords,
|
||||
@Switch('o') boolean offset,
|
||||
@Switch('c') boolean offsetCenter) throws WorldEditException {
|
||||
|
||||
final Vector zero;
|
||||
Vector unit;
|
||||
|
||||
if (useRawCoords) {
|
||||
zero = Vector.ZERO;
|
||||
unit = Vector.ONE;
|
||||
} else if (offset) {
|
||||
zero = session.getPlacementPosition(player);
|
||||
unit = Vector.ONE;
|
||||
} else if (offsetCenter) {
|
||||
final Vector min = region.getMinimumPoint();
|
||||
final Vector max = region.getMaximumPoint();
|
||||
|
||||
zero = max.add(min).multiply(0.5);
|
||||
unit = Vector.ONE;
|
||||
} else {
|
||||
final Vector min = region.getMinimumPoint();
|
||||
final Vector max = region.getMaximumPoint();
|
||||
|
||||
zero = max.add(min).multiply(0.5);
|
||||
unit = max.subtract(zero);
|
||||
|
||||
if (unit.getX() == 0) unit = unit.setX(1.0);
|
||||
if (unit.getY() == 0) unit = unit.setY(1.0);
|
||||
if (unit.getZ() == 0) unit = unit.setZ(1.0);
|
||||
}
|
||||
|
||||
try {
|
||||
final int affected = editSession.makeShape(region, zero, unit, Patterns.wrap(pattern), expression, hollow);
|
||||
player.findFreePosition();
|
||||
player.print(affected + " block(s) have been created.");
|
||||
} catch (ExpressionException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/generatebiome", "/genbiome", "/gb" },
|
||||
usage = "<block> <expression>",
|
||||
desc = "Sets biome according to a formula.",
|
||||
help =
|
||||
"Generates a shape according to a formula that is expected to\n" +
|
||||
"return positive numbers (true) if the point is inside the shape\n" +
|
||||
"Optionally set type/data to the desired block.\n" +
|
||||
"Flags:\n" +
|
||||
" -h to generate a hollow shape\n" +
|
||||
" -r to use raw minecraft coordinates\n" +
|
||||
" -o is like -r, except offset from placement.\n" +
|
||||
" -c is like -r, except offset selection center.\n" +
|
||||
"If neither -r nor -o is given, the selection is mapped to -1..1\n" +
|
||||
"See also tinyurl.com/wesyntax.",
|
||||
flags = "hroc",
|
||||
min = 2,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions({"worldedit.generation.shape", "worldedit.biome.set"})
|
||||
@Logging(ALL)
|
||||
public void generateBiome(Player player, LocalSession session, EditSession editSession,
|
||||
@Selection Region region,
|
||||
BaseBiome target,
|
||||
@Text String expression,
|
||||
@Switch('h') boolean hollow,
|
||||
@Switch('r') boolean useRawCoords,
|
||||
@Switch('o') boolean offset,
|
||||
@Switch('c') boolean offsetCenter) throws WorldEditException {
|
||||
final Vector zero;
|
||||
Vector unit;
|
||||
|
||||
if (useRawCoords) {
|
||||
zero = Vector.ZERO;
|
||||
unit = Vector.ONE;
|
||||
} else if (offset) {
|
||||
zero = session.getPlacementPosition(player);
|
||||
unit = Vector.ONE;
|
||||
} else if (offsetCenter) {
|
||||
final Vector min = region.getMinimumPoint();
|
||||
final Vector max = region.getMaximumPoint();
|
||||
|
||||
zero = max.add(min).multiply(0.5);
|
||||
unit = Vector.ONE;
|
||||
} else {
|
||||
final Vector min = region.getMinimumPoint();
|
||||
final Vector max = region.getMaximumPoint();
|
||||
|
||||
zero = max.add(min).multiply(0.5);
|
||||
unit = max.subtract(zero);
|
||||
|
||||
if (unit.getX() == 0) unit = unit.setX(1.0);
|
||||
if (unit.getY() == 0) unit = unit.setY(1.0);
|
||||
if (unit.getZ() == 0) unit = unit.setZ(1.0);
|
||||
}
|
||||
|
||||
try {
|
||||
final int affected = editSession.makeBiomeShape(region, zero, unit, target, expression, hollow);
|
||||
player.findFreePosition();
|
||||
player.print("" + affected + " columns affected.");
|
||||
} catch (ExpressionException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Commands to undo, redo, and clear history.
|
||||
*/
|
||||
public class HistoryCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public HistoryCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/undo", "undo" },
|
||||
usage = "[times] [player]",
|
||||
desc = "Undoes the last action",
|
||||
min = 0,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.history.undo")
|
||||
public void undo(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
int times = Math.max(1, args.getInteger(0, 1));
|
||||
for (int i = 0; i < times; ++i) {
|
||||
EditSession undone;
|
||||
if (args.argsLength() < 2) {
|
||||
undone = session.undo(session.getBlockBag(player), player);
|
||||
} else {
|
||||
player.checkPermission("worldedit.history.undo.other");
|
||||
LocalSession sess = worldEdit.getSession(args.getString(1));
|
||||
if (sess == null) {
|
||||
player.printError("Unable to find session for " + args.getString(1));
|
||||
break;
|
||||
}
|
||||
undone = sess.undo(session.getBlockBag(player), player);
|
||||
}
|
||||
if (undone != null) {
|
||||
player.print("Undo successful.");
|
||||
worldEdit.flushBlockBag(player, undone);
|
||||
} else {
|
||||
player.printError("Nothing left to undo.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/redo", "redo" },
|
||||
usage = "[times] [player]",
|
||||
desc = "Redoes the last action (from history)",
|
||||
min = 0,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.history.redo")
|
||||
public void redo(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
int times = Math.max(1, args.getInteger(0, 1));
|
||||
|
||||
for (int i = 0; i < times; ++i) {
|
||||
EditSession redone;
|
||||
if (args.argsLength() < 2) {
|
||||
redone = session.redo(session.getBlockBag(player), player);
|
||||
} else {
|
||||
player.checkPermission("worldedit.history.redo.other");
|
||||
LocalSession sess = worldEdit.getSession(args.getString(1));
|
||||
if (sess == null) {
|
||||
player.printError("Unable to find session for " + args.getString(1));
|
||||
break;
|
||||
}
|
||||
redone = sess.redo(session.getBlockBag(player), player);
|
||||
}
|
||||
if (redone != null) {
|
||||
player.print("Redo successful.");
|
||||
worldEdit.flushBlockBag(player, redone);
|
||||
} else {
|
||||
player.printError("Nothing left to redo.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/clearhistory", "clearhistory" },
|
||||
usage = "",
|
||||
desc = "Clear your history",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.history.clear")
|
||||
public void clearHistory(Player player, LocalSession session, EditSession editSession) throws WorldEditException {
|
||||
session.clearHistory();
|
||||
player.print("History cleared.");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
|
||||
public class InsufficientArgumentsException extends WorldEditException {
|
||||
|
||||
public InsufficientArgumentsException(String error) {
|
||||
super(error);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
|
||||
|
||||
/**
|
||||
* Commands for moving the player around.
|
||||
*/
|
||||
public class NavigationCommands {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public NavigationCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "unstuck", "!" },
|
||||
usage = "",
|
||||
desc = "Escape from being stuck inside a block",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.unstuck")
|
||||
public void unstuck(Player player) throws WorldEditException {
|
||||
player.print("There you go!");
|
||||
player.findFreePosition();
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "ascend", "asc" },
|
||||
usage = "[# of levels]",
|
||||
desc = "Go up a floor",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.ascend")
|
||||
public void ascend(Player player, @Optional("1") int levelsToAscend) throws WorldEditException {
|
||||
int ascentLevels = 1;
|
||||
while (player.ascendLevel() && levelsToAscend != ascentLevels) {
|
||||
++ascentLevels;
|
||||
}
|
||||
if (ascentLevels == 0) {
|
||||
player.printError("No free spot above you found.");
|
||||
} else {
|
||||
player.print((ascentLevels != 1) ? "Ascended " + Integer.toString(ascentLevels) + " levels." : "Ascended a level.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "descend", "desc" },
|
||||
usage = "[# of floors]",
|
||||
desc = "Go down a floor",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.descend")
|
||||
public void descend(Player player, @Optional("1") int levelsToDescend) throws WorldEditException {
|
||||
int descentLevels = 1;
|
||||
while (player.descendLevel() && levelsToDescend != descentLevels) {
|
||||
++descentLevels;
|
||||
}
|
||||
if (descentLevels == 0) {
|
||||
player.printError("No free spot above you found.");
|
||||
} else {
|
||||
player.print((descentLevels != 1) ? "Descended " + Integer.toString(descentLevels) + " levels." : "Descended a level.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "ceil" },
|
||||
usage = "[clearance]",
|
||||
desc = "Go to the celing",
|
||||
flags = "fg",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.ceiling")
|
||||
@Logging(POSITION)
|
||||
public void ceiling(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
final int clearance = args.argsLength() > 0 ?
|
||||
Math.max(0, args.getInteger(0)) : 0;
|
||||
|
||||
final boolean alwaysGlass = getAlwaysGlass(args);
|
||||
if (player.ascendToCeiling(clearance, alwaysGlass)) {
|
||||
player.print("Whoosh!");
|
||||
} else {
|
||||
player.printError("No free spot above you found.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "thru" },
|
||||
usage = "",
|
||||
desc = "Passthrough walls",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.thru.command")
|
||||
public void thru(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
if (player.passThroughForwardWall(6)) {
|
||||
player.print("Whoosh!");
|
||||
} else {
|
||||
player.printError("No free spot ahead of you found.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "jumpto", "j" },
|
||||
usage = "",
|
||||
desc = "Teleport to a location",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.jumpto.command")
|
||||
public void jumpTo(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
WorldVector pos = player.getSolidBlockTrace(300);
|
||||
if (pos != null) {
|
||||
player.findFreePosition(pos);
|
||||
player.print("Poof!");
|
||||
} else {
|
||||
player.printError("No block in sight!");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "up" },
|
||||
usage = "<block>",
|
||||
desc = "Go upwards some distance",
|
||||
flags = "fg",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.navigation.up")
|
||||
@Logging(POSITION)
|
||||
public void up(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
final int distance = args.getInteger(0);
|
||||
|
||||
final boolean alwaysGlass = getAlwaysGlass(args);
|
||||
if (player.ascendUpwards(distance, alwaysGlass)) {
|
||||
player.print("Whoosh!");
|
||||
} else {
|
||||
player.printError("You would hit something above you.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function for /up and /ceil.
|
||||
*
|
||||
* @param args The {@link CommandContext} to extract the flags from.
|
||||
* @return true, if glass should always be put under the player
|
||||
*/
|
||||
private boolean getAlwaysGlass(CommandContext args) {
|
||||
final LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
final boolean forceFlight = args.hasFlag('f');
|
||||
final boolean forceGlass = args.hasFlag('g');
|
||||
|
||||
return forceGlass || (config.navigationUseGlass && !forceFlight);
|
||||
}
|
||||
}
|
@ -0,0 +1,484 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.GroundFunction;
|
||||
import com.sk89q.worldedit.function.generator.FloraGenerator;
|
||||
import com.sk89q.worldedit.function.generator.ForestGenerator;
|
||||
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.NoiseFilter2D;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.pattern.Patterns;
|
||||
import com.sk89q.worldedit.function.visitor.LayerVisitor;
|
||||
import com.sk89q.worldedit.internal.annotation.Direction;
|
||||
import com.sk89q.worldedit.internal.annotation.Selection;
|
||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||
import com.sk89q.worldedit.math.convolution.GaussianKernel;
|
||||
import com.sk89q.worldedit.math.convolution.HeightMap;
|
||||
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
|
||||
import com.sk89q.worldedit.math.noise.RandomNoise;
|
||||
import com.sk89q.worldedit.regions.ConvexPolyhedralRegion;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
|
||||
import com.sk89q.worldedit.util.command.binding.Range;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.binding.Text;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.*;
|
||||
import static com.sk89q.worldedit.regions.Regions.*;
|
||||
|
||||
/**
|
||||
* Commands that operate on regions.
|
||||
*/
|
||||
public class RegionCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public RegionCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/set" },
|
||||
usage = "<block>",
|
||||
desc = "Set all the blocks inside the selection to a block",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.region.set")
|
||||
@Logging(REGION)
|
||||
public void set(Player player, LocalSession session, EditSession editSession, Pattern pattern) throws WorldEditException {
|
||||
int affected = editSession.setBlocks(session.getSelection(player.getWorld()), Patterns.wrap(pattern));
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/line" },
|
||||
usage = "<block> [thickness]",
|
||||
desc = "Draws a line segment between cuboid selection corners",
|
||||
help =
|
||||
"Draws a line segment between cuboid selection corners.\n" +
|
||||
"Can only be used with cuboid selections.\n" +
|
||||
"Flags:\n" +
|
||||
" -h generates only a shell",
|
||||
flags = "h",
|
||||
min = 1,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.region.line")
|
||||
@Logging(REGION)
|
||||
public void line(Player player, EditSession editSession,
|
||||
@Selection Region region,
|
||||
Pattern pattern,
|
||||
@Optional("0") @Range(min = 0) int thickness,
|
||||
@Switch('h') boolean shell) throws WorldEditException {
|
||||
|
||||
if (!(region instanceof CuboidRegion)) {
|
||||
player.printError("//line only works with cuboid selections");
|
||||
return;
|
||||
}
|
||||
|
||||
CuboidRegion cuboidregion = (CuboidRegion) region;
|
||||
Vector pos1 = cuboidregion.getPos1();
|
||||
Vector pos2 = cuboidregion.getPos2();
|
||||
int blocksChanged = editSession.drawLine(Patterns.wrap(pattern), pos1, pos2, thickness, !shell);
|
||||
|
||||
player.print(blocksChanged + " block(s) have been changed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/curve" },
|
||||
usage = "<block> [thickness]",
|
||||
desc = "Draws a spline through selected points",
|
||||
help =
|
||||
"Draws a spline through selected points.\n" +
|
||||
"Can only be used with convex polyhedral selections.\n" +
|
||||
"Flags:\n" +
|
||||
" -h generates only a shell",
|
||||
flags = "h",
|
||||
min = 1,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.region.curve")
|
||||
@Logging(REGION)
|
||||
public void curve(Player player, EditSession editSession,
|
||||
@Selection Region region,
|
||||
Pattern pattern,
|
||||
@Optional("0") @Range(min = 0) int thickness,
|
||||
@Switch('h') boolean shell) throws WorldEditException {
|
||||
if (!(region instanceof ConvexPolyhedralRegion)) {
|
||||
player.printError("//line only works with convex polyhedral selections");
|
||||
return;
|
||||
}
|
||||
|
||||
ConvexPolyhedralRegion cpregion = (ConvexPolyhedralRegion) region;
|
||||
List<Vector> vectors = new ArrayList<Vector>(cpregion.getVertices());
|
||||
|
||||
int blocksChanged = editSession.drawSpline(Patterns.wrap(pattern), vectors, 0, 0, 0, 10, thickness, !shell);
|
||||
|
||||
player.print(blocksChanged + " block(s) have been changed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/replace", "/re", "/rep" },
|
||||
usage = "[from-block] <to-block>",
|
||||
desc = "Replace all blocks in the selection with another",
|
||||
flags = "f",
|
||||
min = 1,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.region.replace")
|
||||
@Logging(REGION)
|
||||
public void replace(Player player, EditSession editSession, @Selection Region region, @Optional Mask from, Pattern to) throws WorldEditException {
|
||||
if (from == null) {
|
||||
from = new ExistingBlockMask(editSession);
|
||||
}
|
||||
int affected = editSession.replaceBlocks(region, from, Patterns.wrap(to));
|
||||
player.print(affected + " block(s) have been replaced.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/overlay" },
|
||||
usage = "<block>",
|
||||
desc = "Set a block on top of blocks in the region",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.region.overlay")
|
||||
@Logging(REGION)
|
||||
public void overlay(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
|
||||
int affected = editSession.overlayCuboidBlocks(region, Patterns.wrap(pattern));
|
||||
player.print(affected + " block(s) have been overlaid.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/center", "/middle" },
|
||||
usage = "<block>",
|
||||
desc = "Set the center block(s)",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.region.center")
|
||||
public void center(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
|
||||
int affected = editSession.center(region, Patterns.wrap(pattern));
|
||||
player.print("Center set ("+ affected + " blocks changed)");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/naturalize" },
|
||||
usage = "",
|
||||
desc = "3 layers of dirt on top then rock below",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.region.naturalize")
|
||||
@Logging(REGION)
|
||||
public void naturalize(Player player, EditSession editSession, @Selection Region region) throws WorldEditException {
|
||||
int affected = editSession.naturalizeCuboidBlocks(region);
|
||||
player.print(affected + " block(s) have been made to look more natural.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/walls" },
|
||||
usage = "<block>",
|
||||
desc = "Build the four sides of the selection",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.region.walls")
|
||||
@Logging(REGION)
|
||||
public void walls(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
|
||||
int affected = editSession.makeCuboidWalls(region, Patterns.wrap(pattern));
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/faces", "/outline" },
|
||||
usage = "<block>",
|
||||
desc = "Build the walls, ceiling, and floor of a selection",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.region.faces")
|
||||
@Logging(REGION)
|
||||
public void faces(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
|
||||
int affected = editSession.makeCuboidFaces(region, Patterns.wrap(pattern));
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/smooth" },
|
||||
usage = "[iterations]",
|
||||
flags = "n",
|
||||
desc = "Smooth the elevation in the selection",
|
||||
help =
|
||||
"Smooths the elevation in the selection.\n" +
|
||||
"The -n flag makes it only consider naturally occuring blocks.",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.region.smooth")
|
||||
@Logging(REGION)
|
||||
public void smooth(Player player, EditSession editSession, @Selection Region region, @Optional("1") int iterations, @Switch('n') boolean affectNatural) throws WorldEditException {
|
||||
HeightMap heightMap = new HeightMap(editSession, region, affectNatural);
|
||||
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
|
||||
int affected = heightMap.applyFilter(filter, iterations);
|
||||
player.print("Terrain's height map smoothed. " + affected + " block(s) changed.");
|
||||
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/move" },
|
||||
usage = "[count] [direction] [leave-id]",
|
||||
flags = "s",
|
||||
desc = "Move the contents of the selection",
|
||||
help =
|
||||
"Moves the contents of the selection.\n" +
|
||||
"The -s flag shifts the selection to the target location.\n" +
|
||||
"Optionally fills the old location with <leave-id>.",
|
||||
min = 0,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.region.move")
|
||||
@Logging(ORIENTATION_REGION)
|
||||
public void move(Player player, EditSession editSession, LocalSession session,
|
||||
@Selection Region region,
|
||||
@Optional("1") @Range(min = 1) int count,
|
||||
@Optional(Direction.AIM) @Direction Vector direction,
|
||||
@Optional("air") BaseBlock replace,
|
||||
@Switch('s') boolean moveSelection) throws WorldEditException {
|
||||
|
||||
int affected = editSession.moveRegion(region, direction, count, true, replace);
|
||||
|
||||
if (moveSelection) {
|
||||
try {
|
||||
region.shift(direction.multiply(count));
|
||||
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
|
||||
} catch (RegionOperationException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
player.print(affected + " blocks moved.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/stack" },
|
||||
usage = "[count] [direction]",
|
||||
flags = "sa",
|
||||
desc = "Repeat the contents of the selection",
|
||||
help =
|
||||
"Repeats the contents of the selection.\n" +
|
||||
"Flags:\n" +
|
||||
" -s shifts the selection to the last stacked copy\n" +
|
||||
" -a skips air blocks",
|
||||
min = 0,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.region.stack")
|
||||
@Logging(ORIENTATION_REGION)
|
||||
public void stack(Player player, EditSession editSession, LocalSession session,
|
||||
@Selection Region region,
|
||||
@Optional("1") @Range(min = 1) int count,
|
||||
@Optional(Direction.AIM) @Direction Vector direction,
|
||||
@Switch('s') boolean moveSelection,
|
||||
@Switch('a') boolean ignoreAirBlocks) throws WorldEditException {
|
||||
int affected = editSession.stackCuboidRegion(region, direction, count, !ignoreAirBlocks);
|
||||
|
||||
if (moveSelection) {
|
||||
try {
|
||||
final Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint());
|
||||
|
||||
final Vector shiftVector = direction.multiply(count * (Math.abs(direction.dot(size)) + 1));
|
||||
region.shift(shiftVector);
|
||||
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
|
||||
} catch (RegionOperationException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
player.print(affected + " blocks changed. Undo with //undo");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/regen" },
|
||||
usage = "",
|
||||
desc = "Regenerates the contents of the selection",
|
||||
help =
|
||||
"Regenerates the contents of the current selection.\n" +
|
||||
"This command might affect things outside the selection,\n" +
|
||||
"if they are within the same chunk.",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.regen")
|
||||
@Logging(REGION)
|
||||
public void regenerateChunk(Player player, LocalSession session, EditSession editSession, @Selection Region region) throws WorldEditException {
|
||||
Mask mask = session.getMask();
|
||||
try {
|
||||
session.setMask((Mask) null);
|
||||
player.getWorld().regenerate(region, editSession);
|
||||
} finally {
|
||||
session.setMask(mask);
|
||||
}
|
||||
player.print("Region regenerated.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/deform" },
|
||||
usage = "<expression>",
|
||||
desc = "Deforms a selected region with an expression",
|
||||
help =
|
||||
"Deforms a selected region with an expression\n" +
|
||||
"The expression is executed for each block and is expected\n" +
|
||||
"to modify the variables x, y and z to point to a new block\n" +
|
||||
"to fetch. See also tinyurl.com/wesyntax.",
|
||||
flags = "ro",
|
||||
min = 1,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.region.deform")
|
||||
@Logging(ALL)
|
||||
public void deform(Player player, LocalSession session, EditSession editSession,
|
||||
@Selection Region region,
|
||||
@Text String expression,
|
||||
@Switch('r') boolean useRawCoords,
|
||||
@Switch('o') boolean offset) throws WorldEditException {
|
||||
final Vector zero;
|
||||
Vector unit;
|
||||
|
||||
if (useRawCoords) {
|
||||
zero = Vector.ZERO;
|
||||
unit = Vector.ONE;
|
||||
} else if (offset) {
|
||||
zero = session.getPlacementPosition(player);
|
||||
unit = Vector.ONE;
|
||||
} else {
|
||||
final Vector min = region.getMinimumPoint();
|
||||
final Vector max = region.getMaximumPoint();
|
||||
|
||||
zero = max.add(min).multiply(0.5);
|
||||
unit = max.subtract(zero);
|
||||
|
||||
if (unit.getX() == 0) unit = unit.setX(1.0);
|
||||
if (unit.getY() == 0) unit = unit.setY(1.0);
|
||||
if (unit.getZ() == 0) unit = unit.setZ(1.0);
|
||||
}
|
||||
|
||||
try {
|
||||
final int affected = editSession.deformRegion(region, zero, unit, expression);
|
||||
player.findFreePosition();
|
||||
player.print(affected + " block(s) have been deformed.");
|
||||
} catch (ExpressionException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hollow" },
|
||||
usage = "[<thickness>[ <block>]]",
|
||||
desc = "Hollows out the object contained in this selection",
|
||||
help =
|
||||
"Hollows out the object contained in this selection.\n" +
|
||||
"Optionally fills the hollowed out part with the given block.\n" +
|
||||
"Thickness is measured in manhattan distance.",
|
||||
min = 0,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.region.hollow")
|
||||
@Logging(REGION)
|
||||
public void hollow(Player player, EditSession editSession,
|
||||
@Selection Region region,
|
||||
@Optional("0") @Range(min = 0) int thickness,
|
||||
@Optional("air") Pattern pattern) throws WorldEditException {
|
||||
|
||||
int affected = editSession.hollowOutRegion(region, thickness, Patterns.wrap(pattern));
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/forest" },
|
||||
usage = "[type] [density]",
|
||||
desc = "Make a forest within the region",
|
||||
min = 0,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.region.forest")
|
||||
@Logging(REGION)
|
||||
public void forest(Player player, EditSession editSession, @Selection Region region, @Optional("tree") TreeType type,
|
||||
@Optional("5") @Range(min = 0, max = 100) double density) throws WorldEditException {
|
||||
density = density / 100;
|
||||
ForestGenerator generator = new ForestGenerator(editSession, new TreeGenerator(type));
|
||||
GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator);
|
||||
LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
|
||||
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
|
||||
Operations.completeLegacy(visitor);
|
||||
|
||||
player.print(ground.getAffected() + " trees created.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/flora" },
|
||||
usage = "[density]",
|
||||
desc = "Make flora within the region",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.region.flora")
|
||||
@Logging(REGION)
|
||||
public void flora(Player player, EditSession editSession, @Selection Region region, @Optional("10") @Range(min = 0, max = 100) double density) throws WorldEditException {
|
||||
density = density / 100;
|
||||
FloraGenerator generator = new FloraGenerator(editSession);
|
||||
GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator);
|
||||
LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
|
||||
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
|
||||
Operations.completeLegacy(visitor);
|
||||
|
||||
player.print(ground.getAffected() + " flora created.");
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,313 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.util.io.file.FilenameException;
|
||||
import com.sk89q.worldedit.util.io.file.FilenameResolutionException;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardReader;
|
||||
import com.sk89q.worldedit.extent.clipboard.io.ClipboardWriter;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.io.Closer;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import com.sk89q.worldedit.world.registry.WorldData;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Commands that work with schematic files.
|
||||
*/
|
||||
public class SchematicCommands {
|
||||
|
||||
private static final Logger log = Logger.getLogger(SchematicCommands.class.getCanonicalName());
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public SchematicCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "load" },
|
||||
usage = "[<format>] <filename>",
|
||||
desc = "Load a schematic into your clipboard"
|
||||
)
|
||||
@Deprecated
|
||||
@CommandPermissions({ "worldedit.clipboard.load", "worldedit.schematic.load" })
|
||||
public void load(Player player, LocalSession session, @Optional("schematic") String formatName, String filename) throws FilenameException {
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
|
||||
File f = worldEdit.getSafeOpenFile(player, dir, filename, "schematic", "schematic");
|
||||
|
||||
if (!f.exists()) {
|
||||
player.printError("Schematic " + filename + " does not exist!");
|
||||
return;
|
||||
}
|
||||
|
||||
ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
|
||||
if (format == null) {
|
||||
player.printError("Unknown schematic format: " + formatName);
|
||||
return;
|
||||
}
|
||||
|
||||
Closer closer = Closer.create();
|
||||
try {
|
||||
String filePath = f.getCanonicalPath();
|
||||
String dirPath = dir.getCanonicalPath();
|
||||
|
||||
if (!filePath.substring(0, dirPath.length()).equals(dirPath)) {
|
||||
player.printError("Clipboard file could not read or it does not exist.");
|
||||
} else {
|
||||
FileInputStream fis = closer.register(new FileInputStream(f));
|
||||
BufferedInputStream bis = closer.register(new BufferedInputStream(fis));
|
||||
ClipboardReader reader = format.getReader(bis);
|
||||
|
||||
WorldData worldData = player.getWorld().getWorldData();
|
||||
Clipboard clipboard = reader.read(player.getWorld().getWorldData());
|
||||
session.setClipboard(new ClipboardHolder(clipboard, worldData));
|
||||
|
||||
log.info(player.getName() + " loaded " + filePath);
|
||||
player.print(filename + " loaded. Paste it with //paste");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
player.printError("Schematic could not read or it does not exist: " + e.getMessage());
|
||||
log.log(Level.WARNING, "Failed to load a saved clipboard", e);
|
||||
} finally {
|
||||
try {
|
||||
closer.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "save" },
|
||||
usage = "[<format>] <filename>",
|
||||
desc = "Save a schematic into your clipboard"
|
||||
)
|
||||
@Deprecated
|
||||
@CommandPermissions({ "worldedit.clipboard.save", "worldedit.schematic.save" })
|
||||
public void save(Player player, LocalSession session, @Optional("schematic") String formatName, String filename) throws CommandException, WorldEditException {
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
|
||||
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
|
||||
File f = worldEdit.getSafeSaveFile(player, dir, filename, "schematic", "schematic");
|
||||
|
||||
ClipboardFormat format = ClipboardFormat.findByAlias(formatName);
|
||||
if (format == null) {
|
||||
player.printError("Unknown schematic format: " + formatName);
|
||||
return;
|
||||
}
|
||||
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
Transform transform = holder.getTransform();
|
||||
Clipboard target;
|
||||
|
||||
// If we have a transform, bake it into the copy
|
||||
if (!transform.isIdentity()) {
|
||||
FlattenedClipboardTransform result = FlattenedClipboardTransform.transform(clipboard, transform, holder.getWorldData());
|
||||
target = new BlockArrayClipboard(result.getTransformedRegion());
|
||||
target.setOrigin(clipboard.getOrigin());
|
||||
Operations.completeLegacy(result.copyTo(target));
|
||||
} else {
|
||||
target = clipboard;
|
||||
}
|
||||
|
||||
Closer closer = Closer.create();
|
||||
try {
|
||||
// Create parent directories
|
||||
File parent = f.getParentFile();
|
||||
if (parent != null && !parent.exists()) {
|
||||
if (!parent.mkdirs()) {
|
||||
throw new CommandException("Could not create folder for schematics!");
|
||||
}
|
||||
}
|
||||
|
||||
FileOutputStream fos = closer.register(new FileOutputStream(f));
|
||||
BufferedOutputStream bos = closer.register(new BufferedOutputStream(fos));
|
||||
ClipboardWriter writer = closer.register(format.getWriter(bos));
|
||||
writer.write(target, holder.getWorldData());
|
||||
log.info(player.getName() + " saved " + f.getCanonicalPath());
|
||||
player.print(filename + " saved.");
|
||||
} catch (IOException e) {
|
||||
player.printError("Schematic could not written: " + e.getMessage());
|
||||
log.log(Level.WARNING, "Failed to write a saved clipboard", e);
|
||||
} finally {
|
||||
try {
|
||||
closer.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "delete", "d" },
|
||||
usage = "<filename>",
|
||||
desc = "Delete a saved schematic",
|
||||
help = "Delete a schematic from the schematic list",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.schematic.delete")
|
||||
public void delete(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = worldEdit.getConfiguration();
|
||||
String filename = args.getString(0);
|
||||
|
||||
File dir = worldEdit.getWorkingDirectoryFile(config.saveDir);
|
||||
File f = worldEdit.getSafeSaveFile(player, dir, filename, "schematic", "schematic");
|
||||
|
||||
if (!f.exists()) {
|
||||
player.printError("Schematic " + filename + " does not exist!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!f.delete()) {
|
||||
player.printError("Deletion of " + filename + " failed! Maybe it is read-only.");
|
||||
return;
|
||||
}
|
||||
|
||||
player.print(filename + " has been deleted.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"formats", "listformats", "f"},
|
||||
desc = "List available formats",
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.schematic.formats")
|
||||
public void formats(Actor actor) throws WorldEditException {
|
||||
actor.print("Available clipboard formats (Name: Lookup names)");
|
||||
StringBuilder builder;
|
||||
boolean first = true;
|
||||
for (ClipboardFormat format : ClipboardFormat.values()) {
|
||||
builder = new StringBuilder();
|
||||
builder.append(format.name()).append(": ");
|
||||
for (String lookupName : format.getAliases()) {
|
||||
if (!first) {
|
||||
builder.append(", ");
|
||||
}
|
||||
builder.append(lookupName);
|
||||
first = false;
|
||||
}
|
||||
first = true;
|
||||
actor.print(builder.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"list", "all", "ls"},
|
||||
desc = "List saved schematics",
|
||||
max = 0,
|
||||
flags = "dn",
|
||||
help = "List all schematics in the schematics directory\n" +
|
||||
" -d sorts by date, oldest first\n" +
|
||||
" -n sorts by date, newest first\n"
|
||||
)
|
||||
@CommandPermissions("worldedit.schematic.list")
|
||||
public void list(Actor actor, CommandContext args) throws WorldEditException {
|
||||
File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().saveDir);
|
||||
File[] files = dir.listFiles(new FileFilter(){
|
||||
@Override
|
||||
public boolean accept(File file) {
|
||||
// sort out directories from the schematic list
|
||||
// if WE supports sub-directories in the future,
|
||||
// this will have to be changed
|
||||
return file.isFile();
|
||||
}
|
||||
});
|
||||
if (files == null) {
|
||||
throw new FilenameResolutionException(dir.getPath(), "Schematics directory invalid or not found.");
|
||||
}
|
||||
|
||||
final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0;
|
||||
// cleanup file list
|
||||
Arrays.sort(files, new Comparator<File>(){
|
||||
@Override
|
||||
public int compare(File f1, File f2) {
|
||||
// this should no longer happen, as directory-ness is checked before
|
||||
// however, if a directory slips through, this will break the contract
|
||||
// of comparator transitivity
|
||||
if (!f1.isFile() || !f2.isFile()) return -1;
|
||||
// http://stackoverflow.com/questions/203030/best-way-to-list-files-in-java-sorted-by-date-modified
|
||||
int result = sortType == 0 ? f1.getName().compareToIgnoreCase(f2.getName()) : // use name by default
|
||||
Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); // use date if there is a flag
|
||||
if (sortType == 1) result = -result; // flip date for newest first instead of oldest first
|
||||
return result;
|
||||
}
|
||||
});
|
||||
|
||||
actor.print("Available schematics (Filename (Format)):");
|
||||
actor.print(listFiles("", files));
|
||||
}
|
||||
|
||||
private String listFiles(String prefix, File[] files) {
|
||||
StringBuilder build = new StringBuilder();
|
||||
for (File file : files) {
|
||||
if (file.isDirectory()) {
|
||||
build.append(listFiles(prefix + file.getName() + "/", file.listFiles()));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!file.isFile()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
build.append("\n\u00a79");
|
||||
ClipboardFormat format = ClipboardFormat.findByFile(file);
|
||||
build.append(prefix).append(file.getName()).append(": ").append(format == null ? "Unknown" : format.name());
|
||||
}
|
||||
return build.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL;
|
||||
|
||||
/**
|
||||
* Commands related to scripting.
|
||||
*/
|
||||
public class ScriptingCommands {
|
||||
|
||||
private final WorldEdit worldEdit;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param worldEdit reference to WorldEdit
|
||||
*/
|
||||
public ScriptingCommands(WorldEdit worldEdit) {
|
||||
checkNotNull(worldEdit);
|
||||
this.worldEdit = worldEdit;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "cs" },
|
||||
usage = "<filename> [args...]",
|
||||
desc = "Execute a CraftScript",
|
||||
min = 1,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.scripting.execute")
|
||||
@Logging(ALL)
|
||||
public void execute(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
String[] scriptArgs = args.getSlice(1);
|
||||
String name = args.getString(0);
|
||||
|
||||
if (!player.hasPermission("worldedit.scripting.execute." + name)) {
|
||||
player.printError("You don't have permission to use that script.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.setLastScript(name);
|
||||
|
||||
File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().scriptsDir);
|
||||
File f = worldEdit.getSafeOpenFile(player, dir, name, "js", "js");
|
||||
|
||||
worldEdit.runScript(player, f, scriptArgs);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { ".s" },
|
||||
usage = "[args...]",
|
||||
desc = "Execute last CraftScript",
|
||||
min = 0,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.scripting.execute")
|
||||
@Logging(ALL)
|
||||
public void executeLast(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
String lastScript = session.getLastScript();
|
||||
|
||||
if (!player.hasPermission("worldedit.scripting.execute." + lastScript)) {
|
||||
player.printError("You don't have permission to use that script.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastScript == null) {
|
||||
player.printError("Use /cs with a script name first.");
|
||||
return;
|
||||
}
|
||||
|
||||
String[] scriptArgs = args.getSlice(0);
|
||||
|
||||
File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().scriptsDir);
|
||||
File f = worldEdit.getSafeOpenFile(player, dir, lastScript, "js", "js");
|
||||
|
||||
worldEdit.runScript(player, f, scriptArgs);
|
||||
}
|
||||
}
|
@ -0,0 +1,799 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionOperationException;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.CylinderRegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.EllipsoidRegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.ExtendingCuboidRegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.RegionSelectorType;
|
||||
import com.sk89q.worldedit.regions.selector.SphereRegionSelector;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.Countable;
|
||||
import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
|
||||
import com.sk89q.worldedit.util.formatting.Style;
|
||||
import com.sk89q.worldedit.util.formatting.StyledFragment;
|
||||
import com.sk89q.worldedit.util.formatting.component.CommandListBox;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.storage.ChunkStore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
|
||||
/**
|
||||
* Selection commands.
|
||||
*/
|
||||
public class SelectionCommands {
|
||||
|
||||
private final WorldEdit we;
|
||||
|
||||
public SelectionCommands(WorldEdit we) {
|
||||
this.we = we;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/pos1" },
|
||||
usage = "[coordinates]",
|
||||
desc = "Set position 1",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@Logging(POSITION)
|
||||
@CommandPermissions("worldedit.selection.pos")
|
||||
public void pos1(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
Vector pos;
|
||||
|
||||
if (args.argsLength() == 1) {
|
||||
if (args.getString(0).matches("-?\\d+,-?\\d+,-?\\d+")) {
|
||||
String[] coords = args.getString(0).split(",");
|
||||
pos = new Vector(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(coords[2]));
|
||||
} else {
|
||||
player.printError("Invalid coordinates " + args.getString(0));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
pos = player.getBlockIn();
|
||||
}
|
||||
|
||||
if (!session.getRegionSelector(player.getWorld()).selectPrimary(pos, ActorSelectorLimits.forActor(player))) {
|
||||
player.printError("Position already set.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.getRegionSelector(player.getWorld())
|
||||
.explainPrimarySelection(player, session, pos);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/pos2" },
|
||||
usage = "[coordinates]",
|
||||
desc = "Set position 2",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@Logging(POSITION)
|
||||
@CommandPermissions("worldedit.selection.pos")
|
||||
public void pos2(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
Vector pos;
|
||||
if (args.argsLength() == 1) {
|
||||
if (args.getString(0).matches("-?\\d+,-?\\d+,-?\\d+")) {
|
||||
String[] coords = args.getString(0).split(",");
|
||||
pos = new Vector(Integer.parseInt(coords[0]),
|
||||
Integer.parseInt(coords[1]),
|
||||
Integer.parseInt(coords[2]));
|
||||
} else {
|
||||
player.printError("Invalid coordinates " + args.getString(0));
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
pos = player.getBlockIn();
|
||||
}
|
||||
|
||||
if (!session.getRegionSelector(player.getWorld()).selectSecondary(pos, ActorSelectorLimits.forActor(player))) {
|
||||
player.printError("Position already set.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.getRegionSelector(player.getWorld())
|
||||
.explainSecondarySelection(player, session, pos);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hpos1" },
|
||||
usage = "",
|
||||
desc = "Set position 1 to targeted block",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.selection.hpos")
|
||||
public void hpos1(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
Vector pos = player.getBlockTrace(300);
|
||||
|
||||
if (pos != null) {
|
||||
if (!session.getRegionSelector(player.getWorld()).selectPrimary(pos, ActorSelectorLimits.forActor(player))) {
|
||||
player.printError("Position already set.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.getRegionSelector(player.getWorld())
|
||||
.explainPrimarySelection(player, session, pos);
|
||||
} else {
|
||||
player.printError("No block in sight!");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/hpos2" },
|
||||
usage = "",
|
||||
desc = "Set position 2 to targeted block",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.selection.hpos")
|
||||
public void hpos2(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
Vector pos = player.getBlockTrace(300);
|
||||
|
||||
if (pos != null) {
|
||||
if (!session.getRegionSelector(player.getWorld()).selectSecondary(pos, ActorSelectorLimits.forActor(player))) {
|
||||
player.printError("Position already set.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.getRegionSelector(player.getWorld())
|
||||
.explainSecondarySelection(player, session, pos);
|
||||
} else {
|
||||
player.printError("No block in sight!");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/chunk" },
|
||||
usage = "[x,z coordinates]",
|
||||
flags = "sc",
|
||||
desc = "Set the selection to your current chunk.",
|
||||
help =
|
||||
"Set the selection to the chunk you are currently in.\n" +
|
||||
"With the -s flag, your current selection is expanded\n" +
|
||||
"to encompass all chunks that are part of it.\n\n" +
|
||||
"Specifying coordinates will use those instead of your\n"+
|
||||
"current position. Use -c to specify chunk coordinates,\n" +
|
||||
"otherwise full coordinates will be implied.\n" +
|
||||
"(for example, the coordinates 5,5 are the same as -c 0,0)",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@Logging(POSITION)
|
||||
@CommandPermissions("worldedit.selection.chunk")
|
||||
public void chunk(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
final Vector min;
|
||||
final Vector max;
|
||||
final World world = player.getWorld();
|
||||
if (args.hasFlag('s')) {
|
||||
Region region = session.getSelection(world);
|
||||
|
||||
final Vector2D min2D = ChunkStore.toChunk(region.getMinimumPoint());
|
||||
final Vector2D max2D = ChunkStore.toChunk(region.getMaximumPoint());
|
||||
|
||||
min = new Vector(min2D.getBlockX() * 16, 0, min2D.getBlockZ() * 16);
|
||||
max = new Vector(max2D.getBlockX() * 16 + 15, world.getMaxY(), max2D.getBlockZ() * 16 + 15);
|
||||
|
||||
player.print("Chunks selected: ("
|
||||
+ min2D.getBlockX() + ", " + min2D.getBlockZ() + ") - ("
|
||||
+ max2D.getBlockX() + ", " + max2D.getBlockZ() + ")");
|
||||
} else {
|
||||
final Vector2D min2D;
|
||||
if (args.argsLength() == 1) {
|
||||
// coords specified
|
||||
String[] coords = args.getString(0).split(",");
|
||||
if (coords.length != 2) {
|
||||
throw new InsufficientArgumentsException("Invalid coordinates specified.");
|
||||
}
|
||||
int x = Integer.parseInt(coords[0]);
|
||||
int z = Integer.parseInt(coords[1]);
|
||||
Vector2D pos = new Vector2D(x, z);
|
||||
min2D = (args.hasFlag('c')) ? pos : ChunkStore.toChunk(pos.toVector());
|
||||
} else {
|
||||
// use player loc
|
||||
min2D = ChunkStore.toChunk(player.getBlockIn());
|
||||
}
|
||||
|
||||
min = new Vector(min2D.getBlockX() * 16, 0, min2D.getBlockZ() * 16);
|
||||
max = min.add(15, world.getMaxY(), 15);
|
||||
|
||||
player.print("Chunk selected: "
|
||||
+ min2D.getBlockX() + ", " + min2D.getBlockZ());
|
||||
}
|
||||
|
||||
final CuboidRegionSelector selector;
|
||||
if (session.getRegionSelector(world) instanceof ExtendingCuboidRegionSelector) {
|
||||
selector = new ExtendingCuboidRegionSelector(world);
|
||||
} else {
|
||||
selector = new CuboidRegionSelector(world);
|
||||
}
|
||||
selector.selectPrimary(min, ActorSelectorLimits.forActor(player));
|
||||
selector.selectSecondary(max, ActorSelectorLimits.forActor(player));
|
||||
session.setRegionSelector(world, selector);
|
||||
|
||||
session.dispatchCUISelection(player);
|
||||
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/wand" },
|
||||
usage = "",
|
||||
desc = "Get the wand object",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.wand")
|
||||
public void wand(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
player.giveItem(we.getConfiguration().wandItem, 1);
|
||||
player.print("Left click: select pos #1; Right click: select pos #2");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "toggleeditwand" },
|
||||
usage = "",
|
||||
desc = "Toggle functionality of the edit wand",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.wand.toggle")
|
||||
public void toggleWand(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
session.setToolControl(!session.isToolControlEnabled());
|
||||
|
||||
if (session.isToolControlEnabled()) {
|
||||
player.print("Edit wand enabled.");
|
||||
} else {
|
||||
player.print("Edit wand disabled.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/expand" },
|
||||
usage = "<amount> [reverse-amount] <direction>",
|
||||
desc = "Expand the selection area",
|
||||
min = 1,
|
||||
max = 3
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.selection.expand")
|
||||
public void expand(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
// Special syntax (//expand vert) to expand the selection between
|
||||
// sky and bedrock.
|
||||
if (args.getString(0).equalsIgnoreCase("vert")
|
||||
|| args.getString(0).equalsIgnoreCase("vertical")) {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
try {
|
||||
int oldSize = region.getArea();
|
||||
region.expand(
|
||||
new Vector(0, (player.getWorld().getMaxY() + 1), 0),
|
||||
new Vector(0, -(player.getWorld().getMaxY() + 1), 0));
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
int newSize = region.getArea();
|
||||
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
|
||||
player.print("Region expanded " + (newSize - oldSize)
|
||||
+ " blocks [top-to-bottom].");
|
||||
} catch (RegionOperationException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
List<Vector> dirs = new ArrayList<Vector>();
|
||||
int change = args.getInteger(0);
|
||||
int reverseChange = 0;
|
||||
|
||||
switch (args.argsLength()) {
|
||||
case 2:
|
||||
// Either a reverse amount or a direction
|
||||
try {
|
||||
reverseChange = args.getInteger(1);
|
||||
dirs.add(we.getDirection(player, "me"));
|
||||
} catch (NumberFormatException e) {
|
||||
if (args.getString(1).contains(",")) {
|
||||
String[] split = args.getString(1).split(",");
|
||||
for (String s : split) {
|
||||
dirs.add(we.getDirection(player, s.toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Both reverse amount and direction
|
||||
reverseChange = args.getInteger(1);
|
||||
if (args.getString(2).contains(",")) {
|
||||
String[] split = args.getString(2).split(",");
|
||||
for (String s : split) {
|
||||
dirs.add(we.getDirection(player, s.toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, args.getString(2).toLowerCase()));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
dirs.add(we.getDirection(player, "me"));
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
int oldSize = region.getArea();
|
||||
|
||||
if (reverseChange == 0) {
|
||||
for (Vector dir : dirs) {
|
||||
region.expand(dir.multiply(change));
|
||||
}
|
||||
} else {
|
||||
for (Vector dir : dirs) {
|
||||
region.expand(dir.multiply(change), dir.multiply(-reverseChange));
|
||||
}
|
||||
}
|
||||
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
int newSize = region.getArea();
|
||||
|
||||
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
|
||||
|
||||
player.print("Region expanded " + (newSize - oldSize) + " blocks.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/contract" },
|
||||
usage = "<amount> [reverse-amount] [direction]",
|
||||
desc = "Contract the selection area",
|
||||
min = 1,
|
||||
max = 3
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.selection.contract")
|
||||
public void contract(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
List<Vector> dirs = new ArrayList<Vector>();
|
||||
int change = args.getInteger(0);
|
||||
int reverseChange = 0;
|
||||
|
||||
switch (args.argsLength()) {
|
||||
case 2:
|
||||
// Either a reverse amount or a direction
|
||||
try {
|
||||
reverseChange = args.getInteger(1);
|
||||
dirs.add(we.getDirection(player, "me"));
|
||||
} catch (NumberFormatException e) {
|
||||
if (args.getString(1).contains(",")) {
|
||||
String[] split = args.getString(1).split(",");
|
||||
for (String s : split) {
|
||||
dirs.add(we.getDirection(player, s.toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 3:
|
||||
// Both reverse amount and direction
|
||||
reverseChange = args.getInteger(1);
|
||||
if (args.getString(2).contains(",")) {
|
||||
String[] split = args.getString(2).split(",");
|
||||
for (String s : split) {
|
||||
dirs.add(we.getDirection(player, s.toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, args.getString(2).toLowerCase()));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
dirs.add(we.getDirection(player, "me"));
|
||||
break;
|
||||
}
|
||||
|
||||
try {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
int oldSize = region.getArea();
|
||||
if (reverseChange == 0) {
|
||||
for (Vector dir : dirs) {
|
||||
region.contract(dir.multiply(change));
|
||||
}
|
||||
} else {
|
||||
for (Vector dir : dirs) {
|
||||
region.contract(dir.multiply(change), dir.multiply(-reverseChange));
|
||||
}
|
||||
}
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
int newSize = region.getArea();
|
||||
|
||||
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
|
||||
|
||||
|
||||
player.print("Region contracted " + (oldSize - newSize) + " blocks.");
|
||||
} catch (RegionOperationException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/shift" },
|
||||
usage = "<amount> [direction]",
|
||||
desc = "Shift the selection area",
|
||||
min = 1,
|
||||
max = 2
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.selection.shift")
|
||||
public void shift(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
List<Vector> dirs = new ArrayList<Vector>();
|
||||
int change = args.getInteger(0);
|
||||
if (args.argsLength() == 2) {
|
||||
if (args.getString(1).contains(",")) {
|
||||
for (String s : args.getString(1).split(",")) {
|
||||
dirs.add(we.getDirection(player, s.toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
|
||||
}
|
||||
} else {
|
||||
dirs.add(we.getDirection(player, "me"));
|
||||
}
|
||||
|
||||
try {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
|
||||
for (Vector dir : dirs) {
|
||||
region.shift(dir.multiply(change));
|
||||
}
|
||||
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
|
||||
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
|
||||
|
||||
player.print("Region shifted.");
|
||||
} catch (RegionOperationException e) {
|
||||
player.printError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/outset" },
|
||||
usage = "<amount>",
|
||||
desc = "Outset the selection area",
|
||||
help =
|
||||
"Expands the selection by the given amount in all directions.\n" +
|
||||
"Flags:\n" +
|
||||
" -h only expand horizontally\n" +
|
||||
" -v only expand vertically\n",
|
||||
flags = "hv",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.selection.outset")
|
||||
public void outset(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
region.expand(getChangesForEachDir(args));
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
|
||||
player.print("Region outset.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/inset" },
|
||||
usage = "<amount>",
|
||||
desc = "Inset the selection area",
|
||||
help =
|
||||
"Contracts the selection by the given amount in all directions.\n" +
|
||||
"Flags:\n" +
|
||||
" -h only contract horizontally\n" +
|
||||
" -v only contract vertically\n",
|
||||
flags = "hv",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.selection.inset")
|
||||
public void inset(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
region.contract(getChangesForEachDir(args));
|
||||
session.getRegionSelector(player.getWorld()).learnChanges();
|
||||
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
|
||||
player.print("Region inset.");
|
||||
}
|
||||
|
||||
private Vector[] getChangesForEachDir(CommandContext args) {
|
||||
List<Vector> changes = new ArrayList<Vector>(6);
|
||||
int change = args.getInteger(0);
|
||||
|
||||
if (!args.hasFlag('h')) {
|
||||
changes.add((new Vector(0, 1, 0)).multiply(change));
|
||||
changes.add((new Vector(0, -1, 0)).multiply(change));
|
||||
}
|
||||
|
||||
if (!args.hasFlag('v')) {
|
||||
changes.add((new Vector(1, 0, 0)).multiply(change));
|
||||
changes.add((new Vector(-1, 0, 0)).multiply(change));
|
||||
changes.add((new Vector(0, 0, 1)).multiply(change));
|
||||
changes.add((new Vector(0, 0, -1)).multiply(change));
|
||||
}
|
||||
|
||||
return changes.toArray(new Vector[0]);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/size" },
|
||||
flags = "c",
|
||||
usage = "",
|
||||
desc = "Get information about the selection",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.selection.size")
|
||||
public void size(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
if (args.hasFlag('c')) {
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
Region region = clipboard.getRegion();
|
||||
Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint());
|
||||
Vector origin = clipboard.getOrigin();
|
||||
|
||||
player.print("Cuboid dimensions (max - min): " + size);
|
||||
player.print("Offset: " + origin);
|
||||
player.print("Cuboid distance: " + size.distance(Vector.ONE));
|
||||
player.print("# of blocks: " + (int) (size.getX() * size.getY() * size.getZ()));
|
||||
return;
|
||||
}
|
||||
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
Vector size = region.getMaximumPoint()
|
||||
.subtract(region.getMinimumPoint())
|
||||
.add(1, 1, 1);
|
||||
|
||||
player.print("Type: " + session.getRegionSelector(player.getWorld())
|
||||
.getTypeName());
|
||||
|
||||
for (String line : session.getRegionSelector(player.getWorld())
|
||||
.getInformationLines()) {
|
||||
player.print(line);
|
||||
}
|
||||
|
||||
player.print("Size: " + size);
|
||||
player.print("Cuboid distance: " + region.getMaximumPoint().distance(region.getMinimumPoint()));
|
||||
player.print("# of blocks: " + region.getArea());
|
||||
}
|
||||
|
||||
|
||||
@Command(
|
||||
aliases = { "/count" },
|
||||
usage = "<block>",
|
||||
desc = "Counts the number of a certain type of block",
|
||||
flags = "d",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.analysis.count")
|
||||
public void count(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
boolean useData = args.hasFlag('d');
|
||||
if (args.getString(0).contains(":")) {
|
||||
useData = true; //override d flag, if they specified data they want it
|
||||
}
|
||||
if (useData) {
|
||||
Set<BaseBlock> searchBlocks = we.getBlocks(player, args.getString(0), true);
|
||||
int count = editSession.countBlocks(session.getSelection(player.getWorld()), searchBlocks);
|
||||
player.print("Counted: " + count);
|
||||
} else {
|
||||
Set<Integer> searchIDs = we.getBlockIDs(player, args.getString(0), true);
|
||||
int count = editSession.countBlock(session.getSelection(player.getWorld()), searchIDs);
|
||||
player.print("Counted: " + count);
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/distr" },
|
||||
usage = "",
|
||||
desc = "Get the distribution of blocks in the selection",
|
||||
help =
|
||||
"Gets the distribution of blocks in the selection.\n" +
|
||||
"The -c flag gets the distribution of your clipboard.\n" +
|
||||
"The -d flag separates blocks by data",
|
||||
flags = "cd",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.analysis.distr")
|
||||
public void distr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException {
|
||||
|
||||
int size;
|
||||
boolean useData = args.hasFlag('d');
|
||||
List<Countable<Integer>> distribution = null;
|
||||
List<Countable<BaseBlock>> distributionData = null;
|
||||
|
||||
if (args.hasFlag('c')) {
|
||||
// TODO: Update for new clipboard
|
||||
throw new CommandException("Needs to be re-written again");
|
||||
} else {
|
||||
if (useData) {
|
||||
distributionData = editSession.getBlockDistributionWithData(session.getSelection(player.getWorld()));
|
||||
} else {
|
||||
distribution = editSession.getBlockDistribution(session.getSelection(player.getWorld()));
|
||||
}
|
||||
size = session.getSelection(player.getWorld()).getArea();
|
||||
}
|
||||
|
||||
if ((useData && distributionData.size() <= 0)
|
||||
|| (!useData && distribution.size() <= 0)) { // *Should* always be false
|
||||
player.printError("No blocks counted.");
|
||||
return;
|
||||
}
|
||||
|
||||
player.print("# total blocks: " + size);
|
||||
|
||||
if (useData) {
|
||||
for (Countable<BaseBlock> c : distributionData) {
|
||||
String name = BlockType.fromID(c.getID().getId()).getName();
|
||||
String str = String.format("%-7s (%.3f%%) %s #%d:%d",
|
||||
String.valueOf(c.getAmount()),
|
||||
c.getAmount() / (double) size * 100,
|
||||
name == null ? "Unknown" : name,
|
||||
c.getID().getType(), c.getID().getData());
|
||||
player.print(str);
|
||||
}
|
||||
} else {
|
||||
for (Countable<Integer> c : distribution) {
|
||||
BlockType block = BlockType.fromID(c.getID());
|
||||
String str = String.format("%-7s (%.3f%%) %s #%d",
|
||||
String.valueOf(c.getAmount()),
|
||||
c.getAmount() / (double) size * 100,
|
||||
block == null ? "Unknown" : block.getName(), c.getID());
|
||||
player.print(str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/sel", ";", "/desel", "/deselect" },
|
||||
flags = "d",
|
||||
usage = "[cuboid|extend|poly|ellipsoid|sphere|cyl|convex]",
|
||||
desc = "Choose a region selector",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
public void select(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
final World world = player.getWorld();
|
||||
if (args.argsLength() == 0) {
|
||||
session.getRegionSelector(world).clear();
|
||||
session.dispatchCUISelection(player);
|
||||
player.print("Selection cleared.");
|
||||
return;
|
||||
}
|
||||
|
||||
final String typeName = args.getString(0);
|
||||
final RegionSelector oldSelector = session.getRegionSelector(world);
|
||||
|
||||
final RegionSelector selector;
|
||||
if (typeName.equalsIgnoreCase("cuboid")) {
|
||||
selector = new CuboidRegionSelector(oldSelector);
|
||||
player.print("Cuboid: left click for point 1, right click for point 2");
|
||||
} else if (typeName.equalsIgnoreCase("extend")) {
|
||||
selector = new ExtendingCuboidRegionSelector(oldSelector);
|
||||
player.print("Cuboid: left click for a starting point, right click to extend");
|
||||
} else if (typeName.equalsIgnoreCase("poly")) {
|
||||
selector = new Polygonal2DRegionSelector(oldSelector);
|
||||
player.print("2D polygon selector: Left/right click to add a point.");
|
||||
Optional<Integer> limit = ActorSelectorLimits.forActor(player).getPolygonVertexLimit();
|
||||
if (limit.isPresent()) {
|
||||
player.print(limit.get() + " points maximum.");
|
||||
}
|
||||
} else if (typeName.equalsIgnoreCase("ellipsoid")) {
|
||||
selector = new EllipsoidRegionSelector(oldSelector);
|
||||
player.print("Ellipsoid selector: left click=center, right click to extend");
|
||||
} else if (typeName.equalsIgnoreCase("sphere")) {
|
||||
selector = new SphereRegionSelector(oldSelector);
|
||||
player.print("Sphere selector: left click=center, right click to set radius");
|
||||
} else if (typeName.equalsIgnoreCase("cyl")) {
|
||||
selector = new CylinderRegionSelector(oldSelector);
|
||||
player.print("Cylindrical selector: Left click=center, right click to extend.");
|
||||
} else if (typeName.equalsIgnoreCase("convex") || typeName.equalsIgnoreCase("hull") || typeName.equalsIgnoreCase("polyhedron")) {
|
||||
selector = new ConvexPolyhedralRegionSelector(oldSelector);
|
||||
player.print("Convex polyhedral selector: Left click=First vertex, right click to add more.");
|
||||
Optional<Integer> limit = ActorSelectorLimits.forActor(player).getPolyhedronVertexLimit();
|
||||
if (limit.isPresent()) {
|
||||
player.print(limit.get() + " points maximum.");
|
||||
}
|
||||
} else {
|
||||
CommandListBox box = new CommandListBox("Selection modes");
|
||||
StyledFragment contents = box.getContents();
|
||||
StyledFragment tip = contents.createFragment(Style.RED);
|
||||
tip.append("Select one of the modes below:").newLine();
|
||||
|
||||
box.appendCommand("cuboid", "Select two corners of a cuboid");
|
||||
box.appendCommand("extend", "Fast cuboid selection mode");
|
||||
box.appendCommand("poly", "Select a 2D polygon with height");
|
||||
box.appendCommand("ellipsoid", "Select an ellipsoid");
|
||||
box.appendCommand("sphere", "Select a sphere");
|
||||
box.appendCommand("cyl", "Select a cylinder");
|
||||
box.appendCommand("convex", "Select a convex polyhedral");
|
||||
|
||||
player.printRaw(ColorCodeBuilder.asColorCodes(box));
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.hasFlag('d')) {
|
||||
RegionSelectorType found = null;
|
||||
for (RegionSelectorType type : RegionSelectorType.values()) {
|
||||
if (type.getSelectorClass() == selector.getClass()) {
|
||||
found = type;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found != null) {
|
||||
session.setDefaultRegionSelector(found);
|
||||
player.print("Your default region selector is now " + found.name() + ".");
|
||||
} else {
|
||||
throw new RuntimeException("Something unexpected happened. Please report this.");
|
||||
}
|
||||
}
|
||||
|
||||
session.setRegionSelector(world, selector);
|
||||
session.dispatchCUISelection(player);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,272 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// $Id$
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.world.snapshot.InvalidSnapshotException;
|
||||
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
||||
import com.sk89q.worldedit.world.storage.MissingWorldException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
/**
|
||||
* Snapshot commands.
|
||||
*/
|
||||
public class SnapshotCommands {
|
||||
|
||||
private static final Logger logger = Logger.getLogger("Minecraft.WorldEdit");
|
||||
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
|
||||
|
||||
private final WorldEdit we;
|
||||
|
||||
public SnapshotCommands(WorldEdit we) {
|
||||
this.we = we;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "list" },
|
||||
usage = "[num]",
|
||||
desc = "List snapshots",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.snapshots.list")
|
||||
public void list(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
if (config.snapshotRepo == null) {
|
||||
player.printError("Snapshot/backup restore is not configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
List<Snapshot> snapshots = config.snapshotRepo.getSnapshots(true, player.getWorld().getName());
|
||||
|
||||
if (!snapshots.isEmpty()) {
|
||||
|
||||
int num = args.argsLength() > 0 ? Math.min(40, Math.max(5, args.getInteger(0))) : 5;
|
||||
|
||||
player.print("Snapshots for world: '" + player.getWorld().getName() + "'");
|
||||
for (byte i = 0; i < Math.min(num, snapshots.size()); i++) {
|
||||
player.print((i + 1) + ". " + snapshots.get(i).getName());
|
||||
}
|
||||
|
||||
player.print("Use /snap use [snapshot] or /snap use latest.");
|
||||
} else {
|
||||
player.printError("No snapshots are available. See console for details.");
|
||||
|
||||
// Okay, let's toss some debugging information!
|
||||
File dir = config.snapshotRepo.getDirectory();
|
||||
|
||||
try {
|
||||
logger.info("WorldEdit found no snapshots: looked in: "
|
||||
+ dir.getCanonicalPath());
|
||||
} catch (IOException e) {
|
||||
logger.info("WorldEdit found no snapshots: looked in "
|
||||
+ "(NON-RESOLVABLE PATH - does it exist?): "
|
||||
+ dir.getPath());
|
||||
}
|
||||
}
|
||||
} catch (MissingWorldException ex) {
|
||||
player.printError("No snapshots were found for this world.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "use" },
|
||||
usage = "<snapshot>",
|
||||
desc = "Choose a snapshot to use",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.snapshots.restore")
|
||||
public void use(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
if (config.snapshotRepo == null) {
|
||||
player.printError("Snapshot/backup restore is not configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
String name = args.getString(0);
|
||||
|
||||
// Want the latest snapshot?
|
||||
if (name.equalsIgnoreCase("latest")) {
|
||||
try {
|
||||
Snapshot snapshot = config.snapshotRepo.getDefaultSnapshot(player.getWorld().getName());
|
||||
|
||||
if (snapshot != null) {
|
||||
session.setSnapshot(null);
|
||||
player.print("Now using newest snapshot.");
|
||||
} else {
|
||||
player.printError("No snapshots were found.");
|
||||
}
|
||||
} catch (MissingWorldException ex) {
|
||||
player.printError("No snapshots were found for this world.");
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
session.setSnapshot(config.snapshotRepo.getSnapshot(name));
|
||||
player.print("Snapshot set to: " + name);
|
||||
} catch (InvalidSnapshotException e) {
|
||||
player.printError("That snapshot does not exist or is not available.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "sel" },
|
||||
usage = "<index>",
|
||||
desc = "Choose the snapshot based on the list id",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.snapshots.restore")
|
||||
public void sel(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
if (config.snapshotRepo == null) {
|
||||
player.printError("Snapshot/backup restore is not configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
int index = -1;
|
||||
try {
|
||||
index = Integer.parseInt(args.getString(0));
|
||||
} catch (NumberFormatException e) {
|
||||
player.printError("Invalid index, " + args.getString(0) + " is not a valid integer.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (index < 1) {
|
||||
player.printError("Invalid index, must be equal or higher then 1.");
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
List<Snapshot> snapshots = config.snapshotRepo.getSnapshots(true, player.getWorld().getName());
|
||||
if (snapshots.size() < index) {
|
||||
player.printError("Invalid index, must be between 1 and " + snapshots.size() + ".");
|
||||
return;
|
||||
}
|
||||
Snapshot snapshot = snapshots.get(index - 1);
|
||||
if (snapshot == null) {
|
||||
player.printError("That snapshot does not exist or is not available.");
|
||||
return;
|
||||
}
|
||||
session.setSnapshot(snapshot);
|
||||
player.print("Snapshot set to: " + snapshot.getName());
|
||||
} catch (MissingWorldException e) {
|
||||
player.printError("No snapshots were found for this world.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "before" },
|
||||
usage = "<date>",
|
||||
desc = "Choose the nearest snapshot before a date",
|
||||
min = 1,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.snapshots.restore")
|
||||
public void before(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
if (config.snapshotRepo == null) {
|
||||
player.printError("Snapshot/backup restore is not configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
Calendar date = session.detectDate(args.getJoinedStrings(0));
|
||||
|
||||
if (date == null) {
|
||||
player.printError("Could not detect the date inputted.");
|
||||
} else {
|
||||
try {
|
||||
Snapshot snapshot = config.snapshotRepo.getSnapshotBefore(date, player.getWorld().getName());
|
||||
|
||||
if (snapshot == null) {
|
||||
dateFormat.setTimeZone(session.getTimeZone());
|
||||
player.printError("Couldn't find a snapshot before "
|
||||
+ dateFormat.format(date.getTime()) + ".");
|
||||
} else {
|
||||
session.setSnapshot(snapshot);
|
||||
player.print("Snapshot set to: " + snapshot.getName());
|
||||
}
|
||||
} catch (MissingWorldException ex) {
|
||||
player.printError("No snapshots were found for this world.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "after" },
|
||||
usage = "<date>",
|
||||
desc = "Choose the nearest snapshot after a date",
|
||||
min = 1,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.snapshots.restore")
|
||||
public void after(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
if (config.snapshotRepo == null) {
|
||||
player.printError("Snapshot/backup restore is not configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
Calendar date = session.detectDate(args.getJoinedStrings(0));
|
||||
|
||||
if (date == null) {
|
||||
player.printError("Could not detect the date inputted.");
|
||||
} else {
|
||||
try {
|
||||
Snapshot snapshot = config.snapshotRepo.getSnapshotAfter(date, player.getWorld().getName());
|
||||
if (snapshot == null) {
|
||||
dateFormat.setTimeZone(session.getTimeZone());
|
||||
player.printError("Couldn't find a snapshot after "
|
||||
+ dateFormat.format(date.getTime()) + ".");
|
||||
} else {
|
||||
session.setSnapshot(snapshot);
|
||||
player.print("Snapshot set to: " + snapshot.getName());
|
||||
}
|
||||
} catch (MissingWorldException ex) {
|
||||
player.printError("No snapshots were found for this world.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,154 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.world.DataException;
|
||||
import com.sk89q.worldedit.world.snapshot.InvalidSnapshotException;
|
||||
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
||||
import com.sk89q.worldedit.world.snapshot.SnapshotRestore;
|
||||
import com.sk89q.worldedit.world.storage.ChunkStore;
|
||||
import com.sk89q.worldedit.world.storage.MissingWorldException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
|
||||
|
||||
public class SnapshotUtilCommands {
|
||||
|
||||
private static final Logger logger = Logger.getLogger("Minecraft.WorldEdit");
|
||||
|
||||
private final WorldEdit we;
|
||||
|
||||
public SnapshotUtilCommands(WorldEdit we) {
|
||||
this.we = we;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "restore", "/restore" },
|
||||
usage = "[snapshot]",
|
||||
desc = "Restore the selection from a snapshot",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@Logging(REGION)
|
||||
@CommandPermissions("worldedit.snapshots.restore")
|
||||
public void restore(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
if (config.snapshotRepo == null) {
|
||||
player.printError("Snapshot/backup restore is not configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
Region region = session.getSelection(player.getWorld());
|
||||
Snapshot snapshot;
|
||||
|
||||
if (args.argsLength() > 0) {
|
||||
try {
|
||||
snapshot = config.snapshotRepo.getSnapshot(args.getString(0));
|
||||
} catch (InvalidSnapshotException e) {
|
||||
player.printError("That snapshot does not exist or is not available.");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
snapshot = session.getSnapshot();
|
||||
}
|
||||
|
||||
// No snapshot set?
|
||||
if (snapshot == null) {
|
||||
try {
|
||||
snapshot = config.snapshotRepo.getDefaultSnapshot(player.getWorld().getName());
|
||||
|
||||
if (snapshot == null) {
|
||||
player.printError("No snapshots were found. See console for details.");
|
||||
|
||||
// Okay, let's toss some debugging information!
|
||||
File dir = config.snapshotRepo.getDirectory();
|
||||
|
||||
try {
|
||||
logger.info("WorldEdit found no snapshots: looked in: "
|
||||
+ dir.getCanonicalPath());
|
||||
} catch (IOException e) {
|
||||
logger.info("WorldEdit found no snapshots: looked in "
|
||||
+ "(NON-RESOLVABLE PATH - does it exist?): "
|
||||
+ dir.getPath());
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
} catch (MissingWorldException ex) {
|
||||
player.printError("No snapshots were found for this world.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ChunkStore chunkStore = null;
|
||||
|
||||
// Load chunk store
|
||||
try {
|
||||
chunkStore = snapshot.getChunkStore();
|
||||
player.print("Snapshot '" + snapshot.getName() + "' loaded; now restoring...");
|
||||
} catch (DataException e) {
|
||||
player.printError("Failed to load snapshot: " + e.getMessage());
|
||||
return;
|
||||
} catch (IOException e) {
|
||||
player.printError("Failed to load snapshot: " + e.getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Restore snapshot
|
||||
SnapshotRestore restore = new SnapshotRestore(chunkStore, editSession, region);
|
||||
//player.print(restore.getChunksAffected() + " chunk(s) will be loaded.");
|
||||
|
||||
restore.restore();
|
||||
|
||||
if (restore.hadTotalFailure()) {
|
||||
String error = restore.getLastErrorMessage();
|
||||
if (error != null) {
|
||||
player.printError("Errors prevented any blocks from being restored.");
|
||||
player.printError("Last error: " + error);
|
||||
} else {
|
||||
player.printError("No chunks could be loaded. (Bad archive?)");
|
||||
}
|
||||
} else {
|
||||
player.print(String.format("Restored; %d "
|
||||
+ "missing chunks and %d other errors.",
|
||||
restore.getMissingChunks().size(),
|
||||
restore.getErrorChunks().size()));
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
chunkStore.close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.command.tool.AreaPickaxe;
|
||||
import com.sk89q.worldedit.command.tool.RecursivePickaxe;
|
||||
import com.sk89q.worldedit.command.tool.SinglePickaxe;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
|
||||
public class SuperPickaxeCommands {
|
||||
private final WorldEdit we;
|
||||
|
||||
public SuperPickaxeCommands(WorldEdit we) {
|
||||
this.we = we;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "single" },
|
||||
usage = "",
|
||||
desc = "Enable the single block super pickaxe mode",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.superpickaxe")
|
||||
public void single(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
session.setSuperPickaxe(new SinglePickaxe());
|
||||
session.enableSuperPickAxe();
|
||||
player.print("Mode changed. Left click with a pickaxe. // to disable.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "area" },
|
||||
usage = "<radius>",
|
||||
desc = "Enable the area super pickaxe pickaxe mode",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.superpickaxe.area")
|
||||
public void area(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
int range = args.getInteger(0);
|
||||
|
||||
if (range > config.maxSuperPickaxeSize) {
|
||||
player.printError("Maximum range: " + config.maxSuperPickaxeSize);
|
||||
return;
|
||||
}
|
||||
|
||||
session.setSuperPickaxe(new AreaPickaxe(range));
|
||||
session.enableSuperPickAxe();
|
||||
player.print("Mode changed. Left click with a pickaxe. // to disable.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "recur", "recursive" },
|
||||
usage = "<radius>",
|
||||
desc = "Enable the recursive super pickaxe pickaxe mode",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.superpickaxe.recursive")
|
||||
public void recursive(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
double range = args.getDouble(0);
|
||||
|
||||
if (range > config.maxSuperPickaxeSize) {
|
||||
player.printError("Maximum range: " + config.maxSuperPickaxeSize);
|
||||
return;
|
||||
}
|
||||
|
||||
session.setSuperPickaxe(new RecursivePickaxe(range));
|
||||
session.enableSuperPickAxe();
|
||||
player.print("Mode changed. Left click with a pickaxe. // to disable.");
|
||||
}
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.ItemType;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.patterns.Pattern;
|
||||
import com.sk89q.worldedit.command.tool.*;
|
||||
import com.sk89q.worldedit.util.TreeGenerator;
|
||||
|
||||
public class ToolCommands {
|
||||
private final WorldEdit we;
|
||||
|
||||
public ToolCommands(WorldEdit we) {
|
||||
this.we = we;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "none" },
|
||||
usage = "",
|
||||
desc = "Unbind a bound tool from your current item",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
public void none(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
session.setTool(player.getItemInHand(), null);
|
||||
player.print("Tool unbound from your current item.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "info" },
|
||||
usage = "",
|
||||
desc = "Block information tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.info")
|
||||
public void info(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
session.setTool(player.getItemInHand(), new QueryTool());
|
||||
player.print("Info tool bound to "
|
||||
+ ItemType.toHeldName(player.getItemInHand()) + ".");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "tree" },
|
||||
usage = "[type]",
|
||||
desc = "Tree generator tool",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.tree")
|
||||
@SuppressWarnings("deprecation")
|
||||
public void tree(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
TreeGenerator.TreeType type = args.argsLength() > 0 ?
|
||||
type = TreeGenerator.lookup(args.getString(0))
|
||||
: TreeGenerator.TreeType.TREE;
|
||||
|
||||
if (type == null) {
|
||||
player.printError("Tree type '" + args.getString(0) + "' is unknown.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.setTool(player.getItemInHand(), new TreePlanter(new TreeGenerator(type)));
|
||||
player.print("Tree tool bound to "
|
||||
+ ItemType.toHeldName(player.getItemInHand()) + ".");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "repl" },
|
||||
usage = "<block>",
|
||||
desc = "Block replacer tool",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.replacer")
|
||||
public void repl(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
BaseBlock targetBlock = we.getBlock(player, args.getString(0));
|
||||
session.setTool(player.getItemInHand(), new BlockReplacer(targetBlock));
|
||||
player.print("Block replacer tool bound to "
|
||||
+ ItemType.toHeldName(player.getItemInHand()) + ".");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "cycler" },
|
||||
usage = "",
|
||||
desc = "Block data cycler tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.data-cycler")
|
||||
public void cycler(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
session.setTool(player.getItemInHand(), new BlockDataCyler());
|
||||
player.print("Block data cycler tool bound to "
|
||||
+ ItemType.toHeldName(player.getItemInHand()) + ".");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "floodfill", "flood" },
|
||||
usage = "<pattern> <range>",
|
||||
desc = "Flood fill tool",
|
||||
min = 2,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.flood-fill")
|
||||
public void floodFill(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
int range = args.getInteger(1);
|
||||
|
||||
if (range > config.maxSuperPickaxeSize) {
|
||||
player.printError("Maximum range: " + config.maxSuperPickaxeSize);
|
||||
return;
|
||||
}
|
||||
|
||||
Pattern pattern = we.getBlockPattern(player, args.getString(0));
|
||||
session.setTool(player.getItemInHand(), new FloodFillTool(range, pattern));
|
||||
player.print("Block flood fill tool bound to "
|
||||
+ ItemType.toHeldName(player.getItemInHand()) + ".");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "deltree" },
|
||||
usage = "",
|
||||
desc = "Floating tree remover tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.deltree")
|
||||
public void deltree(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
session.setTool(player.getItemInHand(), new FloatingTreeRemover());
|
||||
player.print("Floating tree remover tool bound to "
|
||||
+ ItemType.toHeldName(player.getItemInHand()) + ".");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "farwand" },
|
||||
usage = "",
|
||||
desc = "Wand at a distance tool",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.farwand")
|
||||
public void farwand(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
session.setTool(player.getItemInHand(), new DistanceWand());
|
||||
player.print("Far wand tool bound to " + ItemType.toHeldName(player.getItemInHand()) + ".");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "lrbuild", "/lrbuild" },
|
||||
usage = "<leftclick block> <rightclick block>",
|
||||
desc = "Long-range building tool",
|
||||
min = 2,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.tool.lrbuild")
|
||||
public void longrangebuildtool(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
BaseBlock secondary = we.getBlock(player, args.getString(0));
|
||||
BaseBlock primary = we.getBlock(player, args.getString(1));
|
||||
session.setTool(player.getItemInHand(), new LongRangeBuildTool(primary, secondary));
|
||||
player.print("Long-range building tool bound to " + ItemType.toHeldName(player.getItemInHand()) + ".");
|
||||
player.print("Left-click set to " + ItemType.toName(secondary.getType()) + "; right-click set to "
|
||||
+ ItemType.toName(primary.getType()) + ".");
|
||||
}
|
||||
}
|
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
|
||||
/**
|
||||
* Tool commands.
|
||||
*/
|
||||
public class ToolUtilCommands {
|
||||
private final WorldEdit we;
|
||||
|
||||
public ToolUtilCommands(WorldEdit we) {
|
||||
this.we = we;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/", "," },
|
||||
usage = "[on|off]",
|
||||
desc = "Toggle the super pickaxe function",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.superpickaxe")
|
||||
public void togglePickaxe(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
String newState = args.getString(0, null);
|
||||
if (session.hasSuperPickAxe()) {
|
||||
if ("on".equals(newState)) {
|
||||
player.printError("Super pick axe already enabled.");
|
||||
return;
|
||||
}
|
||||
|
||||
session.disableSuperPickAxe();
|
||||
player.print("Super pick axe disabled.");
|
||||
} else {
|
||||
if ("off".equals(newState)) {
|
||||
player.printError("Super pick axe already disabled.");
|
||||
return;
|
||||
}
|
||||
session.enableSuperPickAxe();
|
||||
player.print("Super pick axe enabled.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "mask" },
|
||||
usage = "[mask]",
|
||||
desc = "Set the brush mask",
|
||||
min = 0,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.options.mask")
|
||||
public void mask(Player player, LocalSession session, EditSession editSession, @Optional Mask mask) throws WorldEditException {
|
||||
if (mask == null) {
|
||||
session.getBrushTool(player.getItemInHand()).setMask(null);
|
||||
player.print("Brush mask disabled.");
|
||||
} else {
|
||||
session.getBrushTool(player.getItemInHand()).setMask(mask);
|
||||
player.print("Brush mask set.");
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "mat", "material" },
|
||||
usage = "[pattern]",
|
||||
desc = "Set the brush material",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.options.material")
|
||||
public void material(Player player, LocalSession session, EditSession editSession, Pattern pattern) throws WorldEditException {
|
||||
session.getBrushTool(player.getItemInHand()).setFill(pattern);
|
||||
player.print("Brush material set.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "range" },
|
||||
usage = "[pattern]",
|
||||
desc = "Set the brush range",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.options.range")
|
||||
public void range(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
int range = args.getInteger(0);
|
||||
session.getBrushTool(player.getItemInHand()).setRange(range);
|
||||
player.print("Brush range set.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "size" },
|
||||
usage = "[pattern]",
|
||||
desc = "Set the brush size",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.brush.options.size")
|
||||
public void size(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
int radius = args.getInteger(0);
|
||||
we.checkMaxBrushRadius(radius);
|
||||
|
||||
session.getBrushTool(player.getItemInHand()).setSize(radius);
|
||||
player.print("Brush size set.");
|
||||
}
|
||||
}
|
@ -0,0 +1,675 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.google.common.base.Joiner;
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.minecraft.util.commands.Logging;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.command.util.CreatureButcher;
|
||||
import com.sk89q.worldedit.command.util.EntityRemover;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.CommandManager;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
||||
import com.sk89q.worldedit.internal.expression.Expression;
|
||||
import com.sk89q.worldedit.internal.expression.ExpressionException;
|
||||
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
|
||||
import com.sk89q.worldedit.patterns.Pattern;
|
||||
import com.sk89q.worldedit.patterns.SingleBlockPattern;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.CylinderRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.util.command.CommandCallable;
|
||||
import com.sk89q.worldedit.util.command.CommandMapping;
|
||||
import com.sk89q.worldedit.util.command.Dispatcher;
|
||||
import com.sk89q.worldedit.util.command.PrimaryAliasComparator;
|
||||
import com.sk89q.worldedit.util.command.binding.Text;
|
||||
import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
|
||||
import com.sk89q.worldedit.util.formatting.Style;
|
||||
import com.sk89q.worldedit.util.formatting.StyledFragment;
|
||||
import com.sk89q.worldedit.util.formatting.component.Code;
|
||||
import com.sk89q.worldedit.util.formatting.component.CommandListBox;
|
||||
import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
|
||||
|
||||
/**
|
||||
* Utility commands.
|
||||
*/
|
||||
public class UtilityCommands {
|
||||
|
||||
private final WorldEdit we;
|
||||
|
||||
public UtilityCommands(WorldEdit we) {
|
||||
this.we = we;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/fill" },
|
||||
usage = "<block> <radius> [depth]",
|
||||
desc = "Fill a hole",
|
||||
min = 2,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.fill")
|
||||
@Logging(PLACEMENT)
|
||||
public void fill(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
Pattern pattern = we.getBlockPattern(player, args.getString(0));
|
||||
double radius = Math.max(1, args.getDouble(1));
|
||||
we.checkMaxRadius(radius);
|
||||
int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : 1;
|
||||
|
||||
Vector pos = session.getPlacementPosition(player);
|
||||
int affected = 0;
|
||||
if (pattern instanceof SingleBlockPattern) {
|
||||
affected = editSession.fillXZ(pos,
|
||||
((SingleBlockPattern) pattern).getBlock(),
|
||||
radius, depth, false);
|
||||
} else {
|
||||
affected = editSession.fillXZ(pos, pattern, radius, depth, false);
|
||||
}
|
||||
player.print(affected + " block(s) have been created.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/fillr" },
|
||||
usage = "<block> <radius> [depth]",
|
||||
desc = "Fill a hole recursively",
|
||||
min = 2,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.fill.recursive")
|
||||
@Logging(PLACEMENT)
|
||||
public void fillr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
Pattern pattern = we.getBlockPattern(player, args.getString(0));
|
||||
double radius = Math.max(1, args.getDouble(1));
|
||||
we.checkMaxRadius(radius);
|
||||
int depth = args.argsLength() > 2 ? Math.max(1, args.getInteger(2)) : Integer.MAX_VALUE;
|
||||
|
||||
Vector pos = session.getPlacementPosition(player);
|
||||
int affected = 0;
|
||||
if (pattern instanceof SingleBlockPattern) {
|
||||
affected = editSession.fillXZ(pos,
|
||||
((SingleBlockPattern) pattern).getBlock(),
|
||||
radius, depth, true);
|
||||
} else {
|
||||
affected = editSession.fillXZ(pos, pattern, radius, depth, true);
|
||||
}
|
||||
player.print(affected + " block(s) have been created.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/drain" },
|
||||
usage = "<radius>",
|
||||
desc = "Drain a pool",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.drain")
|
||||
@Logging(PLACEMENT)
|
||||
public void drain(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
double radius = Math.max(0, args.getDouble(0));
|
||||
we.checkMaxRadius(radius);
|
||||
int affected = editSession.drainArea(
|
||||
session.getPlacementPosition(player), radius);
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/fixlava", "fixlava" },
|
||||
usage = "<radius>",
|
||||
desc = "Fix lava to be stationary",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.fixlava")
|
||||
@Logging(PLACEMENT)
|
||||
public void fixLava(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
double radius = Math.max(0, args.getDouble(0));
|
||||
we.checkMaxRadius(radius);
|
||||
int affected = editSession.fixLiquid(
|
||||
session.getPlacementPosition(player), radius, 10, 11);
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/fixwater", "fixwater" },
|
||||
usage = "<radius>",
|
||||
desc = "Fix water to be stationary",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.fixwater")
|
||||
@Logging(PLACEMENT)
|
||||
public void fixWater(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
double radius = Math.max(0, args.getDouble(0));
|
||||
we.checkMaxRadius(radius);
|
||||
int affected = editSession.fixLiquid(
|
||||
session.getPlacementPosition(player), radius, 8, 9);
|
||||
player.print(affected + " block(s) have been changed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/removeabove", "removeabove" },
|
||||
usage = "[size] [height]",
|
||||
desc = "Remove blocks above your head.",
|
||||
min = 0,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.removeabove")
|
||||
@Logging(PLACEMENT)
|
||||
public void removeAbove(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1;
|
||||
we.checkMaxRadius(size);
|
||||
World world = player.getWorld();
|
||||
int height = args.argsLength() > 1 ? Math.min((world.getMaxY() + 1), args.getInteger(1) + 2) : (world.getMaxY() + 1);
|
||||
|
||||
int affected = editSession.removeAbove(
|
||||
session.getPlacementPosition(player), size, height);
|
||||
player.print(affected + " block(s) have been removed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/removebelow", "removebelow" },
|
||||
usage = "[size] [height]",
|
||||
desc = "Remove blocks below you.",
|
||||
min = 0,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.removebelow")
|
||||
@Logging(PLACEMENT)
|
||||
public void removeBelow(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0)) : 1;
|
||||
we.checkMaxRadius(size);
|
||||
World world = player.getWorld();
|
||||
int height = args.argsLength() > 1 ? Math.min((world.getMaxY() + 1), args.getInteger(1) + 2) : (world.getMaxY() + 1);
|
||||
|
||||
int affected = editSession.removeBelow(session.getPlacementPosition(player), size, height);
|
||||
player.print(affected + " block(s) have been removed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/removenear", "removenear" },
|
||||
usage = "<block> [size]",
|
||||
desc = "Remove blocks near you.",
|
||||
min = 1,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.removenear")
|
||||
@Logging(PLACEMENT)
|
||||
public void removeNear(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
BaseBlock block = we.getBlock(player, args.getString(0), true);
|
||||
int size = Math.max(1, args.getInteger(1, 50));
|
||||
we.checkMaxRadius(size);
|
||||
|
||||
int affected = editSession.removeNear(session.getPlacementPosition(player), block.getType(), size);
|
||||
player.print(affected + " block(s) have been removed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/replacenear", "replacenear" },
|
||||
usage = "<size> <from-id> <to-id>",
|
||||
desc = "Replace nearby blocks",
|
||||
flags = "f",
|
||||
min = 3,
|
||||
max = 3
|
||||
)
|
||||
@CommandPermissions("worldedit.replacenear")
|
||||
@Logging(PLACEMENT)
|
||||
public void replaceNear(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
int size = Math.max(1, args.getInteger(0));
|
||||
int affected;
|
||||
Set<BaseBlock> from;
|
||||
Pattern to;
|
||||
if (args.argsLength() == 2) {
|
||||
from = null;
|
||||
to = we.getBlockPattern(player, args.getString(1));
|
||||
} else {
|
||||
from = we.getBlocks(player, args.getString(1), true, !args.hasFlag('f'));
|
||||
to = we.getBlockPattern(player, args.getString(2));
|
||||
}
|
||||
|
||||
Vector base = session.getPlacementPosition(player);
|
||||
Vector min = base.subtract(size, size, size);
|
||||
Vector max = base.add(size, size, size);
|
||||
Region region = new CuboidRegion(player.getWorld(), min, max);
|
||||
|
||||
if (to instanceof SingleBlockPattern) {
|
||||
affected = editSession.replaceBlocks(region, from, ((SingleBlockPattern) to).getBlock());
|
||||
} else {
|
||||
affected = editSession.replaceBlocks(region, from, to);
|
||||
}
|
||||
player.print(affected + " block(s) have been replaced.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/snow", "snow" },
|
||||
usage = "[radius]",
|
||||
desc = "Simulates snow",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.snow")
|
||||
@Logging(PLACEMENT)
|
||||
public void snow(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
|
||||
|
||||
int affected = editSession.simulateSnow(session.getPlacementPosition(player), size);
|
||||
player.print(affected + " surfaces covered. Let it snow~");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = {"/thaw", "thaw"},
|
||||
usage = "[radius]",
|
||||
desc = "Thaws the area",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.thaw")
|
||||
@Logging(PLACEMENT)
|
||||
public void thaw(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
|
||||
|
||||
int affected = editSession.thaw(session.getPlacementPosition(player), size);
|
||||
player.print(affected + " surfaces thawed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/green", "green" },
|
||||
usage = "[radius]",
|
||||
desc = "Greens the area",
|
||||
flags = "f",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.green")
|
||||
@Logging(PLACEMENT)
|
||||
public void green(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
final double size = args.argsLength() > 0 ? Math.max(1, args.getDouble(0)) : 10;
|
||||
final boolean onlyNormalDirt = !args.hasFlag('f');
|
||||
|
||||
final int affected = editSession.green(session.getPlacementPosition(player), size, onlyNormalDirt);
|
||||
player.print(affected + " surfaces greened.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/ex", "/ext", "/extinguish", "ex", "ext", "extinguish" },
|
||||
usage = "[radius]",
|
||||
desc = "Extinguish nearby fire",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.extinguish")
|
||||
@Logging(PLACEMENT)
|
||||
public void extinguish(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
|
||||
int defaultRadius = config.maxRadius != -1 ? Math.min(40, config.maxRadius) : 40;
|
||||
int size = args.argsLength() > 0 ? Math.max(1, args.getInteger(0))
|
||||
: defaultRadius;
|
||||
we.checkMaxRadius(size);
|
||||
|
||||
int affected = editSession.removeNear(session.getPlacementPosition(player), 51, size);
|
||||
player.print(affected + " block(s) have been removed.");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "butcher" },
|
||||
usage = "[radius]",
|
||||
flags = "plangbtf",
|
||||
desc = "Kill all or nearby mobs",
|
||||
help =
|
||||
"Kills nearby mobs, based on radius, if none is given uses default in configuration.\n" +
|
||||
"Flags:" +
|
||||
" -p also kills pets.\n" +
|
||||
" -n also kills NPCs.\n" +
|
||||
" -g also kills Golems.\n" +
|
||||
" -a also kills animals.\n" +
|
||||
" -b also kills ambient mobs.\n" +
|
||||
" -t also kills mobs with name tags.\n" +
|
||||
" -f compounds all previous flags.\n" +
|
||||
" -l currently does nothing.",
|
||||
min = 0,
|
||||
max = 1
|
||||
)
|
||||
@CommandPermissions("worldedit.butcher")
|
||||
@Logging(PLACEMENT)
|
||||
public void butcher(Actor actor, CommandContext args) throws WorldEditException {
|
||||
LocalConfiguration config = we.getConfiguration();
|
||||
Player player = actor instanceof Player ? (Player) actor : null;
|
||||
|
||||
// technically the default can be larger than the max, but that's not my problem
|
||||
int radius = config.butcherDefaultRadius;
|
||||
|
||||
// there might be a better way to do this but my brain is fried right now
|
||||
if (args.argsLength() > 0) { // user inputted radius, override the default
|
||||
radius = args.getInteger(0);
|
||||
if (config.butcherMaxRadius != -1) { // clamp if there is a max
|
||||
if (radius == -1) {
|
||||
radius = config.butcherMaxRadius;
|
||||
} else { // Math.min does not work if radius is -1 (actually highest possible value)
|
||||
radius = Math.min(radius, config.butcherMaxRadius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CreatureButcher flags = new CreatureButcher(actor);
|
||||
flags.fromCommand(args);
|
||||
|
||||
List<EntityVisitor> visitors = new ArrayList<EntityVisitor>();
|
||||
LocalSession session = null;
|
||||
EditSession editSession = null;
|
||||
|
||||
if (player != null) {
|
||||
session = we.getSessionManager().get(player);
|
||||
Vector center = session.getPlacementPosition(player);
|
||||
editSession = session.createEditSession(player);
|
||||
List<? extends Entity> entities;
|
||||
if (radius >= 0) {
|
||||
CylinderRegion region = CylinderRegion.createRadius(editSession, center, radius);
|
||||
entities = editSession.getEntities(region);
|
||||
} else {
|
||||
entities = editSession.getEntities();
|
||||
}
|
||||
visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction(editSession.getWorld().getWorldData().getEntityRegistry())));
|
||||
} else {
|
||||
Platform platform = we.getPlatformManager().queryCapability(Capability.WORLD_EDITING);
|
||||
for (World world : platform.getWorlds()) {
|
||||
List<? extends Entity> entities = world.getEntities();
|
||||
visitors.add(new EntityVisitor(entities.iterator(), flags.createFunction(world.getWorldData().getEntityRegistry())));
|
||||
}
|
||||
}
|
||||
|
||||
int killed = 0;
|
||||
for (EntityVisitor visitor : visitors) {
|
||||
Operations.completeLegacy(visitor);
|
||||
killed += visitor.getAffected();
|
||||
}
|
||||
|
||||
if (radius < 0) {
|
||||
actor.print("Killed " + killed + " mobs.");
|
||||
} else {
|
||||
actor.print("Killed " + killed + " mobs in a radius of " + radius + ".");
|
||||
}
|
||||
|
||||
if (editSession != null) {
|
||||
session.remember(editSession);
|
||||
editSession.flushQueue();
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "remove", "rem", "rement" },
|
||||
usage = "<type> <radius>",
|
||||
desc = "Remove all entities of a type",
|
||||
min = 2,
|
||||
max = 2
|
||||
)
|
||||
@CommandPermissions("worldedit.remove")
|
||||
@Logging(PLACEMENT)
|
||||
public void remove(Actor actor, CommandContext args) throws WorldEditException, CommandException {
|
||||
String typeStr = args.getString(0);
|
||||
int radius = args.getInteger(1);
|
||||
Player player = actor instanceof Player ? (Player) actor : null;
|
||||
|
||||
if (radius < -1) {
|
||||
actor.printError("Use -1 to remove all entities in loaded chunks");
|
||||
return;
|
||||
}
|
||||
|
||||
EntityRemover remover = new EntityRemover();
|
||||
remover.fromString(typeStr);
|
||||
|
||||
List<EntityVisitor> visitors = new ArrayList<EntityVisitor>();
|
||||
LocalSession session = null;
|
||||
EditSession editSession = null;
|
||||
|
||||
if (player != null) {
|
||||
session = we.getSessionManager().get(player);
|
||||
Vector center = session.getPlacementPosition(player);
|
||||
editSession = session.createEditSession(player);
|
||||
List<? extends Entity> entities;
|
||||
if (radius >= 0) {
|
||||
CylinderRegion region = CylinderRegion.createRadius(editSession, center, radius);
|
||||
entities = editSession.getEntities(region);
|
||||
} else {
|
||||
entities = editSession.getEntities();
|
||||
}
|
||||
visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction(editSession.getWorld().getWorldData().getEntityRegistry())));
|
||||
} else {
|
||||
Platform platform = we.getPlatformManager().queryCapability(Capability.WORLD_EDITING);
|
||||
for (World world : platform.getWorlds()) {
|
||||
List<? extends Entity> entities = world.getEntities();
|
||||
visitors.add(new EntityVisitor(entities.iterator(), remover.createFunction(world.getWorldData().getEntityRegistry())));
|
||||
}
|
||||
}
|
||||
|
||||
int removed = 0;
|
||||
for (EntityVisitor visitor : visitors) {
|
||||
Operations.completeLegacy(visitor);
|
||||
removed += visitor.getAffected();
|
||||
}
|
||||
|
||||
actor.print("Marked " + (removed != 1 ? "entities" : "entity") + " for removal.");
|
||||
|
||||
if (editSession != null) {
|
||||
session.remember(editSession);
|
||||
editSession.flushQueue();
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/calc", "/calculate", "/eval", "/evaluate", "/solve" },
|
||||
usage = "<expression>",
|
||||
desc = "Evaluate a mathematical expression"
|
||||
)
|
||||
public void calc(Actor actor, @Text String input) throws CommandException {
|
||||
try {
|
||||
Expression expression = Expression.compile(input);
|
||||
actor.print("= " + expression.evaluate());
|
||||
} catch (EvaluationException e) {
|
||||
actor.printError(String.format(
|
||||
"'%s' could not be parsed as a valid expression", input));
|
||||
} catch (ExpressionException e) {
|
||||
actor.printError(String.format(
|
||||
"'%s' could not be evaluated (error: %s)", input, e.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "/help" },
|
||||
usage = "[<command>]",
|
||||
desc = "Displays help for WorldEdit commands",
|
||||
min = 0,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.help")
|
||||
public void help(Actor actor, CommandContext args) throws WorldEditException {
|
||||
help(args, we, actor);
|
||||
}
|
||||
|
||||
private static CommandMapping detectCommand(Dispatcher dispatcher, String command, boolean isRootLevel) {
|
||||
CommandMapping mapping;
|
||||
|
||||
// First try the command as entered
|
||||
mapping = dispatcher.get(command);
|
||||
if (mapping != null) {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
// Then if we're looking at root commands and the user didn't use
|
||||
// any slashes, let's try double slashes and then single slashes.
|
||||
// However, be aware that there exists different single slash
|
||||
// and double slash commands in WorldEdit
|
||||
if (isRootLevel && !command.contains("/")) {
|
||||
mapping = dispatcher.get("//" + command);
|
||||
if (mapping != null) {
|
||||
return mapping;
|
||||
}
|
||||
|
||||
mapping = dispatcher.get("/" + command);
|
||||
if (mapping != null) {
|
||||
return mapping;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void help(CommandContext args, WorldEdit we, Actor actor) {
|
||||
CommandCallable callable = we.getPlatformManager().getCommandManager().getDispatcher();
|
||||
|
||||
int page = 0;
|
||||
final int perPage = actor instanceof Player ? 8 : 20; // More pages for console
|
||||
int effectiveLength = args.argsLength();
|
||||
|
||||
// Detect page from args
|
||||
try {
|
||||
if (args.argsLength() > 0) {
|
||||
page = args.getInteger(args.argsLength() - 1);
|
||||
if (page <= 0) {
|
||||
page = 1;
|
||||
} else {
|
||||
page--;
|
||||
}
|
||||
|
||||
effectiveLength--;
|
||||
}
|
||||
} catch (NumberFormatException ignored) {
|
||||
}
|
||||
|
||||
boolean isRootLevel = true;
|
||||
List<String> visited = new ArrayList<String>();
|
||||
|
||||
// Drill down to the command
|
||||
for (int i = 0; i < effectiveLength; i++) {
|
||||
String command = args.getString(i);
|
||||
|
||||
if (callable instanceof Dispatcher) {
|
||||
// Chop off the beginning / if we're are the root level
|
||||
if (isRootLevel && command.length() > 1 && command.charAt(0) == '/') {
|
||||
command = command.substring(1);
|
||||
}
|
||||
|
||||
CommandMapping mapping = detectCommand((Dispatcher) callable, command, isRootLevel);
|
||||
if (mapping != null) {
|
||||
callable = mapping.getCallable();
|
||||
} else {
|
||||
if (isRootLevel) {
|
||||
actor.printError(String.format("The command '%s' could not be found.", args.getString(i)));
|
||||
return;
|
||||
} else {
|
||||
actor.printError(String.format("The sub-command '%s' under '%s' could not be found.",
|
||||
command, Joiner.on(" ").join(visited)));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
visited.add(args.getString(i));
|
||||
isRootLevel = false;
|
||||
} else {
|
||||
actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)",
|
||||
Joiner.on(" ").join(visited), command));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the message
|
||||
if (callable instanceof Dispatcher) {
|
||||
Dispatcher dispatcher = (Dispatcher) callable;
|
||||
|
||||
// Get a list of aliases
|
||||
List<CommandMapping> aliases = new ArrayList<CommandMapping>(dispatcher.getCommands());
|
||||
Collections.sort(aliases, new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN));
|
||||
|
||||
// Calculate pagination
|
||||
int offset = perPage * page;
|
||||
int pageTotal = (int) Math.ceil(aliases.size() / (double) perPage);
|
||||
|
||||
// Box
|
||||
CommandListBox box = new CommandListBox(String.format("Help: page %d/%d ", page + 1, pageTotal));
|
||||
StyledFragment contents = box.getContents();
|
||||
StyledFragment tip = contents.createFragment(Style.GRAY);
|
||||
|
||||
if (offset >= aliases.size()) {
|
||||
tip.createFragment(Style.RED).append(String.format("There is no page %d (total number of pages is %d).", page + 1, pageTotal)).newLine();
|
||||
} else {
|
||||
List<CommandMapping> list = aliases.subList(offset, Math.min(offset + perPage, aliases.size()));
|
||||
|
||||
tip.append("Type ");
|
||||
tip.append(new Code().append("//help ").append("<command> [<page>]"));
|
||||
tip.append(" for more information.").newLine();
|
||||
|
||||
// Add each command
|
||||
for (CommandMapping mapping : list) {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (isRootLevel) {
|
||||
builder.append("/");
|
||||
}
|
||||
if (!visited.isEmpty()) {
|
||||
builder.append(Joiner.on(" ").join(visited));
|
||||
builder.append(" ");
|
||||
}
|
||||
builder.append(mapping.getPrimaryAlias());
|
||||
box.appendCommand(builder.toString(), mapping.getDescription().getShortDescription());
|
||||
}
|
||||
}
|
||||
|
||||
actor.printRaw(ColorCodeBuilder.asColorCodes(box));
|
||||
} else {
|
||||
CommandUsageBox box = new CommandUsageBox(callable, Joiner.on(" ").join(visited));
|
||||
actor.printRaw(ColorCodeBuilder.asColorCodes(box));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,124 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.Command;
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.minecraft.util.commands.CommandPermissions;
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Capability;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.extension.platform.PlatformManager;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.TimeZone;
|
||||
|
||||
public class WorldEditCommands {
|
||||
private static final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
|
||||
|
||||
private final WorldEdit we;
|
||||
|
||||
public WorldEditCommands(WorldEdit we) {
|
||||
this.we = we;
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "version", "ver" },
|
||||
usage = "",
|
||||
desc = "Get WorldEdit version",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
public void version(Actor actor) throws WorldEditException {
|
||||
actor.print("WorldEdit version " + WorldEdit.getVersion());
|
||||
actor.print("https://github.com/sk89q/worldedit/");
|
||||
|
||||
PlatformManager pm = we.getPlatformManager();
|
||||
|
||||
actor.printDebug("----------- Platforms -----------");
|
||||
for (Platform platform : pm.getPlatforms()) {
|
||||
actor.printDebug(String.format("* %s (%s)", platform.getPlatformName(), platform.getPlatformVersion()));
|
||||
}
|
||||
|
||||
actor.printDebug("----------- Capabilities -----------");
|
||||
for (Capability capability : Capability.values()) {
|
||||
Platform platform = pm.queryCapability(capability);
|
||||
actor.printDebug(String.format("%s: %s", capability.name(), platform != null ? platform.getPlatformName() : "NONE"));
|
||||
}
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "reload" },
|
||||
usage = "",
|
||||
desc = "Reload configuration",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
@CommandPermissions("worldedit.reload")
|
||||
public void reload(Actor actor) throws WorldEditException {
|
||||
we.getServer().reload();
|
||||
we.getEventBus().post(new ConfigurationLoadEvent(we.getPlatformManager().queryCapability(Capability.CONFIGURATION).getConfiguration()));
|
||||
actor.print("Configuration reloaded!");
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "cui" },
|
||||
usage = "",
|
||||
desc = "Complete CUI handshake (internal usage)",
|
||||
min = 0,
|
||||
max = 0
|
||||
)
|
||||
public void cui(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
session.setCUISupport(true);
|
||||
session.dispatchCUISetup(player);
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "tz" },
|
||||
usage = "[timezone]",
|
||||
desc = "Set your timezone for snapshots",
|
||||
min = 1,
|
||||
max = 1
|
||||
)
|
||||
public void tz(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
|
||||
TimeZone tz = TimeZone.getTimeZone(args.getString(0));
|
||||
session.setTimezone(tz);
|
||||
player.print("Timezone set for this session to: " + tz.getDisplayName());
|
||||
player.print("The current time in that timezone is: "
|
||||
+ dateFormat.format(Calendar.getInstance(tz).getTime()));
|
||||
}
|
||||
|
||||
@Command(
|
||||
aliases = { "help" },
|
||||
usage = "[<command>]",
|
||||
desc = "Displays help for WorldEdit commands",
|
||||
min = 0,
|
||||
max = -1
|
||||
)
|
||||
@CommandPermissions("worldedit.help")
|
||||
public void help(Actor actor, CommandContext args) throws WorldEditException {
|
||||
UtilityCommands.help(args, we, actor);
|
||||
}
|
||||
}
|
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
/**
|
||||
* A super pickaxe mode that will remove blocks in an area.
|
||||
*/
|
||||
public class AreaPickaxe implements BlockTool {
|
||||
|
||||
private static final BaseBlock air = new BaseBlock(0);
|
||||
private int range;
|
||||
|
||||
public AreaPickaxe(int range) {
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission("worldedit.superpickaxe.area");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) {
|
||||
int ox = clicked.getBlockX();
|
||||
int oy = clicked.getBlockY();
|
||||
int oz = clicked.getBlockZ();
|
||||
int initialType = ((World) clicked.getExtent()).getBlockType(clicked.toVector());
|
||||
|
||||
if (initialType == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (initialType == BlockID.BEDROCK && !player.canDestroyBedrock()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
EditSession editSession = session.createEditSession(player);
|
||||
editSession.getSurvivalExtent().setToolUse(config.superPickaxeManyDrop);
|
||||
|
||||
try {
|
||||
for (int x = ox - range; x <= ox + range; ++x) {
|
||||
for (int y = oy - range; y <= oy + range; ++y) {
|
||||
for (int z = oz - range; z <= oz + range; ++z) {
|
||||
Vector pos = new Vector(x, y, z);
|
||||
if (editSession.getBlockType(pos) != initialType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
((World) clicked.getExtent()).queueBlockBreakEffect(server, pos, initialType, clicked.toVector().distanceSq(pos));
|
||||
|
||||
editSession.setBlock(pos, air);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
player.printError("Max blocks change limit reached.");
|
||||
} finally {
|
||||
editSession.flushQueue();
|
||||
session.remember(editSession);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
/**
|
||||
* A mode that cycles the data values of supported blocks.
|
||||
*/
|
||||
public class BlockDataCyler implements DoubleActionBlockTool {
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission("worldedit.tool.data-cycler");
|
||||
}
|
||||
|
||||
private boolean handleCycle(Platform server, LocalConfiguration config,
|
||||
Player player, LocalSession session, Location clicked, boolean forward) {
|
||||
|
||||
World world = (World) clicked.getExtent();
|
||||
|
||||
int type = world.getBlockType(clicked.toVector());
|
||||
int data = world.getBlockData(clicked.toVector());
|
||||
|
||||
if (!config.allowedDataCycleBlocks.isEmpty()
|
||||
&& !player.hasPermission("worldedit.override.data-cycler")
|
||||
&& !config.allowedDataCycleBlocks.contains(type)) {
|
||||
player.printError("You are not permitted to cycle the data value of that block.");
|
||||
return true;
|
||||
}
|
||||
|
||||
int increment = forward ? 1 : -1;
|
||||
data = (new BaseBlock(type, data)).cycleData(increment);
|
||||
|
||||
if (data < 0) {
|
||||
player.printError("That block's data cannot be cycled!");
|
||||
} else {
|
||||
world.setBlockData(clicked.toVector(), data);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) {
|
||||
return handleCycle(server, config, player, session, clicked, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) {
|
||||
return handleCycle(server, config, player, session, clicked, false);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
/**
|
||||
* A mode that replaces one block.
|
||||
*/
|
||||
public class BlockReplacer implements DoubleActionBlockTool {
|
||||
|
||||
private BaseBlock targetBlock;
|
||||
|
||||
public BlockReplacer(BaseBlock targetBlock) {
|
||||
this.targetBlock = targetBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission("worldedit.tool.replacer");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) {
|
||||
BlockBag bag = session.getBlockBag(player);
|
||||
|
||||
World world = (World) clicked.getExtent();
|
||||
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1, bag, player);
|
||||
|
||||
try {
|
||||
editSession.setBlock(clicked.toVector(), targetBlock);
|
||||
} catch (MaxChangedBlocksException ignored) {
|
||||
} finally {
|
||||
if (bag != null) {
|
||||
bag.flushChanges();
|
||||
}
|
||||
session.remember(editSession);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) {
|
||||
World world = (World) clicked.getExtent();
|
||||
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, -1, player);
|
||||
targetBlock = (editSession).getBlock(clicked.toVector());
|
||||
BlockType type = BlockType.fromID(targetBlock.getType());
|
||||
|
||||
if (type != null) {
|
||||
player.print("Replacer tool switched to: " + type.getName());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
|
||||
public interface BlockTool extends Tool {
|
||||
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked);
|
||||
}
|
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.command.tool.brush.Brush;
|
||||
import com.sk89q.worldedit.command.tool.brush.SphereBrush;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.extent.inventory.BlockBag;
|
||||
import com.sk89q.worldedit.function.mask.Mask;
|
||||
import com.sk89q.worldedit.function.mask.MaskIntersection;
|
||||
import com.sk89q.worldedit.function.pattern.BlockPattern;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.session.request.Request;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Builds a shape at the place being looked at.
|
||||
*/
|
||||
public class BrushTool implements TraceTool {
|
||||
|
||||
protected static int MAX_RANGE = 500;
|
||||
protected int range = -1;
|
||||
private Mask mask = null;
|
||||
private Brush brush = new SphereBrush();
|
||||
private Pattern material = new BlockPattern(new BaseBlock(BlockID.COBBLESTONE));
|
||||
private double size = 1;
|
||||
private String permission;
|
||||
|
||||
/**
|
||||
* Construct the tool.
|
||||
*
|
||||
* @param permission the permission to check before use is allowed
|
||||
*/
|
||||
public BrushTool(String permission) {
|
||||
checkNotNull(permission);
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission(permission);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the filter.
|
||||
*
|
||||
* @return the filter
|
||||
*/
|
||||
public Mask getMask() {
|
||||
return mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the block filter used for identifying blocks to replace.
|
||||
*
|
||||
* @param filter the filter to set
|
||||
*/
|
||||
public void setMask(Mask filter) {
|
||||
this.mask = filter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the brush.
|
||||
*
|
||||
* @param brush tbe brush
|
||||
* @param permission the permission
|
||||
*/
|
||||
public void setBrush(Brush brush, String permission) {
|
||||
this.brush = brush;
|
||||
this.permission = permission;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the current brush.
|
||||
*
|
||||
* @return the current brush
|
||||
*/
|
||||
public Brush getBrush() {
|
||||
return brush;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the material.
|
||||
*
|
||||
* @param material the material
|
||||
*/
|
||||
public void setFill(Pattern material) {
|
||||
this.material = material;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the material.
|
||||
*
|
||||
* @return the material
|
||||
*/
|
||||
public Pattern getMaterial() {
|
||||
return material;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set brush size.
|
||||
*
|
||||
* @return a radius
|
||||
*/
|
||||
public double getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the set brush size.
|
||||
*
|
||||
* @param radius a radius
|
||||
*/
|
||||
public void setSize(double radius) {
|
||||
this.size = radius;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the set brush range.
|
||||
*
|
||||
* @return the range of the brush in blocks
|
||||
*/
|
||||
public int getRange() {
|
||||
return (range < 0) ? MAX_RANGE : Math.min(range, MAX_RANGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the set brush range.
|
||||
*
|
||||
* @param range the range of the brush in blocks
|
||||
*/
|
||||
public void setRange(int range) {
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
|
||||
WorldVector target = null;
|
||||
target = player.getBlockTrace(getRange(), true);
|
||||
|
||||
if (target == null) {
|
||||
player.printError("No block in sight!");
|
||||
return true;
|
||||
}
|
||||
|
||||
BlockBag bag = session.getBlockBag(player);
|
||||
|
||||
EditSession editSession = session.createEditSession(player);
|
||||
Request.request().setEditSession(editSession);
|
||||
if (mask != null) {
|
||||
Mask existingMask = editSession.getMask();
|
||||
|
||||
if (existingMask == null) {
|
||||
editSession.setMask(mask);
|
||||
} else if (existingMask instanceof MaskIntersection) {
|
||||
((MaskIntersection) existingMask).add(mask);
|
||||
} else {
|
||||
MaskIntersection newMask = new MaskIntersection(existingMask);
|
||||
newMask.add(mask);
|
||||
editSession.setMask(newMask);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
brush.build(editSession, target, material, size);
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
player.printError("Max blocks change limit reached.");
|
||||
} finally {
|
||||
if (bag != null) {
|
||||
bag.flushChanges();
|
||||
}
|
||||
session.remember(editSession);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
|
||||
/**
|
||||
* A wand that can be used at a distance.
|
||||
*/
|
||||
public class DistanceWand extends BrushTool implements DoubleActionTraceTool {
|
||||
|
||||
public DistanceWand() {
|
||||
super("worldedit.wand");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission("worldedit.wand");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
|
||||
if (session.isToolControlEnabled() && player.hasPermission("worldedit.selection.pos")) {
|
||||
WorldVector target = getTarget(player);
|
||||
if (target == null) return true;
|
||||
|
||||
RegionSelector selector = session.getRegionSelector(player.getWorld());
|
||||
if (selector.selectPrimary(target, ActorSelectorLimits.forActor(player))) {
|
||||
selector.explainPrimarySelection(player, session, target);
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
|
||||
if (session.isToolControlEnabled() && player.hasPermission("worldedit.selection.pos")) {
|
||||
WorldVector target = getTarget(player);
|
||||
if (target == null) return true;
|
||||
|
||||
RegionSelector selector = session.getRegionSelector(player.getWorld());
|
||||
if (selector.selectSecondary(target, ActorSelectorLimits.forActor(player))) {
|
||||
selector.explainSecondarySelection(player, session, target);
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public WorldVector getTarget(Player player) {
|
||||
WorldVector target = null;
|
||||
if (this.range > -1) {
|
||||
target = player.getBlockTrace(getRange(), true);
|
||||
} else {
|
||||
target = player.getBlockTrace(MAX_RANGE);
|
||||
}
|
||||
|
||||
if (target == null) {
|
||||
player.printError("No block in sight!");
|
||||
return null;
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
|
||||
/**
|
||||
* Represents a block tool that also has a secondary/primary function.
|
||||
*/
|
||||
public interface DoubleActionBlockTool extends BlockTool {
|
||||
|
||||
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked);
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
|
||||
/**
|
||||
* Represents a trace tool that also has a secondary/primary function.
|
||||
*/
|
||||
public interface DoubleActionTraceTool extends TraceTool {
|
||||
|
||||
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session);
|
||||
|
||||
}
|
@ -0,0 +1,172 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A pickaxe mode that removes floating treetops (logs and leaves not connected
|
||||
* to anything else)
|
||||
*/
|
||||
public class FloatingTreeRemover implements BlockTool {
|
||||
private static final BaseBlock AIR = new BaseBlock(BlockID.AIR);
|
||||
private int rangeSq;
|
||||
|
||||
public FloatingTreeRemover() {
|
||||
rangeSq = 100*100;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission("worldedit.tool.deltree");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config,
|
||||
Player player, LocalSession session, Location clicked) {
|
||||
|
||||
final World world = (World) clicked.getExtent();
|
||||
|
||||
switch (world.getBlockType(clicked.toVector())) {
|
||||
case BlockID.LOG:
|
||||
case BlockID.LOG2:
|
||||
case BlockID.LEAVES:
|
||||
case BlockID.LEAVES2:
|
||||
case BlockID.BROWN_MUSHROOM_CAP:
|
||||
case BlockID.RED_MUSHROOM_CAP:
|
||||
case BlockID.VINE:
|
||||
break;
|
||||
|
||||
default:
|
||||
player.printError("That's not a tree.");
|
||||
return true;
|
||||
}
|
||||
|
||||
final EditSession editSession = session.createEditSession(player);
|
||||
|
||||
try {
|
||||
final Set<Vector> blockSet = bfs(world, clicked.toVector());
|
||||
if (blockSet == null) {
|
||||
player.printError("That's not a floating tree.");
|
||||
return true;
|
||||
}
|
||||
|
||||
for (Vector blockVector : blockSet) {
|
||||
final int typeId = editSession.getBlock(blockVector).getType();
|
||||
switch (typeId) {
|
||||
case BlockID.LOG:
|
||||
case BlockID.LOG2:
|
||||
case BlockID.LEAVES:
|
||||
case BlockID.LEAVES2:
|
||||
case BlockID.BROWN_MUSHROOM_CAP:
|
||||
case BlockID.RED_MUSHROOM_CAP:
|
||||
case BlockID.VINE:
|
||||
editSession.setBlock(blockVector, AIR);
|
||||
}
|
||||
}
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
player.printError("Max blocks change limit reached.");
|
||||
} finally {
|
||||
session.remember(editSession);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Vector[] recurseDirections = {
|
||||
PlayerDirection.NORTH.vector(),
|
||||
PlayerDirection.EAST.vector(),
|
||||
PlayerDirection.SOUTH.vector(),
|
||||
PlayerDirection.WEST.vector(),
|
||||
PlayerDirection.UP.vector(),
|
||||
PlayerDirection.DOWN.vector(),
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper method.
|
||||
*
|
||||
* @param world the world that contains the tree
|
||||
* @param origin any point contained in the floating tree
|
||||
* @return a set containing all blocks in the tree/shroom or null if this is not a floating tree/shroom.
|
||||
*/
|
||||
private Set<Vector> bfs(World world, Vector origin) throws MaxChangedBlocksException {
|
||||
final Set<Vector> visited = new HashSet<Vector>();
|
||||
final LinkedList<Vector> queue = new LinkedList<Vector>();
|
||||
|
||||
queue.addLast(origin);
|
||||
visited.add(origin);
|
||||
|
||||
while (!queue.isEmpty()) {
|
||||
final Vector current = queue.removeFirst();
|
||||
for (Vector recurseDirection : recurseDirections) {
|
||||
final Vector next = current.add(recurseDirection);
|
||||
if (origin.distanceSq(next) > rangeSq) {
|
||||
// Maximum range exceeded => stop walking
|
||||
continue;
|
||||
}
|
||||
|
||||
if (visited.add(next)) {
|
||||
switch (world.getBlockType(next)) {
|
||||
case BlockID.AIR:
|
||||
case BlockID.SNOW:
|
||||
// we hit air or snow => stop walking this route
|
||||
continue;
|
||||
|
||||
case BlockID.LOG:
|
||||
case BlockID.LOG2:
|
||||
case BlockID.LEAVES:
|
||||
case BlockID.LEAVES2:
|
||||
case BlockID.BROWN_MUSHROOM_CAP:
|
||||
case BlockID.RED_MUSHROOM_CAP:
|
||||
case BlockID.VINE:
|
||||
// queue next point
|
||||
queue.addLast(next);
|
||||
break;
|
||||
|
||||
default:
|
||||
// we hit something solid - evaluate where we came from
|
||||
final int curId = world.getBlockType(current);
|
||||
if (curId == BlockID.LEAVES || curId == BlockID.LEAVES2
|
||||
|| curId == BlockID.VINE) {
|
||||
// leaves touching a wall/the ground => stop walking this route
|
||||
continue;
|
||||
} else {
|
||||
// log/shroom touching a wall/the ground => this is not a floating tree, bail out
|
||||
return null;
|
||||
}
|
||||
} // switch
|
||||
} // if
|
||||
} // for
|
||||
} // while
|
||||
|
||||
return visited;
|
||||
} // bfs
|
||||
}
|
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.patterns.Pattern;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A tool that flood fills blocks.
|
||||
*/
|
||||
public class FloodFillTool implements BlockTool {
|
||||
|
||||
private int range;
|
||||
private Pattern pattern;
|
||||
|
||||
public FloodFillTool(int range, Pattern pattern) {
|
||||
this.range = range;
|
||||
this.pattern = pattern;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission("worldedit.tool.flood-fill");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) {
|
||||
World world = (World) clicked.getExtent();
|
||||
|
||||
int initialType = world.getBlockType(clicked.toVector());
|
||||
|
||||
if (initialType == BlockID.AIR) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (initialType == BlockID.BEDROCK && !player.canDestroyBedrock()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
EditSession editSession = session.createEditSession(player);
|
||||
|
||||
try {
|
||||
recurse(server, editSession, world, clicked.toVector().toBlockVector(),
|
||||
clicked.toVector(), range, initialType, new HashSet<BlockVector>());
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
player.printError("Max blocks change limit reached.");
|
||||
} finally {
|
||||
session.remember(editSession);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void recurse(Platform server, EditSession editSession, World world, BlockVector pos, Vector origin, int size, int initialType,
|
||||
Set<BlockVector> visited) throws MaxChangedBlocksException {
|
||||
|
||||
if (origin.distance(pos) > size || visited.contains(pos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
visited.add(pos);
|
||||
|
||||
if (editSession.getBlock(pos).getType() == initialType) {
|
||||
editSession.setBlock(pos, pattern.next(pos));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
recurse(server, editSession, world, pos.add(1, 0, 0).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
recurse(server, editSession, world, pos.add(-1, 0, 0).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
recurse(server, editSession, world, pos.add(0, 0, 1).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
recurse(server, editSession, world, pos.add(0, 0, -1).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
recurse(server, editSession, world, pos.add(0, 1, 0).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
recurse(server, editSession, world, pos.add(0, -1, 0).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
|
||||
public class InvalidToolBindException extends WorldEditException {
|
||||
|
||||
private int itemId;
|
||||
|
||||
public InvalidToolBindException(int itemId, String msg) {
|
||||
super(msg);
|
||||
this.itemId = itemId;
|
||||
}
|
||||
|
||||
public int getItemId() {
|
||||
return itemId;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
|
||||
/**
|
||||
* A tool that can place (or remove) blocks at a distance.
|
||||
*/
|
||||
public class LongRangeBuildTool extends BrushTool implements DoubleActionTraceTool {
|
||||
|
||||
BaseBlock primary;
|
||||
BaseBlock secondary;
|
||||
|
||||
public LongRangeBuildTool(BaseBlock primary, BaseBlock secondary) {
|
||||
super("worldedit.tool.lrbuild");
|
||||
this.primary = primary;
|
||||
this.secondary = secondary;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission("worldedit.tool.lrbuild");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actSecondary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
|
||||
WorldVectorFace pos = getTargetFace(player);
|
||||
if (pos == null) return false;
|
||||
EditSession eS = session.createEditSession(player);
|
||||
try {
|
||||
if (secondary.getType() == BlockID.AIR) {
|
||||
eS.setBlock(pos, secondary);
|
||||
} else {
|
||||
eS.setBlock(pos.getFaceVector(), secondary);
|
||||
}
|
||||
return true;
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
// one block? eat it
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session) {
|
||||
WorldVectorFace pos = getTargetFace(player);
|
||||
if (pos == null) return false;
|
||||
EditSession eS = session.createEditSession(player);
|
||||
try {
|
||||
if (primary.getType() == BlockID.AIR) {
|
||||
eS.setBlock(pos, primary);
|
||||
} else {
|
||||
eS.setBlock(pos.getFaceVector(), primary);
|
||||
}
|
||||
return true;
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
// one block? eat it
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public WorldVectorFace getTargetFace(Player player) {
|
||||
WorldVectorFace target = null;
|
||||
target = player.getBlockTraceFace(getRange(), true);
|
||||
|
||||
if (target == null) {
|
||||
player.printError("No block in sight!");
|
||||
return null;
|
||||
}
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.WorldEdit;
|
||||
import com.sk89q.worldedit.blocks.*;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
/**
|
||||
* Looks up information about a block.
|
||||
*/
|
||||
public class QueryTool implements BlockTool {
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission("worldedit.tool.info");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) {
|
||||
|
||||
World world = (World) clicked.getExtent();
|
||||
EditSession editSession = WorldEdit.getInstance().getEditSessionFactory().getEditSession(world, 0, player);
|
||||
BaseBlock block = (editSession).rawGetBlock(clicked.toVector());
|
||||
BlockType type = BlockType.fromID(block.getType());
|
||||
|
||||
player.print("\u00A79@" + clicked.toVector() + ": " + "\u00A7e"
|
||||
+ "#" + block.getType() + "\u00A77" + " ("
|
||||
+ (type == null ? "Unknown" : type.getName()) + ") "
|
||||
+ "\u00A7f"
|
||||
+ "[" + block.getData() + "]" + " (" + world.getBlockLightLevel(clicked.toVector()) + "/" + world.getBlockLightLevel(clicked.toVector().add(0, 1, 0)) + ")");
|
||||
|
||||
if (block instanceof MobSpawnerBlock) {
|
||||
player.printRaw("\u00A7e" + "Mob Type: "
|
||||
+ ((MobSpawnerBlock) block).getMobType());
|
||||
} else if (block instanceof NoteBlock) {
|
||||
player.printRaw("\u00A7e" + "Note block: "
|
||||
+ ((NoteBlock) block).getNote());
|
||||
} else if (block.getType() == BlockID.CLOTH) {
|
||||
// Should never be null
|
||||
player.printRaw("\u00A7e" + "Color: "
|
||||
+ ClothColor.fromID(block.getData()).getName());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A pickaxe mode that recursively finds adjacent blocks within range of
|
||||
* an initial block and of the same type.
|
||||
*/
|
||||
public class RecursivePickaxe implements BlockTool {
|
||||
|
||||
private static final BaseBlock air = new BaseBlock(0);
|
||||
private double range;
|
||||
|
||||
public RecursivePickaxe(double range) {
|
||||
this.range = range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission("worldedit.superpickaxe.recursive");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) {
|
||||
World world = (World) clicked.getExtent();
|
||||
|
||||
int initialType = world.getBlockType(clicked.toVector());
|
||||
|
||||
if (initialType == BlockID.AIR) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (initialType == BlockID.BEDROCK && !player.canDestroyBedrock()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
EditSession editSession = session.createEditSession(player);
|
||||
editSession.getSurvivalExtent().setToolUse(config.superPickaxeManyDrop);
|
||||
|
||||
try {
|
||||
recurse(server, editSession, world, clicked.toVector().toBlockVector(),
|
||||
clicked.toVector(), range, initialType, new HashSet<BlockVector>());
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
player.printError("Max blocks change limit reached.");
|
||||
} finally {
|
||||
editSession.flushQueue();
|
||||
session.remember(editSession);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void recurse(Platform server, EditSession editSession, World world, BlockVector pos,
|
||||
Vector origin, double size, int initialType, Set<BlockVector> visited) throws MaxChangedBlocksException {
|
||||
|
||||
final double distanceSq = origin.distanceSq(pos);
|
||||
if (distanceSq > size*size || visited.contains(pos)) {
|
||||
return;
|
||||
}
|
||||
|
||||
visited.add(pos);
|
||||
|
||||
if (editSession.getBlock(pos).getType() != initialType) {
|
||||
return;
|
||||
}
|
||||
|
||||
world.queueBlockBreakEffect(server, pos, initialType, distanceSq);
|
||||
|
||||
editSession.setBlock(pos, air);
|
||||
|
||||
recurse(server, editSession, world, pos.add(1, 0, 0).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
recurse(server, editSession, world, pos.add(-1, 0, 0).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
recurse(server, editSession, world, pos.add(0, 0, 1).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
recurse(server, editSession, world, pos.add(0, 0, -1).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
recurse(server, editSession, world, pos.add(0, 1, 0).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
recurse(server, editSession, world, pos.add(0, -1, 0).toBlockVector(),
|
||||
origin, size, initialType, visited);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
|
||||
/**
|
||||
* A super pickaxe mode that removes one block.
|
||||
*/
|
||||
public class SinglePickaxe implements BlockTool {
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission("worldedit.superpickaxe");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, com.sk89q.worldedit.util.Location clicked) {
|
||||
World world = (World) clicked.getExtent();
|
||||
final int blockType = world.getBlockType(clicked.toVector());
|
||||
if (blockType == BlockID.BEDROCK
|
||||
&& !player.canDestroyBedrock()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
EditSession editSession = session.createEditSession(player);
|
||||
editSession.getSurvivalExtent().setToolUse(config.superPickaxeDrop);
|
||||
|
||||
try {
|
||||
editSession.setBlock(clicked.toVector(), new BaseBlock(BlockID.AIR));
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
player.printError("Max blocks change limit reached.");
|
||||
} finally {
|
||||
editSession.flushQueue();
|
||||
}
|
||||
|
||||
world.playEffect(clicked.toVector(), 2001, blockType);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
|
||||
/**
|
||||
* Represents a tool. This interface alone defines nothing. A tool also
|
||||
* has to implement {@code BlockTool} or {@code TraceTool}.
|
||||
*/
|
||||
public interface Tool {
|
||||
|
||||
/**
|
||||
* Checks to see if the player can still be using this tool (considering
|
||||
* permissions and such).
|
||||
*
|
||||
* @param actor the actor
|
||||
* @return true if use is permitted
|
||||
*/
|
||||
public boolean canUse(Actor actor);
|
||||
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.LocalConfiguration;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
|
||||
public interface TraceTool extends Tool {
|
||||
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session);
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool;
|
||||
|
||||
import com.sk89q.worldedit.*;
|
||||
import com.sk89q.worldedit.entity.Player;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.extension.platform.Platform;
|
||||
import com.sk89q.worldedit.util.*;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
|
||||
/**
|
||||
* Plants a tree.
|
||||
*/
|
||||
public class TreePlanter implements BlockTool {
|
||||
|
||||
private TreeGenerator gen;
|
||||
|
||||
public TreePlanter(TreeGenerator gen) {
|
||||
this.gen = gen;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canUse(Actor player) {
|
||||
return player.hasPermission("worldedit.tool.tree");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean actPrimary(Platform server, LocalConfiguration config, Player player, LocalSession session, Location clicked) {
|
||||
|
||||
EditSession editSession = session.createEditSession(player);
|
||||
|
||||
try {
|
||||
boolean successful = false;
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
if (gen.generate(editSession, clicked.toVector().add(0, 1, 0))) {
|
||||
successful = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!successful) {
|
||||
player.printError("A tree can't go there.");
|
||||
}
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
player.printError("Max. blocks changed reached.");
|
||||
} finally {
|
||||
session.remember(editSession);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
|
||||
/**
|
||||
* A brush is a long-range build tool.
|
||||
*/
|
||||
public interface Brush {
|
||||
|
||||
/**
|
||||
* Build the object.
|
||||
*
|
||||
* @param editSession the {@code EditSession}
|
||||
* @param position the position
|
||||
* @param pattern the pattern
|
||||
* @param size the size of the brush
|
||||
* @throws MaxChangedBlocksException
|
||||
*/
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException;
|
||||
|
||||
}
|
@ -0,0 +1,49 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.command.util.CreatureButcher;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.visitor.EntityVisitor;
|
||||
import com.sk89q.worldedit.regions.CylinderRegion;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ButcherBrush implements Brush {
|
||||
|
||||
private CreatureButcher flags;
|
||||
|
||||
public ButcherBrush(CreatureButcher flags) {
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
CylinderRegion region = CylinderRegion.createRadius(editSession, position, size);
|
||||
List<? extends Entity> entities = editSession.getEntities(region);
|
||||
Operations.completeLegacy(new EntityVisitor(entities.iterator(), flags.createFunction(editSession.getWorld().getWorldData().getEntityRegistry())));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.extent.clipboard.Clipboard;
|
||||
import com.sk89q.worldedit.function.operation.Operation;
|
||||
import com.sk89q.worldedit.function.operation.Operations;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
|
||||
public class ClipboardBrush implements Brush {
|
||||
|
||||
private ClipboardHolder holder;
|
||||
private boolean ignoreAirBlocks;
|
||||
private boolean usingOrigin;
|
||||
|
||||
public ClipboardBrush(ClipboardHolder holder, boolean ignoreAirBlocks, boolean usingOrigin) {
|
||||
this.holder = holder;
|
||||
this.ignoreAirBlocks = ignoreAirBlocks;
|
||||
this.usingOrigin = usingOrigin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
Region region = clipboard.getRegion();
|
||||
Vector centerOffset = region.getCenter().subtract(clipboard.getOrigin());
|
||||
|
||||
Operation operation = holder
|
||||
.createPaste(editSession, editSession.getWorld().getWorldData())
|
||||
.to(usingOrigin ? position : position.subtract(centerOffset))
|
||||
.ignoreAirBlocks(ignoreAirBlocks)
|
||||
.build();
|
||||
|
||||
Operations.completeLegacy(operation);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.pattern.Patterns;
|
||||
|
||||
public class CylinderBrush implements Brush {
|
||||
|
||||
private int height;
|
||||
|
||||
public CylinderBrush(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
editSession.makeCylinder(position, Patterns.wrap(pattern), size, size, height, true);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockID;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public class GravityBrush implements Brush {
|
||||
|
||||
private final boolean fullHeight;
|
||||
|
||||
public GravityBrush(boolean fullHeight) {
|
||||
this.fullHeight = fullHeight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
final BaseBlock air = new BaseBlock(BlockID.AIR, 0);
|
||||
final double startY = fullHeight ? editSession.getWorld().getMaxY() : position.getBlockY() + size;
|
||||
for (double x = position.getBlockX() + size; x > position.getBlockX() - size; --x) {
|
||||
for (double z = position.getBlockZ() + size; z > position.getBlockZ() - size; --z) {
|
||||
double y = startY;
|
||||
final List<BaseBlock> blockTypes = new ArrayList<BaseBlock>();
|
||||
for (; y > position.getBlockY() - size; --y) {
|
||||
final Vector pt = new Vector(x, y, z);
|
||||
final BaseBlock block = editSession.getBlock(pt);
|
||||
if (!block.isAir()) {
|
||||
blockTypes.add(block);
|
||||
editSession.setBlock(pt, air);
|
||||
}
|
||||
}
|
||||
Vector pt = new Vector(x, y, z);
|
||||
Collections.reverse(blockTypes);
|
||||
for (int i = 0; i < blockTypes.size();) {
|
||||
if (editSession.getBlock(pt).getType() == BlockID.AIR) {
|
||||
editSession.setBlock(pt, blockTypes.get(i++));
|
||||
}
|
||||
pt = pt.add(0, 1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.pattern.Patterns;
|
||||
|
||||
public class HollowCylinderBrush implements Brush {
|
||||
|
||||
private int height;
|
||||
|
||||
public HollowCylinderBrush(int height) {
|
||||
this.height = height;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
editSession.makeCylinder(position, Patterns.wrap(pattern), size, size, height, false);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.pattern.Patterns;
|
||||
|
||||
public class HollowSphereBrush implements Brush {
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
editSession.makeSphere(position, Patterns.wrap(pattern), size, size, size, false);
|
||||
}
|
||||
}
|
@ -0,0 +1,58 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.LocalWorldAdapter;
|
||||
import com.sk89q.worldedit.math.convolution.HeightMap;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.WorldVector;
|
||||
import com.sk89q.worldedit.math.convolution.GaussianKernel;
|
||||
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
|
||||
public class SmoothBrush implements Brush {
|
||||
|
||||
private int iterations;
|
||||
private boolean naturalOnly;
|
||||
|
||||
public SmoothBrush(int iterations) {
|
||||
this(iterations, false);
|
||||
}
|
||||
|
||||
public SmoothBrush(int iterations, boolean naturalOnly) {
|
||||
this.iterations = iterations;
|
||||
this.naturalOnly = naturalOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
WorldVector min = new WorldVector(LocalWorldAdapter.adapt(editSession.getWorld()), position.subtract(size, size, size));
|
||||
Vector max = position.add(size, size + 10, size);
|
||||
Region region = new CuboidRegion(editSession.getWorld(), min, max);
|
||||
HeightMap heightMap = new HeightMap(editSession, region, naturalOnly);
|
||||
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
|
||||
heightMap.applyFilter(filter, iterations);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.tool.brush;
|
||||
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.MaxChangedBlocksException;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.function.pattern.Patterns;
|
||||
|
||||
public class SphereBrush implements Brush {
|
||||
|
||||
@Override
|
||||
public void build(EditSession editSession, Vector position, Pattern pattern, double size) throws MaxChangedBlocksException {
|
||||
editSession.makeSphere(position, Patterns.wrap(pattern), size, size, size, true);
|
||||
}
|
||||
}
|
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.util;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandContext;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.metadata.EntityType;
|
||||
import com.sk89q.worldedit.extension.platform.Actor;
|
||||
import com.sk89q.worldedit.function.EntityFunction;
|
||||
import com.sk89q.worldedit.world.registry.EntityRegistry;
|
||||
|
||||
/**
|
||||
* The implementation of /butcher.
|
||||
*/
|
||||
public class CreatureButcher {
|
||||
|
||||
final class Flags {
|
||||
@SuppressWarnings("PointlessBitwiseExpression")
|
||||
public static final int PETS = 1 << 0;
|
||||
public static final int NPCS = 1 << 1;
|
||||
public static final int ANIMALS = 1 << 2;
|
||||
public static final int GOLEMS = 1 << 3;
|
||||
public static final int AMBIENT = 1 << 4;
|
||||
public static final int TAGGED = 1 << 5;
|
||||
public static final int FRIENDLY = PETS | NPCS | ANIMALS | GOLEMS | AMBIENT | TAGGED;
|
||||
public static final int WITH_LIGHTNING = 1 << 20;
|
||||
|
||||
private Flags() {
|
||||
}
|
||||
}
|
||||
|
||||
private final Actor player;
|
||||
public int flags = 0;
|
||||
|
||||
public CreatureButcher(Actor player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public void or(int flag, boolean on) {
|
||||
if (on) flags |= flag;
|
||||
}
|
||||
|
||||
public void or(int flag, boolean on, String permission) {
|
||||
or(flag, on);
|
||||
|
||||
if ((flags & flag) != 0 && !player.hasPermission(permission)) {
|
||||
flags &= ~flag;
|
||||
}
|
||||
}
|
||||
|
||||
public void fromCommand(CommandContext args) {
|
||||
or(Flags.FRIENDLY , args.hasFlag('f')); // No permission check here. Flags will instead be filtered by the subsequent calls.
|
||||
or(Flags.PETS , args.hasFlag('p'), "worldedit.butcher.pets");
|
||||
or(Flags.NPCS , args.hasFlag('n'), "worldedit.butcher.npcs");
|
||||
or(Flags.GOLEMS , args.hasFlag('g'), "worldedit.butcher.golems");
|
||||
or(Flags.ANIMALS , args.hasFlag('a'), "worldedit.butcher.animals");
|
||||
or(Flags.AMBIENT , args.hasFlag('b'), "worldedit.butcher.ambient");
|
||||
or(Flags.TAGGED , args.hasFlag('t'), "worldedit.butcher.tagged");
|
||||
or(Flags.WITH_LIGHTNING, args.hasFlag('l'), "worldedit.butcher.lightning");
|
||||
}
|
||||
|
||||
public EntityFunction createFunction(final EntityRegistry entityRegistry) {
|
||||
return new EntityFunction() {
|
||||
@Override
|
||||
public boolean apply(Entity entity) throws WorldEditException {
|
||||
boolean killPets = (flags & Flags.PETS) != 0;
|
||||
boolean killNPCs = (flags & Flags.NPCS) != 0;
|
||||
boolean killAnimals = (flags & Flags.ANIMALS) != 0;
|
||||
boolean killGolems = (flags & Flags.GOLEMS) != 0;
|
||||
boolean killAmbient = (flags & Flags.AMBIENT) != 0;
|
||||
boolean killTagged = (flags & Flags.TAGGED) != 0;
|
||||
|
||||
EntityType type = entity.getFacet(EntityType.class);
|
||||
|
||||
if (type == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type.isPlayerDerived()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!type.isLiving()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!killAnimals && type.isAnimal()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!killPets && type.isTamed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!killGolems && type.isGolem()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!killNPCs && type.isNPC()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!killAmbient && type.isAmbient()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!killTagged && type.isTagged()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
entity.remove();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.command.util;
|
||||
|
||||
import com.sk89q.minecraft.util.commands.CommandException;
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.entity.Entity;
|
||||
import com.sk89q.worldedit.entity.metadata.EntityType;
|
||||
import com.sk89q.worldedit.function.EntityFunction;
|
||||
import com.sk89q.worldedit.world.registry.EntityRegistry;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* The implementation of /remove.
|
||||
*/
|
||||
public class EntityRemover {
|
||||
|
||||
public enum Type {
|
||||
ALL("all") {
|
||||
@Override
|
||||
boolean matches(EntityType type) {
|
||||
for (Type value : values()) {
|
||||
if (value != this && value.matches(type)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
},
|
||||
PROJECTILES("projectiles?|arrows?") {
|
||||
@Override
|
||||
boolean matches(EntityType type) {
|
||||
return type.isProjectile();
|
||||
}
|
||||
},
|
||||
ITEMS("items?|drops?") {
|
||||
@Override
|
||||
boolean matches(EntityType type) {
|
||||
return type.isItem();
|
||||
}
|
||||
},
|
||||
FALLING_BLOCKS("falling(blocks?|sand|gravel)") {
|
||||
@Override
|
||||
boolean matches(EntityType type) {
|
||||
return type.isFallingBlock();
|
||||
}
|
||||
},
|
||||
PAINTINGS("paintings?|art") {
|
||||
@Override
|
||||
boolean matches(EntityType type) {
|
||||
return type.isPainting();
|
||||
}
|
||||
},
|
||||
ITEM_FRAMES("(item)frames?") {
|
||||
@Override
|
||||
boolean matches(EntityType type) {
|
||||
return type.isItemFrame();
|
||||
}
|
||||
},
|
||||
BOATS("boats?") {
|
||||
@Override
|
||||
boolean matches(EntityType type) {
|
||||
return type.isBoat();
|
||||
}
|
||||
},
|
||||
MINECARTS("(mine)?carts?") {
|
||||
@Override
|
||||
boolean matches(EntityType type) {
|
||||
return type.isMinecart();
|
||||
}
|
||||
},
|
||||
TNT("tnt") {
|
||||
@Override
|
||||
boolean matches(EntityType type) {
|
||||
return type.isTNT();
|
||||
}
|
||||
},
|
||||
XP_ORBS("xp") {
|
||||
@Override
|
||||
boolean matches(EntityType type) {
|
||||
return type.isExperienceOrb();
|
||||
}
|
||||
};
|
||||
|
||||
private final Pattern pattern;
|
||||
|
||||
Type(String pattern) {
|
||||
this.pattern = Pattern.compile(pattern);
|
||||
}
|
||||
|
||||
public boolean matches(String str) {
|
||||
return pattern.matcher(str).matches();
|
||||
}
|
||||
|
||||
abstract boolean matches(EntityType type);
|
||||
|
||||
@Nullable
|
||||
public static Type findByPattern(String str) {
|
||||
for (Type type : values()) {
|
||||
if (type.matches(str)) {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Type type;
|
||||
|
||||
public void fromString(String str) throws CommandException {
|
||||
Type type = Type.findByPattern(str);
|
||||
if (type != null) {
|
||||
this.type = type;
|
||||
} else {
|
||||
throw new CommandException("Acceptable types: projectiles, items, paintings, itemframes, boats, minecarts, tnt, xp, or all");
|
||||
}
|
||||
}
|
||||
|
||||
public EntityFunction createFunction(final EntityRegistry entityRegistry) {
|
||||
final Type type = this.type;
|
||||
checkNotNull("type can't be null", type);
|
||||
return new EntityFunction() {
|
||||
@Override
|
||||
public boolean apply(Entity entity) throws WorldEditException {
|
||||
EntityType registryType = entity.getFacet(EntityType.class);
|
||||
if (registryType != null) {
|
||||
if (type.matches(registryType)) {
|
||||
entity.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user