It started on work with commands then I got carried away.

This commit is contained in:
MattBDev
2019-07-25 14:44:10 -04:00
parent 01c371df9c
commit ff5860113d
184 changed files with 1694 additions and 2580 deletions

View File

@ -95,7 +95,7 @@ public class ChunkCommands {
Set<BlockVector2> chunks = session.getSelection(player.getWorld()).getChunks();
PaginationBox paginationBox = PaginationBox.fromStrings("Selected Chunks", "/listchunks -p %page%",
chunks.stream().map(LegacyChunkStore::getFilename).collect(Collectors.toList()));
chunks.stream().map(BlockVector2::toString).collect(Collectors.toList()));
player.print(paginationBox.create(page));
}

View File

@ -238,7 +238,7 @@ public class ClipboardCommands {
@Selection Region region,
@Arg(desc = "Pattern to leave in place of the selection", def = "air")
Pattern leavePattern,
@Switch(name = 'e', desc = "skip cut entities")
@Switch(name = 'e', desc = "Skip cut entities")
boolean skipEntities,
@Switch(name = 'b', desc = "Also copy biomes, source biomes are unaffected")
boolean copyBiomes,
@ -579,7 +579,7 @@ public class ClipboardCommands {
desc = "Clear your clipboard"
)
@CommandPermissions("worldedit.clipboard.clear")
public void clearClipboard(Player player, LocalSession session, EditSession editSession) throws WorldEditException {
public void clearClipboard(Player player, LocalSession session) throws WorldEditException {
session.setClipboard(null);
BBC.CLIPBOARD_CLEARED.send(player);
}

View File

@ -19,9 +19,10 @@
package com.sk89q.worldedit.command;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.extent.ResettableExtent;
import com.boydti.fawe.util.CachedTextureUtil;
import com.boydti.fawe.util.CleanTextureUtil;
@ -29,8 +30,6 @@ import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.RandomTextureUtil;
import com.boydti.fawe.util.StringMan;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.extension.input.InputParseException;
import org.enginehub.piston.inject.InjectedValueAccess;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
@ -41,36 +40,32 @@ import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.WorldEditAsyncCommandBuilder;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.DisallowedUsageException;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.util.formatting.component.PaginationBox;
import com.sk89q.worldedit.util.formatting.text.Component;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.item.ItemType;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Callable;
import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.ArgFlag;
import org.enginehub.piston.annotation.param.Switch;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.Callable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* General WorldEdit commands.
*/
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
//@Command(aliases = {}, desc = "Player toggles, settings and item info")
public class GeneralCommands {
private final WorldEdit worldEdit;
@ -141,12 +136,16 @@ public class GeneralCommands {
@CommandPermissions("worldedit.fast")
public void fast(Player player, LocalSession session, @Arg(desc = "The new fast mode state", def = "") Boolean fastMode) {
boolean hasFastMode = session.hasFastMode();
if (fastMode == null) fastMode = !hasFastMode;
session.setFastMode(fastMode);
if (fastMode) {
BBC.FAST_ENABLED.send(player);
} else {
if (fastMode != null && fastMode == hasFastMode) {
player.printError("Fast mode already " + (fastMode ? "enabled" : "disabled") + ".");
return;
}
if (hasFastMode) {
session.setFastMode(false);
BBC.FAST_DISABLED.send(player);
} else {
session.setFastMode(true);
BBC.FAST_ENABLED.send(player);
}
}
@ -299,7 +298,7 @@ public class GeneralCommands {
desc = "Set the global mask"
)
@CommandPermissions("worldedit.global-texture")
public void gtexture(FawePlayer player, LocalSession session, EditSession editSession, @Arg(name = "context", desc = "InjectedValueAccess", def = "") List<String> arguments) throws WorldEditException, FileNotFoundException {
public void gtexture(Player player, World world, LocalSession session, EditSession editSession, @Arg(name = "context", desc = "InjectedValueAccess", def = "") List<String> arguments) throws WorldEditException, FileNotFoundException {
// gtexture <randomize> <min=0> <max=100>
// TODO NOT IMPLEMENTED convert this to an ArgumentConverter
if (arguments.isEmpty()) {
@ -307,7 +306,7 @@ public class GeneralCommands {
BBC.TEXTURE_DISABLED.send(player);
} else {
String arg = arguments.get(0);
String argLower = arg.toLowerCase();
String argLower = arg.toLowerCase(Locale.ROOT);
TextureUtil util = Fawe.get().getTextureUtil();
int randomIndex = 1;
@ -324,16 +323,15 @@ public class GeneralCommands {
if (argLower.equals("true")) util = new RandomTextureUtil(util);
checkRandomization = false;
} else {
HashSet<BaseBlock> blocks = null;
if (argLower.equals("#copy") || argLower.equals("#clipboard")) {
Clipboard clipboard = player.getSession().getClipboard().getClipboard();
Clipboard clipboard = worldEdit.getSessionManager().get(player).getClipboard().getClipboard();
util = TextureUtil.fromClipboard(clipboard);
} else if (argLower.equals("*") || argLower.equals("true")) {
util = Fawe.get().getTextureUtil();
} else {
ParserContext parserContext = new ParserContext();
parserContext.setActor(player.getPlayer());
parserContext.setWorld(player.getWorld());
parserContext.setActor(player);
parserContext.setWorld(world);
parserContext.setSession(session);
parserContext.setExtent(editSession);
Mask mask = worldEdit.getMaskFactory().parseFromInput(arg, parserContext);
@ -392,7 +390,6 @@ public class GeneralCommands {
)
@CommandPermissions("fawe.tips")
public void tips(Player player, LocalSession session) throws WorldEditException {
FawePlayer<Object> fp = FawePlayer.wrap(player);
if (player.togglePermission("fawe.tips")) {
BBC.WORLDEDIT_TOGGLE_TIPS_ON.send(player);
} else {

View File

@ -70,8 +70,7 @@ import org.enginehub.piston.inject.InjectedValueAccess;
* Commands for the generation of shapes and other objects.
*/
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
//@Command(aliases = {}, desc = "Create structures and features: [More Info](https://goo.gl/KuLFRW)")
public class GenerationCommands extends MethodCommands {
public class GenerationCommands {
private final WorldEdit worldEdit;
@ -275,9 +274,10 @@ public class GenerationCommands extends MethodCommands {
int size,
@Arg(desc = "The type of forest", def = "tree")
TreeType type,
@Range(min = 0, max = 100) @Arg(desc = "The density of the forest, between 0 and 100", def = "5")
@Arg(desc = "The density of the forest, between 0 and 100", def = "5")
double density) throws WorldEditException {
density = density / 100;
checkCommandArgument(0 <= density && density <= 100, "Density must be between 0 and 100");
density /= 100;
int affected = editSession.makeForest(session.getPlacementPosition(player), size, density, type);
player.print(affected + " trees created.");
return affected;
@ -393,7 +393,7 @@ public class GenerationCommands extends MethodCommands {
fp.checkConfirmationRegion(() -> {
try {
int affected = editSession.makeShape(region, zero, unit1, pattern, String.join(" ", expression), hollow, session.getTimeout());
final int affected = editSession.makeShape(region, zero, unit1, pattern, String.join(" ", expression), hollow, session.getTimeout());
player.findFreePosition();
BBC.VISITOR_BLOCK.send(fp, affected);
} catch (ExpressionException e) {

View File

@ -60,7 +60,7 @@ import org.enginehub.piston.inject.InjectedValueAccess;
* Commands to undo, redo, and clear history.
*/
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class HistoryCommands extends MethodCommands {
public class HistoryCommands {
private final WorldEdit worldEdit;
@ -224,11 +224,12 @@ public class HistoryCommands extends MethodCommands {
@Arg(name = "player", desc = "Undo this player's operations", def = "")
String playerName,
InjectedValueAccess context) throws WorldEditException {
times = Math.max(1, times);
LocalSession undoSession;
if (session.hasFastMode()) {
BBC.COMMAND_UNDO_DISABLED.send(player);
return;
}
LocalSession undoSession;
if (playerName != null && !playerName.isEmpty()) {
player.checkPermission("worldedit.history.undo.other");
undoSession = worldEdit.getSessionManager().findByName(playerName);
@ -239,7 +240,6 @@ public class HistoryCommands extends MethodCommands {
} else {
undoSession = session;
}
times = Math.max(1, times);
int finalTimes = times;
FawePlayer.wrap(player).checkConfirmation(() -> {
EditSession undone = null;

View File

@ -25,6 +25,7 @@ import com.boydti.fawe.object.mask.ZAxisMask;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
@ -39,12 +40,14 @@ import com.sk89q.worldedit.function.mask.RegionMask;
import com.sk89q.worldedit.function.mask.SolidBlockMask;
import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.ExpressionEnvironment;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.session.request.RequestSelection;
import com.sk89q.worldedit.world.biome.BiomeType;
import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
import org.enginehub.piston.annotation.param.Switch;
@ -57,7 +60,8 @@ import org.enginehub.piston.annotation.param.Switch;
// "e.g. >[stone,dirt],#light[0][5],$jungle\n" +
// "More Info: https://git.io/v9r4K"
//)
public class MaskCommands extends MethodCommands {
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class MaskCommands {
private final WorldEdit worldEdit;
public MaskCommands(WorldEdit worldEdit) {
@ -69,7 +73,7 @@ public class MaskCommands extends MethodCommands {
desc = "Use simplex noise as the mask"
)
public Mask simplex(double scale, double min, double max) {
scale = (1d / Math.max(1, scale));
scale = 1d / Math.max(1, scale);
min = (min - 50) / 50;
max = (max - 50) / 50;
return new SimplexMask(scale, min, max);
@ -290,11 +294,11 @@ public class MaskCommands extends MethodCommands {
if (max.endsWith("d")) {
double y1d = Expression.compile(min.substring(0, min.length() - 1)).evaluate();
double y2d = Expression.compile(max.substring(0, max.length() - 1)).evaluate();
y1 = (Math.tan(y1d * (Math.PI / 180)));
y2 = (Math.tan(y2d * (Math.PI / 180)));
y1 = Math.tan(y1d * (Math.PI / 180));
y2 = Math.tan(y2d * (Math.PI / 180));
} else {
y1 = (Expression.compile(min).evaluate());
y2 = (Expression.compile(max).evaluate());
y1 = Expression.compile(min).evaluate();
y2 = Expression.compile(max).evaluate();
}
return new AngleMask(extent, y1, y2, overlay, distance);
}
@ -315,11 +319,11 @@ public class MaskCommands extends MethodCommands {
if (max.endsWith("d")) {
double y1d = Expression.compile(min.substring(0, min.length() - 1)).evaluate();
double y2d = Expression.compile(max.substring(0, max.length() - 1)).evaluate();
y1 = (Math.tan(y1d * (Math.PI / 180)));
y2 = (Math.tan(y2d * (Math.PI / 180)));
y1 = Math.tan(y1d * (Math.PI / 180));
y2 = Math.tan(y2d * (Math.PI / 180));
} else {
y1 = (Expression.compile(min).evaluate());
y2 = (Expression.compile(max).evaluate());
y1 = Expression.compile(min).evaluate();
y2 = Expression.compile(max).evaluate();
}
return new ROCAngleMask(extent, y1, y2, overlay, distance);
}
@ -340,11 +344,11 @@ public class MaskCommands extends MethodCommands {
if (max.endsWith("d")) {
double y1d = Expression.compile(min.substring(0, min.length() - 1)).evaluate();
double y2d = Expression.compile(max.substring(0, max.length() - 1)).evaluate();
y1 = (Math.tan(y1d * (Math.PI / 180)));
y2 = (Math.tan(y2d * (Math.PI / 180)));
y1 = Math.tan(y1d * (Math.PI / 180));
y2 = Math.tan(y2d * (Math.PI / 180));
} else {
y1 = (Expression.compile(min).evaluate());
y2 = (Expression.compile(max).evaluate());
y1 = Expression.compile(min).evaluate();
y2 = Expression.compile(max).evaluate();
}
return new ExtremaMask(extent, y1, y2, overlay, distance);
}
@ -430,7 +434,7 @@ public class MaskCommands extends MethodCommands {
)
public Mask expression(Extent extent, String input) throws ExpressionException {
Expression exp = Expression.compile(input, "x", "y", "z");
WorldEditExpressionEnvironment env = new WorldEditExpressionEnvironment(extent, Vector3.ONE, Vector3.ZERO);
ExpressionEnvironment env = new WorldEditExpressionEnvironment(extent, Vector3.ONE, Vector3.ZERO);
exp.setEnvironment(env);
return new ExpressionMask(exp);
}

View File

@ -159,12 +159,21 @@ public class NavigationCommands {
desc = "Teleport to a location"
)
@CommandPermissions("worldedit.navigation.jumpto.command")
public void jumpTo(Player player, @Arg(desc = "Location to jump to", def = "") Location pos, @Switch(name='f', desc = "force teleport") boolean force) throws WorldEditException {
public void jumpTo(Player player,
@Arg(desc = "Location to jump to", def = "")
Location pos,
@Switch(name='f', desc = "force teleport")
boolean force) throws WorldEditException {
if (pos == null) {
pos = player.getSolidBlockTrace(300);
}
if (pos != null) {
if(force) player.setPosition(pos); else player.findFreePosition(pos);
if (force) {
player.setPosition(pos);
} else {
player.findFreePosition(pos);
}
BBC.POOF.send(player);
} else {
BBC.NO_BLOCK.send(player);

View File

@ -8,6 +8,7 @@ import com.boydti.fawe.object.pattern.*;
import com.boydti.fawe.object.random.SimplexRandom;
import com.boydti.fawe.util.ColorUtil;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import org.enginehub.piston.annotation.Command;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.entity.Player;
@ -27,6 +28,7 @@ import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.internal.annotation.Range;
import com.sk89q.worldedit.world.biome.BiomeType;
import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
import java.awt.Color;
@ -43,12 +45,8 @@ import java.util.Set;
// "e.g. #surfacespread[10][#existing],andesite\n" +
// "More Info: https://git.io/vSPmA"
//)
public class PatternCommands extends MethodCommands {
private final WorldEdit worldEdit;
public PatternCommands(WorldEdit worldEdit) {
this.worldEdit = worldEdit;
}
@CommandContainer(superTypes = CommandPermissionsConditionGenerator.Registration.class)
public class PatternCommands {
@Command(
name = "#existing",

View File

@ -100,6 +100,26 @@ public class RegionCommands {
this.worldEdit = worldEdit;
}
@Command(
name = "/set",
desc = "Sets all the blocks in the region"
)
@CommandPermissions("worldedit.region.set")
@Logging(REGION)
public void set(FawePlayer player, EditSession editSession,
@Selection Region region,
@Arg(desc = "The pattern of blocks to set")
Pattern pattern, InjectedValueAccess context) throws WorldEditException {
player.checkConfirmationRegion(() -> {
int affected = editSession.setBlocks(region, pattern);
if (affected != 0) {
BBC.OPERATION.send(player, affected);
if (!player.hasPermission("fawe.tips"))
BBC.TIP_FAST.or(BBC.TIP_CANCEL, BBC.TIP_MASK, BBC.TIP_MASK_ANGLE, BBC.TIP_SET_LINEAR, BBC.TIP_SURFACE_SPREAD, BBC.TIP_SET_HAND).send(player);
}
}, getArguments(context), region, context);
}
@Command(
name = "/fixlighting",
desc = "Get the light at a position"
@ -197,7 +217,7 @@ public class RegionCommands {
@Arg(desc = "The pattern of blocks to place")
Pattern pattern,
@Arg(desc = "The thickness of the line", def = "0")
@Range(min = 0) int thickness,
int thickness,
@Switch(name = 'h', desc = "Generate only a shell")
boolean shell) throws WorldEditException {
if (!(region instanceof CuboidRegion)) {
@ -227,7 +247,7 @@ public class RegionCommands {
@Arg(desc = "The pattern of blocks to place")
Pattern pattern,
@Arg(desc = "The thickness of the curve", def = "0")
@Range(min = 0) int thickness,
int thickness,
@Switch(name = 'h', desc = "Generate only a shell")
boolean shell, InjectedValueAccess context) throws WorldEditException {
if (!(region instanceof ConvexPolyhedralRegion)) {
@ -258,6 +278,9 @@ public class RegionCommands {
Mask from,
@Arg(desc = "The pattern of blocks to replace with")
Pattern to, InjectedValueAccess context) throws WorldEditException {
if (from == null) {
from = new ExistingBlockMask(editSession);
}
player.checkConfirmationRegion(() -> {
int affected = editSession.replaceBlocks(region, from == null ? new ExistingBlockMask(editSession) : from, to);
BBC.VISITOR_BLOCK.send(player, affected);
@ -269,31 +292,13 @@ public class RegionCommands {
}
}, getArguments(context), region, context);
}
// Compatibility for SKCompat
@Deprecated
public void set(Player player, LocalSession session, EditSession editSession, Pattern pattern) throws WorldEditException {
set(FawePlayer.wrap(player), session, editSession, session.getSelection(player.getWorld()), pattern, null);
}
@Command(
name = "/set",
aliases = { "/s" },
desc = "Set all blocks within selection"
)
@CommandPermissions("worldedit.region.set")
@Logging(REGION)
public void set(FawePlayer player, LocalSession session, EditSession editSession, @Selection Region selection, Pattern to, InjectedValueAccess context) throws WorldEditException {
player.checkConfirmationRegion(() -> {
int affected = editSession.setBlocks(selection, to);
if (affected != 0) {
BBC.OPERATION.send(player, affected);
if (!player.hasPermission("fawe.tips"))
BBC.TIP_FAST.or(BBC.TIP_CANCEL, BBC.TIP_MASK, BBC.TIP_MASK_ANGLE, BBC.TIP_SET_LINEAR, BBC.TIP_SURFACE_SPREAD, BBC.TIP_SET_HAND).send(player);
}
}, getArguments(context), selection, context);
}
@Command(
name = "/overlay",
desc = "Set a block on top of blocks in the region"
@ -526,7 +531,7 @@ public class RegionCommands {
)
@CommandPermissions("worldedit.region.stack")
@Logging(ORIENTATION_REGION)
public void stack(FawePlayer player, World world, EditSession editSession, LocalSession session,
public void stack(FawePlayer player, EditSession editSession, LocalSession session,
@Selection Region region,
@Arg(desc = "# of copies to stack", def = "1")
int count,
@ -557,8 +562,8 @@ public class RegionCommands {
final BlockVector3 shiftVector = direction.toVector3().multiply(count * (Math.abs(direction.dot(size)) + 1)).toBlockPoint();
region.shift(shiftVector);
session.getRegionSelector(world).learnChanges();
session.getRegionSelector(world).explainRegionAdjust(player.getPlayer(), session);
session.getRegionSelector(player.getWorld()).learnChanges();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player.getPlayer(), session);
} catch (RegionOperationException e) {
player.toWorldEditPlayer().printError(e.getMessage());
}

View File

@ -34,6 +34,8 @@ import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseItemStack;
import com.sk89q.worldedit.command.argument.SelectorChoice;
import com.sk89q.worldedit.command.tool.NavigationWand;
import com.sk89q.worldedit.command.tool.SelectionWand;
import com.sk89q.worldedit.command.util.CommandPermissions;
import com.sk89q.worldedit.command.util.CommandPermissionsConditionGenerator;
import com.sk89q.worldedit.command.util.Logging;
@ -66,6 +68,7 @@ import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
import com.sk89q.worldedit.world.storage.ChunkStore;
import java.io.File;
@ -249,8 +252,23 @@ public class SelectionCommands {
@CommandPermissions("worldedit.wand")
public void wand(Player player, LocalSession session,
@Switch(name = 'n', desc = "Get a navigation wand") boolean navWand) throws WorldEditException {
player.giveItem(new BaseItemStack(ItemTypes.parse(we.getConfiguration().wandItem), 1));
BBC.SELECTION_WAND.send(player);
String wandId = navWand ? session.getNavWandItem() : session.getWandItem();
if (wandId == null) {
wandId = navWand ? we.getConfiguration().navigationWand : we.getConfiguration().wandItem;
}
ItemType itemType = ItemTypes.parse(wandId);
if (itemType == null) {
player.printError("Wand item is mis-configured or disabled.");
return;
}
player.giveItem(new BaseItemStack(itemType, 1));
if (navWand) {
session.setTool(itemType, new NavigationWand());
player.print("Left click: jump to location; Right click: pass through walls");
} else {
session.setTool(itemType, new SelectionWand());
BBC.SELECTION_WAND.send(player);
}
if (!player.hasPermission("fawe.tips"))
BBC.TIP_SEL_LIST.or(BBC.TIP_SELECT_CONNECTED, BBC.TIP_SET_POS1, BBC.TIP_FARWAND, BBC.TIP_DISCORD).send(player);
}
@ -440,20 +458,22 @@ public class SelectionCommands {
index++;
}
return;
}
} else {
region = session.getSelection(player.getWorld());
region = session.getSelection(player.getWorld());
player.print("Type: " + session.getRegionSelector(player.getWorld()).getTypeName());
for (String line : session.getRegionSelector(player.getWorld())
.getInformationLines()) {
player.print(line);
}
}
BlockVector3 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()));
@ -463,7 +483,7 @@ public class SelectionCommands {
@Command(
name = "/count",
desc = "Counts the number of a certain type of block"
desc = "Counts the number of blocks matching a mask"
)
@CommandPermissions("worldedit.analysis.count")
public void count(Player player, LocalSession session, EditSession editSession,

View File

@ -110,6 +110,7 @@ public class ToolCommands {
public void inspectBrush(Player player, LocalSession session,
@Arg(desc = "The radius of the brush", def = "1")
double radius) throws WorldEditException {
radius = Math.max(1,radius);
BaseItemStack itemStack = player.getItemInHand(HandSide.MAIN_HAND);
session.setTool(player, new InspectBrush());
BBC.TOOL_INSPECT.send(player, itemStack.getType().getName());

View File

@ -72,7 +72,7 @@ public class TransformCommands {
aliases = {"#randomoffset"},
desc = "Random offset transform"
)
public ResettableExtent randomoffset(Actor actor, LocalSession session, double x, double y, double z, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
public ResettableExtent randomOffset(Actor actor, LocalSession session, double x, double y, double z, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
return new RandomOffsetTransform(other, (int) x, (int) y, (int) z);
}
@ -89,7 +89,7 @@ public class TransformCommands {
desc = "All changes will be rotate around the initial position"
)
public ResettableExtent rotate(Player player, LocalSession session, double x, double y, double z, @Arg(name = "other", desc = "ResettableExtent", def = "#null") ResettableExtent other) {
ExtentTraverser<TransformExtent> traverser = new ExtentTraverser(other).find(TransformExtent.class);
ExtentTraverser<TransformExtent> traverser = new ExtentTraverser<>(other).find(TransformExtent.class);
BlockTransformExtent affine = traverser != null ? traverser.get() : null;
if (affine == null) {
other = affine = new TransformExtent(other);

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.command;
import static com.sk89q.worldedit.command.util.Logging.LogMode.PLACEMENT;
import static com.sk89q.worldedit.util.formatting.text.TextComponent.newline;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
@ -29,7 +30,6 @@ import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RunnableVal3;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.chat.Message;
import com.boydti.fawe.util.image.ImageUtil;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.IncompleteRegionException;
@ -70,6 +70,9 @@ import com.sk89q.worldedit.regions.CylinderRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.formatting.component.SubtleFormat;
import com.sk89q.worldedit.util.formatting.text.TextComponent;
import com.sk89q.worldedit.util.formatting.text.TextComponent.Builder;
import com.sk89q.worldedit.util.formatting.text.event.ClickEvent;
import com.sk89q.worldedit.util.formatting.text.event.HoverEvent;
import com.sk89q.worldedit.util.formatting.text.format.TextColor;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.block.BlockTypes;
@ -85,10 +88,10 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.UUID;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import java.util.function.Supplier;
import javax.imageio.ImageIO;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.enginehub.piston.annotation.Command;
import org.enginehub.piston.annotation.CommandContainer;
import org.enginehub.piston.annotation.param.Arg;
@ -188,11 +191,13 @@ public class UtilityCommands {
@Arg(desc = "The blocks to fill with")
Pattern pattern,
@Arg(desc = "The radius to fill in")
@Range(min = 1) double radius,
double radius,
@Arg(desc = "The depth to fill", def = "1")
@Range(min = 1) int depth,
int depth,
@Arg(desc = "Direction to fill", def = "down") BlockVector3 direction) throws WorldEditException {
radius = Math.max(1, radius);
we.checkMaxRadius(radius);
depth = Math.max(1, depth);
BlockVector3 pos = session.getPlacementPosition(player);
int affected = editSession.fillDirection(pos, pattern, radius, depth, direction);
@ -281,9 +286,10 @@ public class UtilityCommands {
@Arg(desc = "The blocks to fill with")
Pattern pattern,
@Arg(desc = "The radius to fill in")
@Range(min = 1) double radius,
double radius,
@Arg(desc = "The depth to fill", def = "")
@Range(min = 1) Integer depth) throws WorldEditException {
Integer depth) throws WorldEditException {
radius = Math.max(1, radius);
we.checkMaxRadius(radius);
depth = depth == null ? Integer.MAX_VALUE : Math.max(1, depth);
we.checkMaxRadius(radius);
@ -302,9 +308,10 @@ public class UtilityCommands {
@Logging(PLACEMENT)
public int drain(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius to drain")
@Range(min = 0) double radius,
double radius,
@Switch(name = 'w', desc = "Also un-waterlog blocks")
boolean waterlogged) throws WorldEditException {
radius = Math.max(0, radius);
we.checkMaxRadius(radius);
int affected = editSession.drainArea(
session.getPlacementPosition(player), radius, waterlogged);
@ -321,7 +328,8 @@ public class UtilityCommands {
@Logging(PLACEMENT)
public int fixLava(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius to fix in")
@Range(min = 0) double radius) throws WorldEditException {
double radius) throws WorldEditException {
radius = Math.max(0, radius);
we.checkMaxRadius(radius);
int affected = editSession.fixLiquid(session.getPlacementPosition(player), radius, BlockTypes.LAVA);
player.print(affected + " block(s) have been changed.");
@ -354,10 +362,13 @@ public class UtilityCommands {
@Logging(PLACEMENT)
public int removeAbove(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The apothem of the square to remove from", def = "1")
@Range(min = 1) int size,
int size,
@Arg(desc = "The maximum height above you to remove from", def = "")
Integer height) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size);
World world = player.getWorld();
height = height != null ? Math.min((world.getMaxY() + 1), height + 1) : (world.getMaxY() + 1);
int affected = editSession.removeAbove(session.getPlacementPosition(player), size, height);
BBC.VISITOR_BLOCK.send(player, affected);
return affected;
@ -372,9 +383,10 @@ public class UtilityCommands {
@Logging(PLACEMENT)
public int removeBelow(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The apothem of the square to remove from", def = "1")
@Range(min =1) int size,
int size,
@Arg(desc = "The maximum height below you to remove from", def = "")
Integer height) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size);
World world = player.getWorld();
height = height != null ? Math.min((world.getMaxY() + 1), height + 1) : (world.getMaxY() + 1);
@ -395,7 +407,8 @@ public class UtilityCommands {
@Arg(desc = "The mask of blocks to remove")
Mask mask,
@Arg(desc = "The radius of the square to remove from", def = "50")
@Range(min=1) int radius) throws WorldEditException {
int radius) throws WorldEditException {
radius = Math.max(1, radius);
we.checkMaxRadius(radius);
int affected = editSession.removeNear(session.getPlacementPosition(player), mask, radius);
@ -412,11 +425,12 @@ public class UtilityCommands {
@Logging(PLACEMENT)
public int replaceNear(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius of the square to remove in")
@Range(min=1) int radius,
int radius,
@Arg(desc = "The mask matching blocks to remove", def = "")
Mask from,
@Arg(desc = "The pattern of blocks to replace with")
Pattern to) throws WorldEditException {
radius = Math.max(1, radius);
we.checkMaxRadius(radius);
BlockVector3 base = session.getPlacementPosition(player);
@ -442,11 +456,12 @@ public class UtilityCommands {
@Logging(PLACEMENT)
public int snow(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius of the circle to snow in", def = "10")
@Range(min=1) double size) throws WorldEditException {
double size) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size);
int affected = editSession.simulateSnow(session.getPlacementPosition(player), size);
player.print(affected + " surfaces covered. Let it snow~");
player.print(affected + " surface(s) covered. Let it snow~");
return affected;
}
@ -459,11 +474,12 @@ public class UtilityCommands {
@Logging(PLACEMENT)
public int thaw(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius of the circle to thaw in", def = "10")
@Range(min=1) double size) throws WorldEditException {
double size) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size);
int affected = editSession.thaw(session.getPlacementPosition(player), size);
player.print(affected + " surfaces thawed.");
player.print(affected + " surface(s) thawed.");
return affected;
}
@ -476,9 +492,10 @@ public class UtilityCommands {
@Logging(PLACEMENT)
public int green(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius of the circle to convert in", def = "10")
@Range(min=1) double size,
double size,
@Switch(name = 'f', desc = "Also convert coarse dirt")
boolean convertCoarse) throws WorldEditException {
size = Math.max(1, size);
we.checkMaxRadius(size);
final boolean onlyNormalDirt = !convertCoarse;
@ -496,12 +513,12 @@ public class UtilityCommands {
@Logging(PLACEMENT)
public void extinguish(Player player, LocalSession session, EditSession editSession,
@Arg(desc = "The radius of the square to remove in", def = "")
@Range(min=1) Integer radius) throws WorldEditException {
Integer radius) throws WorldEditException {
LocalConfiguration config = we.getConfiguration();
int defaultRadius = config.maxRadius != -1 ? Math.min(40, config.maxRadius) : 40;
int size = radius != null ? radius : defaultRadius;
int size = radius != null ? Math.max(1, radius) : defaultRadius;
we.checkMaxRadius(size);
Mask mask = new BlockTypeMask(editSession, BlockTypes.FIRE);
@ -657,7 +674,8 @@ public class UtilityCommands {
return;
}
WorldEditAsyncCommandBuilder.createAndSendMessage(actor, () -> {
double result = expression.evaluateTimeout(WorldEdit.getInstance().getSessionManager().get(actor).getTimeout());
double result = expression.evaluate(
new double[]{}, WorldEdit.getInstance().getSessionManager().get(actor).getTimeout());
String formatted = Double.isNaN(result) ? "NaN" : formatter.format(result);
return SubtleFormat.wrap(input + " = ").append(TextComponent.of(formatted, TextColor.LIGHT_PURPLE));
}, null);
@ -690,16 +708,18 @@ public class UtilityCommands {
}
public static void list(File dir, Actor actor, InjectedValueAccess args, @Range(min = 0) int page, String formatName, boolean playerFolder, String onClickCmd) {
list(dir, actor, args, page, -1, formatName, playerFolder, new RunnableVal3<Message, URI, String>() {
list(dir, actor, args, page, -1, formatName, playerFolder, new RunnableVal3<Builder, URI, String>() {
@Override
public void run(Message m, URI uri, String fileName) {
m.text(BBC.SCHEMATIC_LIST_ELEM, fileName, "");
if (onClickCmd != null) m.cmdTip(onClickCmd + " " + fileName);
public void run(Builder m, URI uri, String fileName) {
m.append(BBC.SCHEMATIC_LIST_ELEM.format(fileName, ""));
if (onClickCmd != null) { m.hoverEvent(HoverEvent.showText(TextComponent.of(onClickCmd + " " + fileName)))
.clickEvent(ClickEvent.runCommand(onClickCmd + " " + fileName));
}
}
});
}
public static void list(File dir, Actor actor, InjectedValueAccess args, @Range(min = 0) int page, int perPage, String formatName, boolean playerFolder, RunnableVal3<Message, URI, String> eachMsg) {
public static void list(File dir, Actor actor, InjectedValueAccess args, @Range(min = 0) int page, int perPage, String formatName, boolean playerFolder, RunnableVal3<Builder, URI, String> eachMsg) {
List<File> fileList = new ArrayList<>();
if (perPage == -1) perPage = actor instanceof Player ? 12 : 20; // More pages for console
page = getFiles(dir, actor, args, page, perPage, formatName, playerFolder, fileList::add);
@ -719,7 +739,7 @@ public class UtilityCommands {
return;
}
final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0;
final int sortType = 0; //args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0;
// cleanup file list
fileList.sort((f1, f2) -> {
boolean dir1 = f1.isDirectory();
@ -751,18 +771,18 @@ public class UtilityCommands {
if (fullArgs != null) {
baseCmd = fullArgs.endsWith(" " + page) ? fullArgs.substring(0, fullArgs.length() - (" " + page).length()) : fullArgs;
}
Message m = new Message(BBC.SCHEMATIC_LIST, page, pageCount);
@NonNull Builder m = TextComponent.builder(BBC.SCHEMATIC_LIST.format(page, pageCount));
UUID uuid = playerFolder ? actor.getUniqueId() : null;
for (int i = offset; i < limit; i++) {
m.newline();
m.append(newline());
File file = fileList.get(i);
eachMsg.run(m, file.toURI(), getPath(dir, file, uuid));
}
if (baseCmd != null) {
m.newline().paginate(baseCmd, page, pageCount);
//TODO m.newline().paginate(baseCmd, page, pageCount);
}
m.send(actor);
actor.print(m.build());
}
public static int getFiles(File root, Actor actor, InjectedValueAccess args, int page, int perPage, String formatName, boolean playerFolder, Consumer<File> forEachFile, ListFilters... filters) {

View File

@ -101,7 +101,7 @@ public class WorldEditCommands {
Platform platform = pm.queryCapability(capability);
actor.printDebug(String.format("%s: %s", capability.name(), platform != null ? platform.getPlatformName() : "NONE"));
}
actor.printDebug("------------------------------------");
actor.printDebug("");
actor.printDebug("Wiki: " + "https://github.com/boy0001/FastAsyncWorldedit/wiki");
}

View File

@ -98,7 +98,7 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
protected int range = -1;
private VisualMode visualMode = VisualMode.NONE;
private TargetMode targetMode = TargetMode.TARGET_BLOCK_RANGE;
private Mask traceMask;
private Mask traceMask = null;
private int targetOffset;
private transient BrushSettings primary = new BrushSettings();

View File

@ -26,6 +26,7 @@ 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.function.mask.Mask;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.util.Location;
@ -72,10 +73,11 @@ public class DistanceWand extends BrushTool implements DoubleActionTraceTool {
private Location getTarget(Player player) {
Location target;
Mask mask = getTraceMask();
if (this.range > -1) {
target = player.getBlockTrace(getRange(), true);
target = player.getBlockTrace(getRange(), true, mask);
} else {
target = player.getBlockTrace(DEFAULT_RANGE);
target = player.getBlockTrace(MAX_RANGE, false, mask);
}
if (target == null) {

View File

@ -216,7 +216,7 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
final World world = context.requireWorld();
final BlockVector3 primaryPosition;
try {
primaryPosition = context.requireSession().getRegionSelector(world).getVerticies().get(index - 1);
primaryPosition = context.requireSession().getRegionSelector(world).getVertices().get(index - 1);
} catch (IncompleteRegionException e) {
throw new InputParseException("Your selection is not complete.");
}
@ -356,4 +356,4 @@ public class DefaultBlockParser extends InputParser<BaseBlock> {
}
return holder;
}
}
}

View File

@ -54,7 +54,7 @@ public class DefaultPatternParser extends FaweParser<Pattern> {
public DefaultPatternParser(WorldEdit worldEdit) {
super(worldEdit);
this.dispatcher = new SimpleDispatcher();
this.register(new PatternCommands(worldEdit));
this.register(new PatternCommands());
}
@Override

View File

@ -412,7 +412,7 @@ public abstract class AbstractPlayerActor implements Actor, Player, Cloneable {
if (typeId.hasBlockType()) {
return typeId.getBlockType().getDefaultState().toBaseBlock();
} else {
return BlockTypes.AIR.getDefaultState().toBaseBlock();
throw new NotABlockException();
}
}

View File

@ -59,6 +59,7 @@ import com.sk89q.worldedit.command.HistoryCommandsRegistration;
import com.sk89q.worldedit.command.NavigationCommands;
import com.sk89q.worldedit.command.NavigationCommandsRegistration;
import com.sk89q.worldedit.command.PaintBrushCommands;
import com.sk89q.worldedit.command.PatternCommands;
import com.sk89q.worldedit.command.RegionCommands;
import com.sk89q.worldedit.command.RegionCommandsRegistration;
import com.sk89q.worldedit.command.SchematicCommands;
@ -298,6 +299,20 @@ public final class PlatformCommandManager {
public void registerAllCommands() {
if (Settings.IMP.ENABLED_COMPONENTS.COMMANDS) {
// TODO NOT IMPLEMENTED dunno why these have issues generating
registerSubCommands(
"patterns",
ImmutableList.of(),
"Patterns determine what blocks are placed",
PatternCommandsRegistration.builder(),
new PatternCommands()
);
registerSubCommands(
"transforms",
ImmutableList.of(),
"Transforms modify how a block is placed",
TransformCommandsRegistration.builder(),
new TransformCommands()
);
registerSubCommands(
"schematic",
ImmutableList.of("schem", "/schematic", "/schem"),
@ -654,7 +669,7 @@ public final class PlatformCommandManager {
handleCommandTask(task, context, session, event);
}
public Object handleCommandTask(ThrowableSupplier<Throwable> task, InjectedValueAccess context, @Nullable LocalSession session, CommandEvent event) {
public void handleCommandTask(ThrowableSupplier<Throwable> task, InjectedValueAccess context, @Nullable LocalSession session, CommandEvent event) {
Request.reset();
Actor actor = context.injectedValue(Key.of(Actor.class)).orElseThrow(() -> new IllegalStateException("No player"));
@ -666,7 +681,7 @@ public final class PlatformCommandManager {
// exceptions without writing a hook into every dispatcher, we need to unwrap these
// exceptions and rethrow their converted form, if their is one.
try {
return task.get();
task.get();
} catch (Throwable t) {
// Use the exception converter to convert the exception if any of its causes
// can be converted, otherwise throw the original exception
@ -729,7 +744,6 @@ public final class PlatformCommandManager {
}
event.setCancelled(true);
return null;
}
private MemoizingValueAccess initializeInjectedValues(Arguments arguments, Actor actor) {

View File

@ -41,14 +41,10 @@ import com.sk89q.worldedit.command.tool.TraceTool;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.platform.BlockInteractEvent;
import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent;
import com.sk89q.worldedit.event.platform.Interaction;
import com.sk89q.worldedit.event.platform.PlatformInitializeEvent;
import com.sk89q.worldedit.event.platform.PlatformReadyEvent;
import com.sk89q.worldedit.event.platform.PlayerInputEvent;
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.util.HandSide;
import com.sk89q.worldedit.util.Location;
@ -321,6 +317,8 @@ public class PlatformManager {
LocalSession session = worldEdit.getSessionManager().get(actor);
Request.reset();
Request.request().setSession(session);
Request.request().setWorld(player.getWorld());
try {
Vector3 vector = location.toVector();
@ -335,7 +333,7 @@ public class PlatformManager {
case HIT: {
// superpickaxe is special because its primary interaction is a left click, not a right click
// in addition, it is implicitly bound to all pickaxe items, not just a single tool item
if (session.hasSuperPickAxe()) {
if (session.hasSuperPickAxe() && player.isHoldingPickAxe()) {
final BlockTool superPickaxe = session.getSuperPickaxe();
if (superPickaxe != null && superPickaxe.canUse(player) && player.isHoldingPickAxe()) {
FawePlayer<?> fp = FawePlayer.wrap(player);

View File

@ -43,6 +43,7 @@ import javax.annotation.Nullable;
* A base class for {@link Extent}s that merely passes extents onto another.
*/
public class AbstractDelegateExtent implements Extent, LightingExtent {
private final Extent extent;
/**
@ -60,14 +61,19 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
*
* @return the extent
*/
public final Extent getExtent() {
public Extent getExtent() {
return extent;
}
@Override
public BlockState getBlock(BlockVector3 position) {
return getBlock(position.getX(),position.getY(),position.getZ());
}
/*
Queue based methods
TODO NOT IMPLEMENTED: IQueueExtent and such need to implement these
*/
Queue based methods
TODO NOT IMPLEMENTED: IQueueExtent and such need to implement these
*/
public boolean isQueueEnabled() {
return extent.isQueueEnabled();
}
@ -78,7 +84,8 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
if (!(extent instanceof ForgetfulExtentBuffer)) { // placeholder
extent.disableQueue();
}
} catch (FaweException ignored) {}
} catch (FaweException ignored) {
}
if (extent instanceof AbstractDelegateExtent) {
Extent next = ((AbstractDelegateExtent) extent).getExtent();
new ExtentTraverser(this).setNext(next);
@ -108,8 +115,7 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
} else {
history.setChangeSet(changeSet);
}
}
else if (extent instanceof AbstractDelegateExtent) {
} else if (extent instanceof AbstractDelegateExtent) {
((AbstractDelegateExtent) extent).setChangeSet(changeSet);
} else if (changeSet != null) {
new ExtentTraverser<>(this).setNext(new HistoryExtent(extent, changeSet));
@ -124,21 +130,12 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
/*
Bounds
*/
@Override
public BlockVector3 getMinimumPoint() {
return extent.getMinimumPoint();
}
@Override
public BlockVector3 getMaximumPoint() {
return extent.getMaximumPoint();
}
@Override
public int getMaxY() {
return extent.getMaxY();
}
/*
Input + Output
*/
@ -147,7 +144,6 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
public BlockState getBlock(int x, int y, int z) {
return extent.getBlock(x, y, z);
}
@Override
public BaseBlock getFullBlock(int x, int y, int z) {
return extent.getFullBlock(x, y, z);
@ -164,10 +160,12 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
}
@Override
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block) throws WorldEditException {
public <T extends BlockStateHolder<T>> boolean setBlock(int x, int y, int z, T block)
throws WorldEditException {
return extent.setBlock(x, y, z, block);
}
/*
Light
*/
@ -184,7 +182,6 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
}
return getBrightness(x, y, z);
}
public int getOpacity(int x, int y, int z) {
if (extent instanceof LightingExtent) {
return ((LightingExtent) extent).getOpacity(x, y, z);
@ -217,15 +214,21 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
}
}
/*
Generic
*/
@Override
public String toString() {
return super.toString() + ":" + extent.toString();
}
@Override
public BlockVector3 getMinimumPoint() {
return extent.getMinimumPoint();
}
@Override
public BlockVector3 getMaximumPoint() {
return extent.getMaximumPoint();
}
protected Operation commitBefore() {
return null;
}
@ -234,7 +237,9 @@ public class AbstractDelegateExtent implements Extent, LightingExtent {
public @Nullable Operation commit() {
Operation ours = commitBefore();
Operation other = null;
if (extent != this) other = extent.commit();
if (extent != this) {
other = extent.commit();
}
if (ours != null && other != null) {
return new OperationQueue(ours, other);
} else if (ours != null) {

View File

@ -45,8 +45,6 @@ import javax.annotation.Nullable;
*/
public class NullExtent implements Extent {
public static final NullExtent INSTANCE = new NullExtent();
@Override
public BlockVector3 getMinimumPoint() {
return BlockVector3.ZERO;
@ -73,6 +71,7 @@ public class NullExtent implements Extent {
return null;
}
@Override
public BlockState getBlock(BlockVector3 position) {
return BlockTypes.AIR.getDefaultState();
}

View File

@ -19,9 +19,11 @@
package com.sk89q.worldedit.extent.buffer;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Maps;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.AbstractBufferingExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Masks;
@ -29,16 +31,14 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Optional;
/**
* Buffers changes to an {@link Extent} and allows retrieval of the changed blocks,
* without modifying the underlying extent.
*/
public class ExtentBuffer extends AbstractDelegateExtent {
public class ExtentBuffer extends AbstractBufferingExtent {
private final Map<BlockVector3, BaseBlock> buffer = Maps.newHashMap();
private final Mask mask;
@ -66,6 +66,14 @@ public class ExtentBuffer extends AbstractDelegateExtent {
this.mask = mask;
}
@Override
protected Optional<BaseBlock> getBufferedBlock(BlockVector3 position) {
if (mask.test(position)) {
return Optional.of(buffer.computeIfAbsent(position, (pos -> getExtent().getFullBlock(pos))));
}
return Optional.empty();
}
@Override
public BlockState getBlock(BlockVector3 position) {
if (mask.test(position)) {

View File

@ -61,7 +61,7 @@ public interface Clipboard extends Extent {
/**
* Returns true if the clipboard has biome data. This can be checked since {@link Extent#getBiome(BlockVector2)}
* strongly suggests returning {@link com.sk89q.worldedit.world.biome.BiomeTypes#OCEAN} instead of {@code null}
* strongly suggests returning {@link com.sk89q.worldedit.world.biome.BiomeTypes.OCEAN} instead of {@code null}
* if biomes aren't present. However, it might not be desired to set areas to ocean if the clipboard is defaulting
* to ocean, instead of having biomes explicitly set.
*

View File

@ -72,13 +72,27 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
@Override
public ClipboardWriter getWriter(OutputStream outputStream) throws IOException {
throw new IOException("This format does not support saving, use `.schem` as format");
throw new IOException("This format does not support saving");
}
@Override
public boolean isFormat(File file) {
String name = file.getName().toLowerCase();
return name.endsWith(".schematic") || name.endsWith(".mcedit") || name.endsWith(".mce");
try (NBTInputStream str = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) {
NamedTag rootTag = str.readNamedTag();
if (!rootTag.getName().equals("Schematic")) {
return false;
}
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
// Check
Map<String, Tag> schematic = schematicTag.getValue();
if (!schematic.containsKey("Materials")) {
return false;
}
} catch (Exception e) {
return false;
}
return true;
}
},
SPONGE_SCHEMATIC("sponge", "schem") {
@ -113,8 +127,23 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
@Override
public boolean isFormat(File file) {
String name = file.getName().toLowerCase();
return name.endsWith(".schem") || name.endsWith(".sponge");
try (NBTInputStream str = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) {
NamedTag rootTag = str.readNamedTag();
if (!rootTag.getName().equals("Schematic")) {
return false;
}
CompoundTag schematicTag = (CompoundTag) rootTag.getTag();
// Check
Map<String, Tag> schematic = schematicTag.getValue();
if (!schematic.containsKey("Version")) {
return false;
}
} catch (Exception e) {
return false;
}
return true;
}
},
@ -149,6 +178,8 @@ public enum BuiltInClipboardFormat implements ClipboardFormat {
try (NBTInputStream str = new NBTInputStream(new GZIPInputStream(new FileInputStream(file)))) {
NamedTag rootTag = str.readNamedTag();
CompoundTag structureTag = (CompoundTag) rootTag.getTag();
// Check
Map<String, Tag> structure = structureTag.getValue();
if (!structure.containsKey("DataVersion")) {
return false;

View File

@ -69,7 +69,7 @@ public class ClipboardFormats {
checkNotNull(format);
for (String key : format.getAliases()) {
String lowKey = key.toLowerCase(Locale.ROOT);
String lowKey = key.toLowerCase(Locale.ENGLISH);
ClipboardFormat old = aliasMap.put(lowKey, format);
if (old != null) {
aliasMap.put(lowKey, old);
@ -77,7 +77,7 @@ public class ClipboardFormats {
}
}
for (String ext : format.getFileExtensions()) {
String lowExt = ext.toLowerCase(Locale.ROOT);
String lowExt = ext.toLowerCase(Locale.ENGLISH);
fileExtensionMap.put(lowExt, format);
}
registeredFormats.add(format);
@ -99,7 +99,7 @@ public class ClipboardFormats {
@Nullable
public static ClipboardFormat findByAlias(String alias) {
checkNotNull(alias);
return aliasMap.get(alias.toLowerCase(Locale.ROOT).trim());
return aliasMap.get(alias.toLowerCase(Locale.ENGLISH).trim());
}
/**
@ -157,7 +157,7 @@ public class ClipboardFormats {
* It is not in SchematicCommands because it may rely on internal register calls.
*/
public static String[] getFileExtensionArray() {
return fileExtensionMap.keySet().toArray(new String[0]);
return fileExtensionMap.keySet().toArray(new String[fileExtensionMap.keySet().size()]);
}
private ClipboardFormats() {
@ -259,7 +259,7 @@ public class ClipboardFormats {
File[] files = dir.listFiles(pathname -> {
String input = pathname.getName();
String extension = input.substring(input.lastIndexOf('.') + 1);
return (extensions.contains(extension.toLowerCase()));
return (extensions.contains(extension.toLowerCase(Locale.ENGLISH)));
});
LazyClipboardHolder[] clipboards = new LazyClipboardHolder[files.length];
for (int i = 0; i < files.length; i++) {

View File

@ -19,10 +19,18 @@
package com.sk89q.worldedit.extent.clipboard.io;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.FloatTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.util.Location;
import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Writes {@code Clipboard}s.
@ -39,4 +47,18 @@ public interface ClipboardWriter extends Closeable {
*/
void write(Clipboard clipboard) throws IOException;
default Tag writeVector(Vector3 vector) {
List<DoubleTag> list = new ArrayList<>();
list.add(new DoubleTag(vector.getX()));
list.add(new DoubleTag(vector.getY()));
list.add(new DoubleTag(vector.getZ()));
return new ListTag(DoubleTag.class, list);
}
default Tag writeRotation(Location location) {
List<FloatTag> list = new ArrayList<>();
list.add(new FloatTag(location.getYaw()));
list.add(new FloatTag(location.getPitch()));
return new ListTag(FloatTag.class, list);
}
}

View File

@ -19,9 +19,12 @@
package com.sk89q.worldedit.extent.clipboard.io;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.jnbt.NBTStreamer;
import com.boydti.fawe.jnbt.NBTStreamer.LazyReader;
import com.boydti.fawe.object.FaweInputStream;
import com.boydti.fawe.object.FaweOutputStream;
import com.boydti.fawe.object.clipboard.CPUOptimizedClipboard;
@ -31,21 +34,15 @@ import com.boydti.fawe.object.clipboard.MemoryOptimizedClipboard;
import com.boydti.fawe.object.io.FastByteArrayOutputStream;
import com.boydti.fawe.object.io.FastByteArraysInputStream;
import com.boydti.fawe.util.IOUtil;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NamedTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector2;
@ -60,18 +57,16 @@ import com.sk89q.worldedit.world.block.BlockTypes;
import com.sk89q.worldedit.world.entity.EntityType;
import com.sk89q.worldedit.world.entity.EntityTypes;
import com.sk89q.worldedit.world.storage.NBTConversions;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.DataInputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.function.BiConsumer;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Reads schematic files using the Sponge Schematic Specification.
@ -174,24 +169,18 @@ public class SpongeSchematicReader extends NBTSchematicReader {
/// readBiomes
streamer.addReader("Schematic.BlockData.#", new NBTStreamer.LazyReader() {
@Override
public void accept(Integer arrayLen, DataInputStream dis) {
try (FaweOutputStream blocks = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut))) {
IOUtil.copy(dis, blocks, arrayLen);
} catch (IOException e) {
e.printStackTrace();
}
streamer.addReader("Schematic.BlockData.#", (LazyReader) (arrayLen, dis) -> {
try (FaweOutputStream blocks = new FaweOutputStream(new LZ4BlockOutputStream(blocksOut))) {
IOUtil.copy(dis, blocks, arrayLen);
} catch (IOException e) {
e.printStackTrace();
}
});
streamer.addReader("Schematic.Biomes.#", new NBTStreamer.LazyReader() {
@Override
public void accept(Integer arrayLen, DataInputStream dis) {
try (FaweOutputStream biomes = new FaweOutputStream(new LZ4BlockOutputStream(biomesOut))) {
IOUtil.copy(dis, biomes, arrayLen);
} catch (IOException e) {
e.printStackTrace();
}
streamer.addReader("Schematic.Biomes.#", (LazyReader) (arrayLen, dis) -> {
try (FaweOutputStream biomes = new FaweOutputStream(new LZ4BlockOutputStream(biomesOut))) {
IOUtil.copy(dis, biomes, arrayLen);
} catch (IOException e) {
e.printStackTrace();
}
});
streamer.addReader("Schematic.TileEntities.#", (BiConsumer<Integer, CompoundTag>) (index, value) -> {
@ -291,6 +280,17 @@ public class SpongeSchematicReader extends NBTSchematicReader {
return clipboard;
}
private Clipboard readVersion2(BlockArrayClipboard version1, CompoundTag schematicTag) throws IOException {
Map<String, Tag> schematic = schematicTag.getValue();
if (schematic.containsKey("BiomeData")) {
readBiomes(version1, schematic);
}
if (schematic.containsKey("Entities")) {
readEntities(version1, schematic);
}
return version1;
}
private void readBiomes(BlockArrayClipboard clipboard, Map<String, Tag> schematic) throws IOException {
ByteArrayTag dataTag = requireTag(schematic, "BiomeData", ByteArrayTag.class);
IntTag maxTag = requireTag(schematic, "BiomePaletteMax", IntTag.class);
@ -349,6 +349,36 @@ public class SpongeSchematicReader extends NBTSchematicReader {
}
}
private void readEntities(BlockArrayClipboard clipboard, Map<String, Tag> schematic) throws IOException {
List<Tag> entList = requireTag(schematic, "Entities", ListTag.class).getValue();
if (entList.isEmpty()) {
return;
}
for (Tag et : entList) {
if (!(et instanceof CompoundTag)) {
continue;
}
CompoundTag entityTag = (CompoundTag) et;
Map<String, Tag> tags = entityTag.getValue();
String id = requireTag(tags, "Id", StringTag.class).getValue();
entityTag = entityTag.createBuilder().putString("id", id).remove("Id").build();
if (fixer != null) {
entityTag = fixer.fixUp(DataFixer.FixTypes.ENTITY, entityTag, dataVersion);
}
EntityType entityType = EntityTypes.get(id);
if (entityType != null) {
Location location = NBTConversions.toLocation(clipboard,
requireTag(tags, "Pos", ListTag.class),
requireTag(tags, "Rotation", ListTag.class));
BaseEntity state = new BaseEntity(entityType, entityTag);
clipboard.createEntity(location, state);
} else {
log.warn("Unknown entity when pasting schematic: " + id);
}
}
}
@Override
public void close() throws IOException {
inputStream.close();

View File

@ -19,13 +19,19 @@
package com.sk89q.worldedit.extent.clipboard.io;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.jnbt.NBTStreamer;
import com.boydti.fawe.object.clipboard.FaweClipboard;
import com.boydti.fawe.util.IOUtil;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.collect.Maps;
import com.sk89q.jnbt.*;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.IntArrayTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.entity.Entity;
@ -34,18 +40,13 @@ import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.biome.BiomeTypes;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataOutput;
@ -53,13 +54,13 @@ import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import net.jpountz.lz4.LZ4BlockInputStream;
import net.jpountz.lz4.LZ4BlockOutputStream;
/**
* Writes schematic files using the Sponge schematic format.
@ -345,21 +346,6 @@ public class SpongeSchematicWriter implements ClipboardWriter {
schematic.writeNamedTag("Entities", new ListTag(CompoundTag.class, entities));
}
private static Tag writeVector(Vector3 vector) {
List<DoubleTag> list = new ArrayList<>();
list.add(new DoubleTag(vector.getX()));
list.add(new DoubleTag(vector.getY()));
list.add(new DoubleTag(vector.getZ()));
return new ListTag(DoubleTag.class, list);
}
private static Tag writeRotation(Location location) {
List<FloatTag> list = new ArrayList<>();
list.add(new FloatTag(location.getYaw()));
list.add(new FloatTag(location.getPitch()));
return new ListTag(FloatTag.class, list);
}
@Override
public void close() throws IOException {
outputStream.close();

View File

@ -28,14 +28,10 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Nullable;
/**
* Applies a {@link BlockBag} to operations.
@ -44,7 +40,7 @@ public class BlockBagExtent extends AbstractDelegateExtent {
private final boolean mine;
private int[] missingBlocks = new int[BlockTypes.size()];
private final BlockBag blockBag;
private BlockBag blockBag;
/**
* Create a new instance.
@ -52,13 +48,12 @@ public class BlockBagExtent extends AbstractDelegateExtent {
* @param extent the extent
* @param blockBag the block bag
*/
public BlockBagExtent(Extent extent, @Nonnull BlockBag blockBag) {
public BlockBagExtent(Extent extent, @Nullable BlockBag blockBag) {
this(extent, blockBag, false);
}
public BlockBagExtent(Extent extent, @Nonnull BlockBag blockBag, boolean mine) {
public BlockBagExtent(Extent extent, @Nullable BlockBag blockBag, boolean mine) {
super(extent);
checkNotNull(blockBag);
this.blockBag = blockBag;
this.mine = mine;
}
@ -72,6 +67,14 @@ public class BlockBagExtent extends AbstractDelegateExtent {
return blockBag;
}
/**
* Set the block bag.
*
* @param blockBag a block bag, which may be null if none is used
*/
public void setBlockBag(@Nullable BlockBag blockBag) {
this.blockBag = blockBag;
}
/**
* Gets the list of missing blocks and clears the list for the next
* operation.

View File

@ -19,22 +19,24 @@
package com.sk89q.worldedit.extent.reorder;
import com.google.common.collect.Table;
import com.google.common.collect.TreeBasedTable;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.AbstractBufferingExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.RunContext;
import com.sk89q.worldedit.function.operation.SetLocatedBlocks;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.collection.LocatedBlockList;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
/**
* A special extent that batches changes into Minecraft chunks. This helps
@ -42,17 +44,19 @@ import java.util.TreeMap;
* loaded repeatedly, however it does take more memory due to caching the
* blocks.
*/
public class ChunkBatchingExtent extends AbstractDelegateExtent {
public class ChunkBatchingExtent extends AbstractBufferingExtent {
/**
* Comparator optimized for sorting chunks by the region file they reside
* in. This allows for file caches to be used while loading the chunk.
*/
private static final Comparator<BlockVector2> REGION_OPTIMIZED_SORT =
Comparator.comparing((BlockVector2 vec) -> vec.divide(32), BlockVector2.COMPARING_GRID_ARRANGEMENT)
Comparator.comparing((BlockVector2 vec) -> vec.shr(5), BlockVector2.COMPARING_GRID_ARRANGEMENT)
.thenComparing(BlockVector2.COMPARING_GRID_ARRANGEMENT);
private final SortedMap<BlockVector2, LocatedBlockList> batches = new TreeMap<>(REGION_OPTIMIZED_SORT);
private final Table<BlockVector2, BlockVector3, BaseBlock> batches =
TreeBasedTable.create(REGION_OPTIMIZED_SORT, BlockVector3.sortByCoordsYzx());
private final Set<BlockVector3> containedBlocks = new HashSet<>();
private boolean enabled;
public ChunkBatchingExtent(Extent extent) {
@ -76,16 +80,32 @@ public class ChunkBatchingExtent extends AbstractDelegateExtent {
return enabled;
}
private BlockVector2 getChunkPos(BlockVector3 location) {
return location.shr(4).toBlockVector2();
}
private BlockVector3 getInChunkPos(BlockVector3 location) {
return BlockVector3.at(location.getX() & 15, location.getY(), location.getZ() & 15);
}
@Override
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
if (!enabled) {
return getExtent().setBlock(location, block);
return setDelegateBlock(location, block);
}
BlockVector2 chunkPos = BlockVector2.at(location.getBlockX() >> 4, location.getBlockZ() >> 4);
batches.computeIfAbsent(chunkPos, k -> new LocatedBlockList()).add(location, block);
BlockVector2 chunkPos = getChunkPos(location);
BlockVector3 inChunkPos = getInChunkPos(location);
batches.put(chunkPos, inChunkPos, block.toBaseBlock());
containedBlocks.add(location);
return true;
}
@Override
protected Optional<BaseBlock> getBufferedBlock(BlockVector3 position) {
if (!containedBlocks.contains(position)) {
return Optional.empty();
}
return Optional.of(batches.get(getChunkPos(position), getInChunkPos(position)));
}
@Override
protected Operation commitBefore() {
if (!commitRequired()) {
@ -94,17 +114,22 @@ public class ChunkBatchingExtent extends AbstractDelegateExtent {
return new Operation() {
// we get modified between create/resume -- only create this on resume to prevent CME
private Iterator<LocatedBlockList> batchIterator;
private Iterator<Map.Entry<BlockVector2, Map<BlockVector3, BaseBlock>>> batchIterator;
@Override
public Operation resume(RunContext run) throws WorldEditException {
if (batchIterator == null) {
batchIterator = batches.values().iterator();
batchIterator = batches.rowMap().entrySet().iterator();
}
if (!batchIterator.hasNext()) {
return null;
}
new SetLocatedBlocks(getExtent(), batchIterator.next()).resume(run);
Map.Entry<BlockVector2, Map<BlockVector3, BaseBlock>> next = batchIterator.next();
BlockVector3 chunkOffset = next.getKey().toBlockVector3().shl(4);
for (Map.Entry<BlockVector3, BaseBlock> block : next.getValue().entrySet()) {
getExtent().setBlock(block.getKey().add(chunkOffset), block.getValue());
containedBlocks.remove(block.getKey());
}
batchIterator.remove();
return this;
}

View File

@ -20,7 +20,7 @@
package com.sk89q.worldedit.extent.reorder;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.AbstractBufferingExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.operation.Operation;
import com.sk89q.worldedit.function.operation.OperationQueue;
@ -33,16 +33,19 @@ import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
/**
* Re-orders blocks into several stages.
*/
public class MultiStageReorder extends AbstractDelegateExtent implements ReorderingExtent {
public class MultiStageReorder extends AbstractBufferingExtent implements ReorderingExtent {
private static final Map<BlockType, PlacementPriority> priorityMap = new HashMap<>();
@ -139,6 +142,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
priorityMap.put(BlockTypes.MOVING_PISTON, PlacementPriority.FINAL);
}
private final Set<BlockVector3> containedBlocks = new HashSet<>();
private Map<PlacementPriority, LocatedBlockList> stages = new HashMap<>();
private boolean enabled;
@ -212,7 +216,7 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
@Override
public <B extends BlockStateHolder<B>> boolean setBlock(BlockVector3 location, B block) throws WorldEditException {
if (!enabled) {
return super.setBlock(location, block);
return setDelegateBlock(location, block);
}
BlockState existing = getBlock(location);
@ -240,9 +244,21 @@ public class MultiStageReorder extends AbstractDelegateExtent implements Reorder
}
stages.get(priority).add(location, block);
containedBlocks.add(location);
return !existing.equalsFuzzy(block);
}
@Override
protected Optional<BaseBlock> getBufferedBlock(BlockVector3 position) {
if (!containedBlocks.contains(position)) {
return Optional.empty();
}
return stages.values().stream()
.map(blocks -> blocks.get(position))
.filter(Objects::nonNull)
.findAny();
}
@Override
public Operation commitBefore() {
if (!commitRequired()) {

View File

@ -50,7 +50,7 @@ public class BlockReplace implements RegionFunction {
@Override
public boolean apply(BlockVector3 position) throws WorldEditException {
return pattern.apply(extent, position, position);
return extent.setBlock(position, pattern.apply(position));
}
}

View File

@ -147,17 +147,33 @@ public class ExtentEntityCopy implements EntityFunction {
CompoundTag tag = state.getNbtData();
if (tag != null) {
// Handle leashed entities
Tag leashTag = tag.getValue().get("Leash");
if (leashTag instanceof CompoundTag) {
CompoundTag leashCompound = (CompoundTag) leashTag;
if (leashCompound.containsKey("X")) { // leashed to a fence
Vector3 tilePosition = Vector3.at(leashCompound.asInt("X"), leashCompound.asInt("Y"), leashCompound.asInt("Z"));
BlockVector3 newLeash = transform.apply(tilePosition.subtract(from)).add(to).toBlockPoint();
return new BaseEntity(state.getType(), tag.createBuilder()
.put("Leash", leashCompound.createBuilder()
.putInt("X", newLeash.getBlockX())
.putInt("Y", newLeash.getBlockY())
.putInt("Z", newLeash.getBlockZ())
.build()
).build());
}
}
boolean changed = false;
// Handle hanging entities (paintings, item frames, etc.)
boolean hasTilePosition = tag.containsKey("TileX") && tag.containsKey("TileY") && tag.containsKey("TileZ");
boolean hasFacing = tag.containsKey("Facing");
tag = tag.createBuilder().build();
Map<String, Tag> values = ReflectionUtils.getMap(tag.getValue());
boolean hasTilePosition = tag.containsKey("TileX") && tag.containsKey("TileY") && tag.containsKey("TileZ");
boolean hasDirection = tag.containsKey("Direction");
boolean hasLegacyDirection = tag.containsKey("Dir");
boolean hasFacing = tag.containsKey("Facing");
if (hasTilePosition) {
changed = true;

View File

@ -44,7 +44,7 @@ public abstract class AbstractExtentMask extends AbstractMask {
*
* @return the extent
*/
public final Extent getExtent() {
public Extent getExtent() {
return extent;
}

View File

@ -20,9 +20,11 @@
package com.sk89q.worldedit.function.mask;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockCategory;
import javax.annotation.Nullable;
/**
* A mask that tests whether a block matches a given {@link BlockCategory}, or tag.
@ -39,7 +41,12 @@ public class BlockCategoryMask extends AbstractExtentMask {
@Override
public boolean test(BlockVector3 vector) {
return category.contains(vector.getBlock(getExtent()));
return category.contains(getExtent().getBlock(vector));
}
@Nullable
@Override
public Mask2D toMask2D() {
return null;
}
}

View File

@ -19,6 +19,8 @@
package com.sk89q.worldedit.function.mask;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.NullExtent;
import com.sk89q.worldedit.math.BlockVector3;
@ -31,8 +33,17 @@ import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.function.Predicate;
import javax.annotation.Nullable;
/**
* A mask that checks whether blocks at the given positions are matched by
* a block in a list.
*
* <p>This mask checks for both an exact block type and state value match,
* respecting fuzzy status of the BlockState.</p>
*/
public class BlockMask extends ABlockMask {
private final boolean[] ordinals;
public BlockMask() {
@ -49,6 +60,10 @@ public class BlockMask extends ABlockMask {
}
/**
* Create a new block mask.
*
* @param extent the extent
* @param blocks a list of blocks to match
* @deprecated NBT not supported by this mask
*/
@Deprecated
@ -57,11 +72,23 @@ public class BlockMask extends ABlockMask {
add(blocks);
}
/**
* Create a new block mask.
*
* @param extent the extent
* @param block an array of blocks to match
*/
public BlockMask(Extent extent, BaseBlock... block) {
this(extent, Arrays.asList(checkNotNull(block)));
}
public BlockMask add(Predicate<BlockState> predicate) {
for (int i = 0; i < ordinals.length; i++) {
if (!ordinals[i]) {
BlockState state = BlockTypes.states[i];
if (state != null) ordinals[i] = predicate.test(state);
if (state != null) {
ordinals[i] = predicate.test(state);
}
}
}
return this;
@ -73,7 +100,9 @@ public class BlockMask extends ABlockMask {
}
public BlockMask remove(BlockState... states) {
for (BlockState state : states) ordinals[state.getOrdinal()] = false;
for (BlockState state : states) {
ordinals[state.getOrdinal()] = false;
}
return this;
}
@ -84,13 +113,17 @@ public class BlockMask extends ABlockMask {
public boolean isEmpty() {
for (boolean value : ordinals) {
if (value) return false;
if (value) {
return false;
}
}
return true;
}
public BlockMask addStates(Collection<BlockState> states) {
for (BlockState state : states) ordinals[state.getOrdinal()] = true;
private BlockMask addStates(Collection<BlockState> states) {
for (BlockState state : states) {
ordinals[state.getOrdinal()] = true;
}
return this;
}
@ -99,7 +132,7 @@ public class BlockMask extends ABlockMask {
return this;
}
public BlockMask addTypes(Collection<BlockType> types) {
private BlockMask addTypes(Collection<BlockType> types) {
for (BlockType type : types) {
for (BlockState state : type.getAllStates()) {
ordinals[state.getOrdinal()] = true;
@ -109,6 +142,9 @@ public class BlockMask extends ABlockMask {
}
/**
* Add the given blocks to the list of criteria.
*
* @param blocks a list of blocks
* @deprecated NBT not supported by this mask
*/
@Deprecated
@ -118,6 +154,15 @@ public class BlockMask extends ABlockMask {
}
}
/**
* Add the given blocks to the list of criteria.
*
* @param block an array of blocks
*/
public void add(BaseBlock... block) {
add(Arrays.asList(checkNotNull(block)));
}
@Override
public boolean test(BlockState state) {
return ordinals[state.getOrdinal()];
@ -156,6 +201,12 @@ public class BlockMask extends ABlockMask {
return null;
}
@Nullable
@Override
public Mask2D toMask2D() {
return null;
}
@Override
public Mask tryOptimize() {
int setStates = 0;
@ -218,7 +269,11 @@ public class BlockMask extends ABlockMask {
}
if (setTypes == totalTypes - 1) {
return new InverseSingleBlockTypeMask(getExtent(), unsetType);
if (unsetType != null) {
return new InverseSingleBlockTypeMask(getExtent(), unsetType);
} else {
throw new IllegalArgumentException("unsetType cannot be null when passed to InverseSingleBlockTypeMask");
}
}
return null;
@ -227,7 +282,9 @@ public class BlockMask extends ABlockMask {
@Override
public Mask inverse() {
boolean[] cloned = ordinals.clone();
for (int i = 0; i < cloned.length; i++) cloned[i] = !cloned[i];
for (int i = 0; i < cloned.length; i++) {
cloned[i] = !cloned[i];
}
return new BlockMask(getExtent(), cloned);
}
}

View File

@ -19,7 +19,6 @@
package com.sk89q.worldedit.function.mask;
import com.boydti.fawe.beta.FilterBlock;
import com.google.common.collect.Maps;
import com.sk89q.worldedit.blocks.Blocks;
import com.sk89q.worldedit.extent.Extent;
@ -27,8 +26,8 @@ import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import java.util.Map;
import javax.annotation.Nullable;
@Deprecated
public class BlockStateMask extends AbstractExtentMask {
@ -66,4 +65,9 @@ public class BlockStateMask extends AbstractExtentMask {
.allMatch(entry -> block.getState(entry.getKey()) == entry.getValue());
}
@Nullable
@Override
public Mask2D toMask2D() {
return null;
}
}

View File

@ -20,15 +20,16 @@
package com.sk89q.worldedit.function.mask;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import javax.annotation.Nullable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import javax.annotation.Nullable;
import org.jetbrains.annotations.NotNull;
/**
* A mask that checks whether blocks at the given positions are matched by
@ -38,10 +39,8 @@ import java.util.Set;
* use {@link BlockMask}.</p>
* @deprecated use BlockMaskBuilder
*/
import static com.google.common.base.Preconditions.checkNotNull;
@Deprecated
public final class BlockTypeMask extends AbstractExtentMask {
public class BlockTypeMask extends AbstractExtentMask {
private final boolean[] types;
@ -51,7 +50,7 @@ public final class BlockTypeMask extends AbstractExtentMask {
* @param extent the extent
* @param blocks a list of blocks to match
*/
public BlockTypeMask(Extent extent, Collection<BlockType> blocks) {
public BlockTypeMask(Extent extent, @NotNull Collection<BlockType> blocks) {
this(extent, blocks.toArray(new BlockType[0]));
}
@ -61,23 +60,18 @@ public final class BlockTypeMask extends AbstractExtentMask {
* @param extent the extent
* @param block an array of blocks to match
*/
public BlockTypeMask(Extent extent, BlockType... block) {
public BlockTypeMask(Extent extent, @NotNull BlockType... block) {
super(extent);
this.types = new boolean[BlockTypes.size()];
for (BlockType type : block) this.types[type.getInternalId()] = true;
}
protected BlockTypeMask(Extent extent, boolean[] types) {
super(extent);
this.types = types;
}
/**
* Add the given blocks to the list of criteria.
*
* @param blocks a list of blocks
*/
public void add(Collection<BlockType> blocks) {
public void add(@NotNull Collection<BlockType> blocks) {
checkNotNull(blocks);
for (BlockType type : blocks) {
add(type);
@ -92,7 +86,7 @@ public final class BlockTypeMask extends AbstractExtentMask {
*
* @param block an array of blocks
*/
public void add(BlockType... block) {
public void add(@NotNull BlockType... block) {
for (BlockType type : block) {
this.types[type.getInternalId()] = true;
}
@ -120,4 +114,10 @@ public final class BlockTypeMask extends AbstractExtentMask {
return types[block.getInternalId()];
}
@Nullable
@Override
public Mask2D toMask2D() {
return null;
}
}

View File

@ -20,7 +20,9 @@
package com.sk89q.worldedit.function.mask;
import static com.google.common.base.Preconditions.checkArgument;
import com.sk89q.worldedit.math.BlockVector3;
import javax.annotation.Nullable;
/**
* Has the criteria where the Y value of passed positions must be within
@ -48,4 +50,9 @@ public class BoundedHeightMask extends AbstractMask {
return vector.getY() >= minY && vector.getY() <= maxY;
}
@Nullable
@Override
public Mask2D toMask2D() {
return null;
}
}

View File

@ -19,9 +19,9 @@
package com.sk89q.worldedit.function.mask;
import com.boydti.fawe.beta.FilterBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import javax.annotation.Nullable;
/**
* A mask that returns true whenever the block at the location is not
@ -40,7 +40,13 @@ public class ExistingBlockMask extends AbstractExtentMask {
@Override
public boolean test(BlockVector3 vector) {
return !vector.getBlock(getExtent()).getMaterial().isAir();
return !getExtent().getBlock(vector).getBlockType().getMaterial().isAir();
}
@Nullable
@Override
public Mask2D toMask2D() {
return null;
}
}

View File

@ -1,10 +1,8 @@
package com.sk89q.worldedit.function.mask;
import com.boydti.fawe.beta.FilterBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;

View File

@ -22,17 +22,12 @@ package com.sk89q.worldedit.function.mask;
import com.boydti.fawe.beta.DelegateFilter;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.FilterBlock;
import com.sk89q.minecraft.util.commands.Link;
import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.math.BlockVector3;
import javax.annotation.Nullable;
/**
* Tests whether a given vector meets a criteria.
*/
@Link(clazz = UtilityCommands.class, value = "masks")
public interface Mask {
/**

View File

@ -22,11 +22,9 @@ package com.sk89q.worldedit.function.mask;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.beta.FilterBlock;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.MutableVector3;
import com.sk89q.worldedit.math.noise.NoiseGenerator;
import javax.annotation.Nullable;
/**
@ -87,8 +85,8 @@ public class NoiseFilter extends AbstractMask {
}
@Override
public boolean test(BlockVector3 v) {
return noiseGenerator.noise(MutableVector3.get(v.getX(), v.getY(), v.getZ())) <= density;
public boolean test(BlockVector3 vector) {
return noiseGenerator.noise(MutableVector3.get(vector.getX(), vector.getY(), vector.getZ())) <= density;
}
@Nullable

View File

@ -63,4 +63,9 @@ public class RegionMask extends AbstractMask {
return region.contains(vector);
}
@Nullable
@Override
public Mask2D toMask2D() {
return null;
}
}

View File

@ -21,6 +21,8 @@ package com.sk89q.worldedit.function.mask;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BlockState;
import javax.annotation.Nullable;
public class SolidBlockMask extends BlockMask {
@ -29,6 +31,13 @@ public class SolidBlockMask extends BlockMask {
add(state -> state.getMaterial().isMovementBlocker());
}
@Override
public boolean test(BlockVector3 vector) {
Extent extent = getExtent();
BlockState block = extent.getBlock(vector);
return block.getBlockType().getMaterial().isMovementBlocker();
}
@Nullable
@Override
public Mask2D toMask2D() {

View File

@ -19,16 +19,14 @@
package com.sk89q.worldedit.function.operation;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.inventory.BlockBag;
import com.sk89q.worldedit.history.UndoContext;
import com.sk89q.worldedit.history.change.Change;
import com.sk89q.worldedit.history.changeset.ChangeSet;
import java.util.Iterator;
import java.util.List;
@ -68,13 +66,12 @@ public class ChangeSetExecutor implements Operation {
@Override
public Operation resume(RunContext run) throws WorldEditException {
while (iterator.hasNext()) {
Change change = iterator.next();
if (type == Type.UNDO) {
while (iterator.hasNext()) {
iterator.next().undo(context);
}
change.undo(context);
} else {
while (iterator.hasNext()) {
iterator.next().redo(context);
change.redo(context);
}
}
return null;

View File

@ -22,7 +22,6 @@ package com.sk89q.worldedit.function.operation;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.beta.IQueueExtent;
import com.boydti.fawe.object.extent.BlockTranslateExtent;
import com.boydti.fawe.object.extent.PositionTransformExtent;
import com.boydti.fawe.object.function.block.BiomeCopy;
@ -30,7 +29,6 @@ import com.boydti.fawe.object.function.block.CombinedBlockCopy;
import com.boydti.fawe.object.function.block.SimpleBlockCopy;
import com.boydti.fawe.util.MaskTraverser;
import com.google.common.collect.Lists;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.entity.metadata.EntityProperties;
@ -74,7 +72,7 @@ public class ForwardExtentCopy implements Operation {
private int repetitions = 1;
private Mask sourceMask = Masks.alwaysTrue();
private boolean removingEntities;
private boolean copyingEntities = true; // default to true for backwards compatibility, sort of // No, it's not for compatibility, it makes sense for entities to be copied and people will get annoyed if it doesn't
private boolean copyingEntities = true; // default to true for backwards compatibility, sort of
private boolean copyingBiomes;
private RegionFunction sourceFunction = null;
private Transform transform = new Identity();

View File

@ -1,18 +1,11 @@
package com.sk89q.worldedit.function.pattern;
import com.sk89q.minecraft.util.commands.Link;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockStateHolder;
/**
* Returns a {@link BlockStateHolder} for a given position.
* - Adapts the vector apply to integer
*/
@Link(clazz = UtilityCommands.class, value = "patterns")
public interface FawePattern extends Pattern {
//
// @Deprecated

View File

@ -21,9 +21,7 @@ package com.sk89q.worldedit.function.pattern;
import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.FilterBlock;
import com.sk89q.minecraft.util.commands.Link;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.world.block.BaseBlock;
@ -32,7 +30,6 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
/**
* Returns a {@link BlockStateHolder} for a given position.
*/
@Link(clazz = UtilityCommands.class, value = "patterns")
public interface Pattern extends Filter {
/**

View File

@ -20,19 +20,13 @@
package com.sk89q.worldedit.function.pattern;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockMaskBuilder;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.registry.state.Property;
import com.sk89q.worldedit.registry.state.PropertyKey;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import com.sk89q.worldedit.world.block.BlockType;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.lang.ref.SoftReference;
import java.util.Map;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
/**
* Removes the waterlogged state from blocks if possible. If not possible, returns air.
@ -42,9 +36,9 @@ public class WaterloggedRemover extends AbstractExtentPattern {
private static SoftReference<BlockState[]> cache = new SoftReference<>(null);
private synchronized BlockState[] getRemap() {
BlockState[] remap = this.cache.get();
BlockState[] remap = cache.get();
if (remap != null) return remap;
this.cache = new SoftReference<>(remap = new BlockState[BlockTypes.states.length]);
cache = new SoftReference<>(remap = new BlockState[BlockTypes.states.length]);
// init
for (int i = 0; i < remap.length; i++) {
@ -76,4 +70,4 @@ public class WaterloggedRemover extends AbstractExtentPattern {
}
return BlockTypes.AIR.getDefaultState().toBaseBlock();
}
}
}

View File

@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.collection.BlockVectorSet;
import com.google.common.collect.Sets;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.function.operation.Operation;
@ -130,7 +131,7 @@ public abstract class BreadthFirstSearch implements Operation {
* Add the directions along the axes as directions to visit.
*/
public void addAxes() {
HashSet<BlockVector3> set = new HashSet<>(Arrays.asList(directions));
HashSet<BlockVector3> set = Sets.newHashSet(directions);
set.add(BlockVector3.UNIT_MINUS_Y);
set.add(BlockVector3.UNIT_Y);
set.add(BlockVector3.UNIT_MINUS_X);
@ -144,7 +145,7 @@ public abstract class BreadthFirstSearch implements Operation {
* Add the diagonal directions as directions to visit.
*/
public void addDiagonal() {
HashSet<BlockVector3> set = new HashSet<>(Arrays.asList(directions));
HashSet<BlockVector3> set = Sets.newHashSet(directions);
set.add(Direction.NORTHEAST.toBlockVector());
set.add(Direction.SOUTHEAST.toBlockVector());
set.add(Direction.SOUTHWEST.toBlockVector());
@ -175,6 +176,22 @@ public abstract class BreadthFirstSearch implements Operation {
}
}
/**
* Try to visit the given 'to' location.
*
* @param from the origin block
* @param to the block under question
*/
private void visit(BlockVector3 from, BlockVector3 to) {
BlockVector3 blockVector = to;
if (!visited.contains(blockVector)) {
visited.add(blockVector);
if (isVisitable(from, to)) {
queue.add(blockVector);
}
}
}
public void setVisited(BlockVectorSet set) {
this.visited = set;
}
@ -213,11 +230,8 @@ public abstract class BreadthFirstSearch implements Operation {
@Override
public Operation resume(RunContext run) throws WorldEditException {
MutableBlockVector3 mutable = new MutableBlockVector3();
// MutableBlockVector3 mutable2 = new MutableBlockVector3();
boolean shouldTrim = false;
BlockVector3[] dirs = directions;
BlockVectorSet tempQueue = new BlockVectorSet();
BlockVectorSet chunkLoadSet = new BlockVectorSet();
for (currentDepth = 0; !queue.isEmpty() && currentDepth <= maxDepth; currentDepth++) {
for (BlockVector3 from : queue) {
if (function.apply(from)) affected++;
@ -244,9 +258,7 @@ public abstract class BreadthFirstSearch implements Operation {
BlockVectorSet tmp = queue;
queue = tempQueue;
tmp.clear();
chunkLoadSet.clear();
tempQueue = tmp;
}
return null;
}

View File

@ -70,17 +70,13 @@ public class RegionVisitor implements Operation {
@Override
public Operation resume(RunContext run) throws WorldEditException {
for (BlockVector3 pt : iterable) {
apply(pt);
if (function.apply(pt)) {
affected++;
}
}
return null;
}
private void apply(BlockVector3 pt) throws WorldEditException {
if (function.apply(pt)) {
affected++;
}
}
@Override
public void cancel() {
}

View File

@ -55,7 +55,9 @@ public class BlockOptimizedHistory extends ArrayListHistory {
if (change instanceof BlockChange) {
BlockChange blockChange = (BlockChange) change;
BlockVector3 position = blockChange.getPosition();
previous.add(position, blockChange.getPrevious());
if (!previous.containsLocation(position)) {
previous.add(position, blockChange.getPrevious());
}
current.add(position, blockChange.getCurrent());
} else {
super.add(change);

View File

@ -19,9 +19,7 @@
package com.sk89q.worldedit.math;
import com.google.common.collect.ComparisonChain;
import com.sk89q.worldedit.math.transform.AffineTransform;
import java.util.Comparator;
/**
@ -48,25 +46,31 @@ public class BlockVector2 {
* cdef
* </pre>
*/
public static final Comparator<BlockVector2> COMPARING_GRID_ARRANGEMENT = (a, b) -> {
return ComparisonChain.start()
.compare(a.getBlockZ(), b.getBlockZ())
.compare(a.getBlockX(), b.getBlockX())
.result();
};
public static final Comparator<BlockVector2> COMPARING_GRID_ARRANGEMENT =
Comparator.comparingInt(BlockVector2::getZ).thenComparingInt(BlockVector2::getX);
public static BlockVector2 at(double x, double z) {
return at((int) Math.floor(x), (int) Math.floor(z));
}
public static BlockVector2 at(int x, int z) {
switch (x) {
case 0:
if (z == 0) {
return ZERO;
}
break;
case 1:
if (z == 1) {
return ONE;
}
break;
}
return new BlockVector2(x, z);
}
protected int x, z;
protected BlockVector2(){}
/**
* Construct an instance.
*
@ -342,6 +346,26 @@ public class BlockVector2 {
return divide(n, n);
}
/**
* Shift all components right.
*
* @param x the value to shift x by
* @param z the value to shift z by
* @return a new vector
*/
public BlockVector2 shr(int x, int z) {
return at(this.x >> x, this.z >> z);
}
/**
* Shift all components right by {@code n}.
*
* @param n the value to shift by
* @return a new vector
*/
public BlockVector2 shr(int n) {
return shr(n, n);
}
/**
* Get the length of the vector.
*
@ -572,4 +596,4 @@ public class BlockVector2 {
return "(" + x + ", " + z + ")";
}
}
}

View File

@ -21,14 +21,12 @@ package com.sk89q.worldedit.math;
import static com.google.common.base.Preconditions.checkArgument;
import com.google.common.collect.ComparisonChain;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.world.biome.BiomeType;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockState;
import java.util.Comparator;
/**
@ -50,11 +48,26 @@ public abstract class BlockVector3 {
}
public static BlockVector3 at(int x, int y, int z) {
// switch for efficiency on typical cases
// in MC y is rarely 0/1 on selections
switch (y) {
case 0:
if (x == 0 && z == 0) {
return ZERO;
}
break;
case 1:
if (x == 1 && z == 1) {
return ONE;
}
break;
}
return new BlockVector3Imp(x, y, z);
}
// thread-safe initialization idiom
private static final class YzxOrderComparator {
private static final Comparator<BlockVector3> YZX_ORDER =
Comparator.comparingInt(BlockVector3::getY)
.thenComparingInt(BlockVector3::getZ)
@ -240,8 +253,7 @@ public abstract class BlockVector3 {
}
/**
* Add a list of vectors to this vector and return the
* result as a new vector.
* Add a list of vectors to this vector and return the result as a new vector.
*
* @param others an array of vectors
* @return a new vector
@ -259,8 +271,7 @@ public abstract class BlockVector3 {
}
/**
* Subtract another vector from this vector and return the result
* as a new vector.
* Subtract another vector from this vector and return the result as a new vector.
*
* @param other the other vector
* @return a new vector
@ -270,8 +281,7 @@ public abstract class BlockVector3 {
}
/**
* Subtract another vector from this vector and return the result
* as a new vector.
* Subtract another vector from this vector and return the result as a new vector.
*
* @param x the value to subtract
* @param y the value to subtract
@ -283,8 +293,7 @@ public abstract class BlockVector3 {
}
/**
* Subtract a list of vectors from this vector and return the result
* as a new vector.
* Subtract a list of vectors from this vector and return the result as a new vector.
*
* @param others an array of vectors
* @return a new vector
@ -469,8 +478,7 @@ public abstract class BlockVector3 {
}
/**
* Get the normalized vector, which is the vector divided by its
* length, as a new vector.
* Get the normalized vector, which is the vector divided by its length, as a new vector.
*
* @return a new vector
*/
@ -514,7 +522,8 @@ public abstract class BlockVector3 {
* @return true if the vector is contained
*/
public boolean containedWithin(BlockVector3 min, BlockVector3 max) {
return getX() >= min.getX() && getX() <= max.getX() && getY() >= min.getY() && getY() <= max.getY() && getZ() >= min.getZ() && getZ() <= max.getZ();
return getX() >= min.getX() && getX() <= max.getX() && getY() >= min.getY() && getY() <= max
.getY() && getZ() >= min.getZ() && getZ() <= max.getZ();
}
/**
@ -568,8 +577,7 @@ public abstract class BlockVector3 {
}
/**
* Returns a vector with the absolute values of the components of
* this vector.
* Returns a vector with the absolute values of the components of this vector.
*
* @return a new vector
*/
@ -580,15 +588,16 @@ public abstract class BlockVector3 {
/**
* Perform a 2D transformation on this vector and return a new one.
*
* @param angle in degrees
* @param aboutX about which x coordinate to rotate
* @param aboutZ about which z coordinate to rotate
* @param angle in degrees
* @param aboutX about which x coordinate to rotate
* @param aboutZ about which z coordinate to rotate
* @param translateX what to add after rotation
* @param translateZ what to add after rotation
* @return a new vector
* @see AffineTransform another method to transform vectors
*/
public BlockVector3 transform2D(double angle, double aboutX, double aboutZ, double translateX, double translateZ) {
public BlockVector3 transform2D(double angle, double aboutX, double aboutZ, double translateX,
double translateZ) {
angle = Math.toRadians(angle);
double x = this.getX() - aboutX;
double z = this.getZ() - aboutZ;
@ -599,7 +608,7 @@ public abstract class BlockVector3 {
return BlockVector3.at(
x2 + aboutX + translateX,
getY(),
getY(),
z2 + aboutZ + translateZ
);
}
@ -646,9 +655,9 @@ public abstract class BlockVector3 {
*/
public BlockVector3 getMinimum(BlockVector3 v2) {
return new BlockVector3Imp(
Math.min(getX(), v2.getX()),
Math.min(getY(), v2.getY()),
Math.min(getZ(), v2.getZ())
Math.min(getX(), v2.getX()),
Math.min(getY(), v2.getY()),
Math.min(getZ(), v2.getZ())
);
}
@ -660,9 +669,9 @@ public abstract class BlockVector3 {
*/
public BlockVector3 getMaximum(BlockVector3 v2) {
return new BlockVector3Imp(
Math.max(getX(), v2.getX()),
Math.max(getY(), v2.getY()),
Math.max(getZ(), v2.getZ())
Math.max(getX(), v2.getX()),
Math.max(getY(), v2.getY()),
Math.max(getZ(), v2.getZ())
);
}
@ -685,7 +694,7 @@ public abstract class BlockVector3 {
}
public boolean setFullBlock(Extent orDefault, BaseBlock block) {
return orDefault.setBlock(this, block);
return orDefault.setBlock(this, block);
}
public boolean setBiome(Extent orDefault, BiomeType biome) {
@ -724,11 +733,6 @@ public abstract class BlockVector3 {
return orDefault.getBlock(getX(), getY() + y, getZ());
}
/*
Adapt
*/
/**
* Creates a 2D vector by dropping the Y component from this vector.
*
@ -743,7 +747,7 @@ public abstract class BlockVector3 {
}
@Override
public final boolean equals(Object obj) {
public boolean equals(Object obj) {
if (!(obj instanceof BlockVector3)) {
return false;
}
@ -752,7 +756,8 @@ public abstract class BlockVector3 {
}
public final boolean equals(BlockVector3 other) {
return other.getX() == this.getX() && other.getY() == this.getY() && other.getZ() == this.getZ();
return other.getX() == this.getX() && other.getY() == this.getY() && other.getZ() == this
.getZ();
}
@Override

View File

@ -2,9 +2,6 @@ package com.sk89q.worldedit.math;
public class MutableVector2 extends Vector2 {
public MutableVector2() {
}
/**
* Construct an instance.
*

View File

@ -3,9 +3,12 @@ package com.sk89q.worldedit.math;
import com.boydti.fawe.FaweCache;
public class MutableVector3 extends Vector3 {
private double x,y,z;
private double x, y, z;
public MutableVector3() {
}
public static MutableVector3 get(int x, int y, int z) {
return FaweCache.MUTABLE_VECTOR3.get().setComponents(x, y, z);
}

View File

@ -33,13 +33,24 @@ public class Vector2 {
public static final Vector2 ONE = new Vector2(1, 1);
public static Vector2 at(double x, double z) {
int xTrunc = (int) x;
switch (xTrunc) {
case 0:
if (x == 0 && z == 0) {
return ZERO;
}
break;
case 1:
if (x == 1 && z == 1) {
return ONE;
}
break;
}
return new Vector2(x, z);
}
protected double x, z;
protected Vector2(){}
/**
* Construct an instance.
*
@ -491,7 +502,7 @@ public class Vector2 {
@Override
public int hashCode() {
return ((int) x << 16) ^ ((int) z);
return (int) x << 16 ^ (int) z;
}
@Override

View File

@ -39,6 +39,21 @@ public abstract class Vector3 {
public static final Vector3 ONE = Vector3.at(1, 1, 1);
public static Vector3 at(double x, double y, double z) {
// switch for efficiency on typical cases
// in MC y is rarely 0/1 on selections
int yTrunc = (int) y;
switch (yTrunc) {
case 0:
if (x == 0 && y == 0 && z == 0) {
return ZERO;
}
break;
case 1:
if (x == 1 && y == 1 && z == 1) {
return ONE;
}
break;
}
return new Vector3Impl(x, y, z);
}

View File

@ -36,6 +36,7 @@ import com.sk89q.worldedit.world.block.BlockStateHolder;
import com.sk89q.worldedit.world.block.BlockTypes;
import java.util.Iterator;
import javax.annotation.Nullable;
/**
* Allows applications of Kernels onto the region's height map.
@ -63,11 +64,11 @@ public class HeightMap {
this(session, region, (Mask) null, false);
}
public HeightMap(EditSession session, Region region, Mask mask) {
public HeightMap(EditSession session, Region region, @Nullable Mask mask) {
this(session, region, mask, false);
}
public HeightMap(EditSession session, Region region, Mask mask, boolean layers) {
public HeightMap(EditSession session, Region region, @Nullable Mask mask, boolean layers) {
checkNotNull(session);
checkNotNull(region);

View File

@ -22,8 +22,6 @@ package com.sk89q.worldedit.math.transform;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.MathUtils;
import com.sk89q.worldedit.math.Vector3;
import java.io.IOException;
import java.io.Serializable;
/**

View File

@ -106,6 +106,20 @@ public abstract class AbstractRegion extends AbstractSet<BlockVector3> implement
return points;
}
/**
* Get the number of blocks in the region.
*
* @return number of blocks
*/
@Override
public int getArea() {
BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint();
return (max.getX() - min.getX() + 1) *
(max.getY() - min.getY() + 1) *
(max.getZ() - min.getZ() + 1);
}
/**
* Get X-size.
*

View File

@ -392,6 +392,14 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
return chunks;
}
@Override
public boolean contains(BlockVector3 position) {
BlockVector3 min = getMinimumPoint();
BlockVector3 max = getMaximumPoint();
return position.containedWithin(min, max);
}
@Override
public boolean contains(int x, int y, int z) {
return x >= this.minX && x <= this.maxX && z >= this.minZ && z <= this.maxZ && y >= this.minY && y <= this.maxY;
@ -511,14 +519,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
if (++nextZ > max.getBlockZ()) {
nextZ = min.getBlockZ();
if (++nextY > max.getBlockY()) {
if (!hasNext) {
throw new NoSuchElementException("End of iterator") {
@Override
public Throwable fillInStackTrace() {
return this;
}
};
}
if (!hasNext()) throw new NoSuchElementException();
nextX = max.getBlockX();
nextZ = max.getBlockZ();
nextY = max.getBlockY();
@ -546,12 +547,7 @@ public class CuboidRegion extends AbstractRegion implements FlatRegion {
@Override
public BlockVector2 next() {
if (!hasNext()) throw new NoSuchElementException() {
@Override
public synchronized Throwable fillInStackTrace() {
return this;
}
};
if (!hasNext()) throw new NoSuchElementException();
BlockVector2 answer = BlockVector2.at(nextX, nextZ);
if (++nextX > max.getBlockX()) {
nextX = min.getBlockX();

View File

@ -293,6 +293,22 @@ public class CylinderRegion extends AbstractRegion implements FlatRegion {
minY += changeY;
}
/**
* Checks to see if a point is inside this region.
*/
@Override
public boolean contains(BlockVector3 position) {
final int blockY = position.getBlockY();
if (blockY < minY || blockY > maxY) {
return false;
}
return position.toBlockVector2().subtract(center).toVector2().divide(radius).lengthSq() <= 1;
}
/**
* Checks to see if a point is inside this region.
*/
@Override
public boolean contains(int x, int y, int z) {
if (y < minY || y > maxY) {

View File

@ -24,17 +24,13 @@ import com.boydti.fawe.beta.Filter;
import com.boydti.fawe.beta.IChunk;
import com.boydti.fawe.beta.IChunkGet;
import com.boydti.fawe.beta.IChunkSet;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.MutableBlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.world.World;
import javax.annotation.Nullable;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import javax.annotation.Nullable;
/**
* Represents a physical shape.

View File

@ -158,11 +158,11 @@ public interface RegionSelector {
List<String> getInformationLines();
/**
* Get the verticies
* Get the vertices
* @return
* @throws IncompleteRegionException
*/
default List<BlockVector3> getVerticies() throws IncompleteRegionException {
default List<BlockVector3> getVertices() throws IncompleteRegionException {
return Collections.singletonList(getPrimaryPosition());
}
}

View File

@ -0,0 +1,191 @@
/*
* 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.regions;
import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.math.BlockVector2;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.math.Vector3;
import com.sk89q.worldedit.math.transform.Identity;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.world.World;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Nullable;
/**
* Transforms another region according to a provided vector {@code Transform}.
*
* @see Transform
*/
public class TransformRegion extends AbstractRegion {
private final Region region;
private Transform transform = new Identity();
/**
* Create a new instance.
*
* @param region the region
* @param transform the transform
*/
public TransformRegion(Region region, Transform transform) {
this(null, region, transform);
}
/**
* Create a new instance.
*
* @param world the world, which may be null
* @param region the region
* @param transform the transform
*/
public TransformRegion(@Nullable World world, Region region, Transform transform) {
super(world);
checkNotNull(region);
checkNotNull(transform);
this.region = region;
this.transform = transform;
}
/**
* Get the untransformed, base region.
*
* @return the base region
*/
public Region getRegion() {
return region;
}
/**
* Get the transform that is applied.
*
* @return the transform
*/
public Transform getTransform() {
return transform;
}
/**
* Set the transform that is applied.
*
* @param transform the transform
*/
public void setTransform(Transform transform) {
checkNotNull(transform);
this.transform = transform;
}
@Override
public BlockVector3 getMinimumPoint() {
return transform.apply(region.getMinimumPoint().toVector3()).toBlockPoint();
}
@Override
public BlockVector3 getMaximumPoint() {
return transform.apply(region.getMaximumPoint().toVector3()).toBlockPoint();
}
@Override
public Vector3 getCenter() {
return transform.apply(region.getCenter());
}
@Override
public int getArea() {
return region.getArea(); // Cannot transform this
}
@Override
public int getWidth() {
return getMaximumPoint().subtract(getMinimumPoint()).getBlockX() + 1;
}
@Override
public int getHeight() {
return getMaximumPoint().subtract(getMinimumPoint()).getBlockY() + 1;
}
@Override
public int getLength() {
return getMaximumPoint().subtract(getMinimumPoint()).getBlockZ() + 1;
}
@Override
public void expand(BlockVector3... changes) throws RegionOperationException {
throw new RegionOperationException("Can't expand a TransformedRegion");
}
@Override
public void contract(BlockVector3... changes) throws RegionOperationException {
throw new RegionOperationException("Can't contract a TransformedRegion");
}
@Override
public void shift(BlockVector3 change) throws RegionOperationException {
throw new RegionOperationException("Can't change a TransformedRegion");
}
@Override
public boolean contains(BlockVector3 position) {
return region.contains(transform.inverse().apply(position.toVector3()).toBlockPoint());
}
@Override
public List<BlockVector2> polygonize(int maxPoints) {
List<BlockVector2> origPoints = region.polygonize(maxPoints);
List<BlockVector2> transformedPoints = new ArrayList<>();
for (BlockVector2 vector : origPoints) {
transformedPoints.add(transform.apply(vector.toVector3(0)).toVector2().toBlockPoint());
}
return transformedPoints;
}
@Override
public Iterator<BlockVector3> iterator() {
final Iterator<BlockVector3> it = region.iterator();
return new Iterator<BlockVector3>() {
@Override
public boolean hasNext() {
return it.hasNext();
}
@Override
public BlockVector3 next() {
BlockVector3 next = it.next();
if (next != null) {
return transform.apply(next.toVector3()).toBlockPoint();
} else {
return null;
}
}
@Override
public void remove() {
it.remove();
}
};
}
}

View File

@ -278,7 +278,7 @@ public class ConvexPolyhedralRegionSelector implements RegionSelector, CUIRegion
}
@Override
public List<BlockVector3> getVerticies() {
public List<BlockVector3> getVertices() {
return new ArrayList<>(region.getVertices());
}
}

View File

@ -302,7 +302,7 @@ public class CuboidRegionSelector implements RegionSelector, CUIRegion {
}
@Override
public List<BlockVector3> getVerticies() {
public List<BlockVector3> getVertices() {
return Arrays.asList(position1, position2);
}
}

View File

@ -31,7 +31,7 @@ public class BooleanProperty extends AbstractProperty<Boolean> {
this(name, values, 0);
}
public BooleanProperty(final String name, final List<Boolean> values, int bitOffset) {
private BooleanProperty(final String name, final List<Boolean> values, int bitOffset) {
super(name, values, bitOffset);
defaultIndex = values.get(0).booleanValue() == Boolean.TRUE ? 0 : 1;
}

View File

@ -35,7 +35,7 @@ public class DirectionalProperty extends AbstractProperty<Direction> {
this(name, values, 0);
}
public DirectionalProperty(final String name, final List<Direction> values, int bitOffset) {
private DirectionalProperty(final String name, final List<Direction> values, int bitOffset) {
super(name, values, bitOffset);
this.map = new int[Direction.values().length];
Arrays.fill(this.map, -1);

View File

@ -19,12 +19,9 @@
package com.sk89q.worldedit.registry.state;
import com.sk89q.worldedit.util.Direction;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.annotation.Nullable;
public class EnumProperty extends AbstractProperty<String> {
@ -35,7 +32,7 @@ public class EnumProperty extends AbstractProperty<String> {
this(name, values, 0);
}
public EnumProperty(final String name, final List<String> values, int bitOffset) {
private EnumProperty(final String name, final List<String> values, int bitOffset) {
super(name, values, bitOffset);
for (int i = 0; i < values.size(); i++) {
String value = values.get(i).intern();
@ -51,7 +48,7 @@ public class EnumProperty extends AbstractProperty<String> {
@Override
public int getIndexFor(CharSequence string) throws IllegalArgumentException {
Integer value = offsets.get(string);
Integer value = offsets.get(string.toString());
return value == null ? -1 : value;
}

View File

@ -34,7 +34,7 @@ public class IntegerProperty extends AbstractProperty<Integer> {
this(name, values, 0);
}
public IntegerProperty(final String name, final List<Integer> values, int bitOffset) {
private IntegerProperty(final String name, final List<Integer> values, int bitOffset) {
super(name, values, bitOffset);
int max = Collections.max(values);
this.map = new int[max + 1];
@ -67,9 +67,10 @@ public class IntegerProperty extends AbstractProperty<Integer> {
public Integer getValueFor(String string) {
try {
int val = Integer.parseInt(string);
// if (!getValues().contains(val)) { // This check is slow
// throw new IllegalArgumentException("Invalid int value: " + string + ". Must be in " + getValues().toString());
// }
//It shouldn't matter if this check is slow. It's an important check
if (!getValues().contains(val)) {
throw new IllegalArgumentException("Invalid int value: " + string + ". Must be in " + getValues().toString());
}
return val;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid int value: " + string + ". Not an int.");

View File

@ -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.scripting;
import org.mozilla.javascript.ClassShutter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Hides Minecraft's obfuscated & de-obfuscated names from scripts.
*/
class MinecraftHidingClassShutter implements ClassShutter {
private static final Logger LOGGER = LoggerFactory.getLogger(MinecraftHidingClassShutter.class);
@Override
public boolean visibleToScripts(String fullClassName) {
if (!fullClassName.contains(".")) {
// Default package -- probably Minecraft
return false;
}
return !fullClassName.startsWith("net.minecraft");
}
}

View File

@ -24,7 +24,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.boydti.fawe.util.MaskTraverser;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.extent.clipboard.BlockArrayClipboard;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.function.RegionFunction;
@ -152,7 +151,7 @@ public class PasteBuilder {
copy.setFilterFunction(this.canApply);
}
if (ignoreAirBlocks) {
sourceMask = MaskIntersection.of(sourceMask, new ExistingBlockMask(clipboard));
sourceMask = new MaskIntersection(sourceMask, new ExistingBlockMask(clipboard));
}
if (targetExtent instanceof EditSession) {
Mask esSourceMask = ((EditSession) targetExtent).getSourceMask();

View File

@ -20,6 +20,7 @@
package com.sk89q.worldedit.session;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import com.google.common.util.concurrent.ListeningExecutorService;
@ -28,6 +29,8 @@ import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.tool.InvalidToolBindException;
import com.sk89q.worldedit.command.tool.NavigationWand;
import com.sk89q.worldedit.command.tool.SelectionWand;
import com.sk89q.worldedit.command.tool.Tool;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.platform.ConfigurationLoadEvent;
@ -40,10 +43,6 @@ import com.sk89q.worldedit.util.eventbus.Subscribe;
import com.sk89q.worldedit.world.gamemode.GameModes;
import com.sk89q.worldedit.world.item.ItemType;
import com.sk89q.worldedit.world.item.ItemTypes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.annotation.Nullable;
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
@ -53,6 +52,9 @@ import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;
import java.util.concurrent.Callable;
import javax.annotation.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Session manager for WorldEdit.
@ -162,6 +164,19 @@ public class SessionManager {
session.setConfiguration(config);
session.setBlockChangeLimit(config.defaultChangeLimit);
session.setTimeout(config.calculationTimeout);
try {
if (owner.hasPermission("worldedit.selection.pos")) {
setDefaultWand(session.getWandItem(), config.wandItem, session, new SelectionWand());
}
if (owner.hasPermission("worldedit.navigation.jumpto.tool") || owner.hasPermission("worldedit.navigation.thru.tool")) {
setDefaultWand(session.getNavWandItem(), config.navigationWand, session, new NavigationWand());
}
} catch (InvalidToolBindException e) {
if (!warnedInvalidTool) {
warnedInvalidTool = true;
log.warn("Invalid wand tool set in config. Tool will not be assigned: " + e.getItemType());
}
}
// Remember the session regardless of if it's currently active or not.
// And have the SessionTracker FLUSH inactive sessions.

View File

@ -23,66 +23,67 @@ import static com.google.common.base.Preconditions.checkNotNull;
import com.sk89q.worldedit.math.BlockVector3;
import com.sk89q.worldedit.util.LocatedBlock;
import com.sk89q.worldedit.world.block.BaseBlock;
import com.sk89q.worldedit.world.block.BlockStateHolder;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import javax.annotation.Nullable;
/**
* Wrapper around a list of blocks located in the world.
*/
public class LocatedBlockList implements Iterable<LocatedBlock> {
private final List<LocatedBlock> list;
private final Map<BlockVector3, LocatedBlock> map = new LinkedHashMap<>();
public LocatedBlockList() {
list = new ArrayList<>();
}
public LocatedBlockList(Collection<? extends LocatedBlock> collection) {
list = new ArrayList<>(collection);
for (LocatedBlock locatedBlock : collection) {
map.put(locatedBlock.getLocation(), locatedBlock);
}
}
public void add(LocatedBlock setBlockCall) {
checkNotNull(setBlockCall);
list.add(setBlockCall);
map.put(setBlockCall.getLocation(), setBlockCall);
}
public <B extends BlockStateHolder<B>> void add(BlockVector3 location, B block) {
add(new LocatedBlock(location, block.toBaseBlock()));
}
public boolean containsLocation(BlockVector3 location) {
return map.containsKey(location);
}
public @Nullable BaseBlock get(BlockVector3 location) {
return map.get(location).getBlock();
}
public int size() {
return list.size();
return map.size();
}
public void clear() {
list.clear();
map.clear();
}
@Override
public Iterator<LocatedBlock> iterator() {
return list.iterator();
return map.values().iterator();
}
public Iterator<LocatedBlock> reverseIterator() {
return new Iterator<LocatedBlock>() {
private final ListIterator<LocatedBlock> backingIterator = list.listIterator(list.size());
@Override
public boolean hasNext() {
return backingIterator.hasPrevious();
}
@Override
public LocatedBlock next() {
return backingIterator.previous();
}
};
List<LocatedBlock> data = new ArrayList<>(map.values());
Collections.reverse(data);
return data.iterator();
}
}

View File

@ -284,8 +284,4 @@ public interface World extends Extent {
return true;
}
@Override
default World getWorld() {
return this;
}
}