Fixes #68
Fixes #69
Fixes #80
Fixes #70
Fixes #72
added heightmap brush
This commit is contained in:
Jesse Boyd 2016-05-01 11:10:39 +10:00
parent b9f2671166
commit 024d46be78
39 changed files with 2286 additions and 144 deletions

3
.gitignore vendored
View File

@ -20,5 +20,4 @@ gradle.log
/bukkit/build
/bukkit0/build
/bukkit19/build
/bukkit18/build
/core/build
/bukkit18/build

View File

@ -248,8 +248,6 @@ public class FaweBukkit implements IFawe, Listener {
} catch (final Throwable e) {
e.printStackTrace();
}
} else {
Fawe.debug("Plugin 'WorldGuard' not found. Worldguard features disabled.");
}
final Plugin plotmePlugin = Bukkit.getServer().getPluginManager().getPlugin("PlotMe");
if ((plotmePlugin != null) && plotmePlugin.isEnabled()) {
@ -259,8 +257,6 @@ public class FaweBukkit implements IFawe, Listener {
} catch (final Throwable e) {
e.printStackTrace();
}
} else {
Fawe.debug("Plugin 'PlotMe' not found. PlotMe features disabled.");
}
final Plugin townyPlugin = Bukkit.getServer().getPluginManager().getPlugin("Towny");
if ((townyPlugin != null) && townyPlugin.isEnabled()) {
@ -270,8 +266,6 @@ public class FaweBukkit implements IFawe, Listener {
} catch (final Throwable e) {
e.printStackTrace();
}
} else {
Fawe.debug("Plugin 'Towny' not found. Towny features disabled.");
}
final Plugin factionsPlugin = Bukkit.getServer().getPluginManager().getPlugin("Factions");
if ((factionsPlugin != null) && factionsPlugin.isEnabled()) {
@ -292,8 +286,6 @@ public class FaweBukkit implements IFawe, Listener {
}
}
} else {
Fawe.debug("Plugin 'Factions' not found. Factions features disabled.");
}
final Plugin residencePlugin = Bukkit.getServer().getPluginManager().getPlugin("Residence");
if ((residencePlugin != null) && residencePlugin.isEnabled()) {
@ -303,8 +295,6 @@ public class FaweBukkit implements IFawe, Listener {
} catch (final Throwable e) {
e.printStackTrace();
}
} else {
Fawe.debug("Plugin 'Residence' not found. Factions features disabled.");
}
final Plugin griefpreventionPlugin = Bukkit.getServer().getPluginManager().getPlugin("GriefPrevention");
if ((griefpreventionPlugin != null) && griefpreventionPlugin.isEnabled()) {
@ -314,8 +304,6 @@ public class FaweBukkit implements IFawe, Listener {
} catch (final Throwable e) {
e.printStackTrace();
}
} else {
Fawe.debug("Plugin 'GriefPrevention' not found. GriefPrevention features disabled.");
}
final Plugin preciousstonesPlugin = Bukkit.getServer().getPluginManager().getPlugin("PreciousStones");
if ((preciousstonesPlugin != null) && preciousstonesPlugin.isEnabled()) {
@ -325,8 +313,6 @@ public class FaweBukkit implements IFawe, Listener {
} catch (final Throwable e) {
e.printStackTrace();
}
} else {
Fawe.debug("Plugin 'PreciousStones' not found. PreciousStones features disabled.");
}
return managers;
}

View File

@ -9,6 +9,7 @@ jar.enabled = false
shadowJar {
dependencies {
include(dependency(':bukkit0'))
include(dependency(':core'))
}
archiveName = "${parent.name}-${project.name}.jar"
destinationDir = file '../target'

View File

@ -4,7 +4,6 @@ import com.boydti.fawe.FaweCache;
import com.boydti.fawe.example.CharFaweChunk;
import com.boydti.fawe.util.FaweQueue;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import net.minecraft.server.v1_9_R1.Block;
import net.minecraft.server.v1_9_R1.DataBits;
import net.minecraft.server.v1_9_R1.DataPalette;
@ -51,28 +50,29 @@ public class BukkitChunk_1_9 extends CharFaweChunk<Chunk> {
if (current == null) {
continue;
}
DataPaletteBlock paletteBlock = new DataPaletteBlock();
// Clone palette
DataPalette currentPalette = (DataPalette) fieldPalette.get(paletteBlock);
DataPalette currentPalette = (DataPalette) fieldPalette.get(current);
if (!(currentPalette instanceof DataPaletteGlobal)) {
try {
Method resize = DataPaletteBlock.class.getDeclaredMethod("b", int.class);
resize.setAccessible(true);
resize.invoke(paletteBlock, 128);
} catch (Throwable e) {
e.printStackTrace();
}
current.a(128, null);
}
DataPaletteBlock paletteBlock = new DataPaletteBlock();
currentPalette = (DataPalette) fieldPalette.get(current);
if (!(currentPalette instanceof DataPaletteGlobal)) {
throw new RuntimeException("Palette must be global!");
}
currentPalette = (DataPalette) fieldPalette.get(paletteBlock);
fieldPalette.set(paletteBlock, currentPalette);
// Clone size
fieldSize.set(paletteBlock, fieldSize.get(current));
// Clone pallete
// Clone palette
DataBits currentBits = (DataBits) fieldBits.get(current);
DataBits newBits = new DataBits(1, 0);
for (Field field : DataBits.class.getDeclaredFields()) {
field.setAccessible(true);
field.set(newBits, field.get(currentBits));
Object currentValue = field.get(currentBits);
if (currentValue instanceof long[]) {
currentValue = ((long[]) currentValue).clone();
}
field.set(newBits, currentValue);
}
fieldBits.set(paletteBlock, newBits);
value.sectionPalettes[i] = paletteBlock;

View File

@ -43,8 +43,17 @@ import org.bukkit.generator.ChunkGenerator;
public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], DataPaletteBlock> {
private IBlockData air;
public BukkitQueue_1_9_R1(final String world) {
super(world);
try {
Field fieldAir = DataPaletteBlock.class.getDeclaredField("a");
fieldAir.setAccessible(true);
air = (IBlockData) fieldAir.get(null);
} catch (Throwable e) {
e.printStackTrace();
}
}
@Override
@ -315,9 +324,12 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], Dat
char combinedId = array[FaweCache.CACHE_J[y][x][z]];
switch (combinedId) {
case 0:
IBlockData existing = nibble.a(x, y, z);
if (existing != air) {
nonEmptyBlockCount++;
}
continue;
case 1:
// TODO check existing
nibble.setBlock(x, y, z, Blocks.AIR.getBlockData());
continue;
default:

View File

@ -24,6 +24,8 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.BrushCommands;
import com.sk89q.worldedit.command.ClipboardCommands;
import com.sk89q.worldedit.command.HistoryCommands;
import com.sk89q.worldedit.command.RegionCommands;
import com.sk89q.worldedit.command.SchematicCommands;
import com.sk89q.worldedit.command.ScriptingCommands;
import com.sk89q.worldedit.command.composition.SelectionCommand;
@ -44,6 +46,7 @@ import com.sk89q.worldedit.function.visitor.RegionVisitor;
import com.sk89q.worldedit.history.change.EntityCreate;
import com.sk89q.worldedit.history.change.EntityRemove;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import java.io.File;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
@ -174,6 +177,7 @@ public class Fawe {
try {
WEManager.IMP.managers.addAll(Fawe.this.IMP.getMaskManagers());
WEManager.IMP.managers.add(new PlotSquaredFeature());
Fawe.debug("Plugin 'PlotSquared' found. Using it now.");
} catch (Throwable e) {}
Fawe.this.worldedit = WorldEdit.getInstance();
// Events
@ -238,8 +242,12 @@ public class Fawe {
SchematicCommands.inject();
ScriptingCommands.inject();
SelectionCommand.inject();
RegionCommands.inject();
HistoryCommands.inject();
// Brushes
GravityBrush.inject();
// Selectors
CuboidRegionSelector.inject();
// Visitors
BreadthFirstSearch.inject();
DownwardVisitor.inject();

View File

@ -1,7 +1,6 @@
package com.boydti.fawe.command;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweCommand;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.util.MainUtil;
@ -15,7 +14,7 @@ public class Reload extends FaweCommand {
@Override
public boolean execute(final FawePlayer player, final String... args) {
Fawe.get().setupConfigs();
MainUtil.sendMessage(player, "&d" + BBC.PREFIX.s() + " Reloaded configuration");
MainUtil.sendMessage(player, "Reloaded configuration");
return true;
}
}

View File

@ -46,7 +46,7 @@ public class Rollback extends FaweCommand {
}
player.deleteMeta("rollback");
final FaweLocation origin = player.getLocation();
rollback(player, !player.hasPermission("fawe.rollback.deep"), Arrays.copyOfRange(args, 1, args.length), new RunnableVal<List<DiskStorageHistory>>() {
rollback(player, true, Arrays.copyOfRange(args, 1, args.length), new RunnableVal<List<DiskStorageHistory>>() {
@Override
public void run(List<DiskStorageHistory> edits) {
long total = 0;
@ -94,7 +94,7 @@ public class Rollback extends FaweCommand {
@Override
public void run() {
if (edits.size() == 0) {
player.sendMessage("&d" + BBC.PREFIX.s() + " Rollback complete!");
player.sendMessage("Rollback complete!");
return;
}
DiskStorageHistory edit = edits.remove(0);

View File

@ -4,6 +4,7 @@ import com.boydti.fawe.Fawe;
import com.boydti.fawe.configuration.file.YamlConfiguration;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.util.StringMan;
import com.sk89q.worldedit.extension.platform.Actor;
import java.io.File;
import java.util.EnumSet;
import java.util.HashMap;
@ -16,14 +17,10 @@ public enum BBC {
* Things to note about this class:
* Can use multiple arguments %s, %s1, %s2, %s3 etc
*/
PREFIX("[FAWE]", "Info"),
COMMAND_SYNTAX("&cUsage: &7%s0", "Error"),
NO_PERM("&cYou are lacking the permission node: %s0", "Error"),
SCHEMATIC_NOT_FOUND("&cSchematic not found: &7%s0", "Error"),
PREFIX("&8(&5&lFAWE&8)&7", "Info"),
SCHEMATIC_PASTING("&7The schematic is pasting. This cannot be undone.", "Info"),
FIX_LIGHTING_CHUNK("&7Lighting has been fixed in your current chunk. Relog to see the affect.", "Info"),
FIX_LIGHTING_SELECTION("&7Lighting has been fixed in %s0 chunks. Relog to see the affect.", "Info"),
NO_REGION("&cYou have no current WorldEdit region", "Error"),
SET_REGION("&7Selection set to your current WorldEdit region", "Info"),
WORLDEDIT_COMMAND_LIMIT("&7Please wait until your current action completes", "Info"),
WORLDEDIT_DELAYED("&7Please wait while we process your WorldEdit action...", "Info"),
@ -39,6 +36,76 @@ public enum BBC {
WORLDEDIT_BYPASSED("&7Currently bypassing WorldEdit restriction.", "Info"),
WORLDEDIT_UNMASKED("&6Your WorldEdit is now unrestricted.", "Info"),
WORLDEDIT_RESTRICTED("&6Your WorldEdit is now restricted.", "Info"),
WORLDEDIT_OOM_ADMIN("&cPossible options:\n&8 - &7//fast\n&8 - &7Do smaller edits\n&8 - &7Allocate more memory\n&8 - &7Disable this safeguard", "Info"),
COMPRESSED("History compressed. Saved ~ %s0b (%s1x smaller)", "Info"),
ACTION_COMPLETE("Action completed in %s0 seconds", "Info"),
COMMAND_COPY("%s0 blocks were copied", "WorldEdit.Copy"),
COMMAND_PASTE("The clipboard has been pasted at %s0", "WorldEdit.Paste"),
COMMAND_ROTATE("The clipboard has been rotated", "WorldEdit.Rotate"),
COMMAND_FLIPPED("The clipboard has been flipped", "WorldEdit.Flip"),
COMMAND_REGEN("Region regenerated.", "WorldEdit.Regen"),
COMMAND_TREE("%s0 trees created.", "WorldEdit.Tree"),
COMMAND_FLORA("%s0 flora created.", "WorldEdit.Flora"),
COMMAND_HISTORY_CLEAR("History cleared", "WorldEdit.History"),
COMMAND_REDO_FAIL("Nothing left to redo.", "WorldEdit.History"),
COMMAND_REDO_SUCCESS("Redo successful.", "WorldEdit.History"),
COMMAND_UNDO_FAIL("Nothing left to undo.", "WorldEdit.History"),
COMMAND_UNDO_SUCCESS("Undo successful.", "WorldEdit.History"),
OPERATION("Operation complete (%s0)", "WorldEdit.Operation"),
SELECTION_WAND("Left click: select pos #1; Right click: select pos #2", "WorldEdit.Selection"),
SELECTION_WAND_DISABLE("Edit wand disabled.", "WorldEdit.Selection"),
SELECTION_WAND_ENABLE("Edit wand enabled.", "WorldEdit.Selection"),
SELECTION_CHUNK("Chunk selected (%s0)", "WorldEdit.Selection"),
SELECTION_CHUNKS("Chunks selected (%s0) - (%s1)", "WorldEdit.Selection"),
SELECTION_CONTRACT("Region contracted %s0 blocks.", "WorldEdit.Selection"),
SELECTION_COUNT("Counted %s0 blocks.", "WorldEdit.Selection"),
SELECTION_DISTR("# total blocks: %s0", "WorldEdit.Selection"),
SELECTION_EXPAND("Region expanded %s0 blocks", "WorldEdit.Selection"),
SELECTION_EXPAND_VERT("Region expanded %s0 blocks (top to bottom)", "WorldEdit.Selection"),
SELECTION_INSET("Region inset", "WorldEdit.Selection"),
SELECTION_OUTSET("Region outset", "WorldEdit.Selection"),
SELECTION_SHIFT("Region shifted", "WorldEdit.Selection"),
SELECTION_CLEARED("Selection cleared", "WorldEdit.Selection"),
BRUSH_BUTCHER("Butcher brush equiped (%s0)", "WorldEdit.Brush"),
BRUSH_CLIPBOARD("Clipboard brush shape equipped", "WorldEdit.Brush"),
BRUSH_CYLINDER("Cylinder brush shape equipped (%s0 by %s1).", "WorldEdit.Brush"),
BRUSH_EXTINGUISHER("Extinguisher equipped (%s0).", "WorldEdit.Brush"),
BRUSH_GRAVITY("Gravity brush equipped (%s0)", "WorldEdit.Brush"),
BRUSH_HEIGHT("Height brush equipped (%s0)", "WorldEdit.Brush"),
BRUSH_HEIGHT_INVALID("Invalid height map file (%s0)", "WorldEdit.Brush"),
BRUSH_SMOOTH("Smooth brush equipped (%s0 x %s1 using %s2).", "WorldEdit.Brush"),
BRUSH_SPHERE("Sphere brush shape equipped (%s0).", "WorldEdit.Brush"),
SCHEMATIC_DELETE("%s0 has been deleted.", "Worldedit.Schematic"),
SCHEMATIC_FORMAT("Available clipboard formats (Name: Lookup names)", "Worldedit.Schematic"),
SCHEMATIC_LIST("Available schematics (Filename (Format)):", "Worldedit.Schematic"),
SCHEMATIC_LOADED("%s0 loaded. Paste it with //paste", "Worldedit.Schematic"),
SCHEMATIC_SAVED("%s0 saved.", "Worldedit.Schematic"),
CLIPBOARD_CLEARED("Clipboard cleared", "WorldEdit.Clipboard"),
VISITOR_BLOCK("%s0 blocks affected", "WorldEdit.Visitor"),
VISITOR_ENTITY("%s0 entities affected", "WorldEdit.Visitor"),
VISITOR_FLAT("%s0 columns affected", "WorldEdit.Visitor"),
SELECTOR_CUBOID_POS1("First position set to %s0 %s1.", "WorldEdit.Selector"),
SELECTOR_CUBOID_POS2("Second position set to %s0 %s1.", "WorldEdit.Selector"),
COMMAND_SYNTAX("&cUsage: &7%s0", "Error"),
NO_PERM("&cYou are lacking the permission node: %s0", "Error"),
SCHEMATIC_NOT_FOUND("&cSchematic not found: &7%s0", "Error"),
NO_REGION("&cYou have no current WorldEdit region", "Error"),
NOT_PLAYER("&cYou must be a player to perform this action!", "Error"),
OOM(
"&8[&cCritical&8] &cDetected low memory i.e. < 1%. FAWE will take the following actions:\n&8 - &7Terminate WE block placement\n&8 - &7Clear WE history\n&8 - &7Unload non essential chunks\n&8 - &7Kill entities\n&8 - &7Garbage collect\n&cIgnore this if trying to crash server.\n&7Note: Low memory is likely (but not necessarily) caused by WE",
"Error"),
WORLDEDIT_CANCEL_COUNT("&cCancelled %s0 edits.", "Cancel"),
WORLDEDIT_CANCEL_REASON("&cYour WorldEdit action was cancelled:&7 %s0&c.", "Cancel"),
WORLDEDIT_CANCEL_REASON_MANUAL("Manual cancellation", "Cancel"),
@ -51,16 +118,15 @@ public enum BBC {
WORLDEDIT_CANCEL_REASON_MAX_FAILS("Outside allowed region", "Cancel"),
WORLDEDIT_FAILED_LOAD_CHUNK("&cSkipped loading chunk: &7%s0;%s1&c. Try increasing chunk-wait.", "Cancel"),
LOADING_CLIPBOARD("&dLoading clipboard from disk, please wait.", "History"),
INDEXING_HISTORY("&dIndexing %s history objects on disk, please wait.", "History"),
INDEXING_COMPLETE("&dIndexing complete. Took: %s seconds!", "History"),
LOADING_CLIPBOARD("Loading clipboard from disk, please wait.", "History"),
INDEXING_HISTORY("Indexing %s history objects on disk, please wait.", "History"),
INDEXING_COMPLETE("Indexing complete. Took: %s seconds!", "History"),
;
WORLDEDIT_OOM_ADMIN("&cPossible options:\n&8 - &7//fast\n&8 - &7Do smaller edits\n&8 - &7Allocate more memory\n&8 - &7Disable this safeguard", "Info"),
NOT_PLAYER("&cYou must be a player to perform this action!", "Error"),
COMPRESSED("History compressed. Saved ~ %s0b (%s1x smaller)", "Info"),
OOM(
"&8[&cCritical&8] &cDetected low memory i.e. < 1%. FAWE will take the following actions:\n&8 - &7Terminate WE block placement\n&8 - &7Clear WE history\n&8 - &7Unload non essential chunks\n&8 - &7Kill entities\n&8 - &7Garbage collect\n&cIgnore this if trying to crash server.\n&7Note: Low memory is likely (but not necessarily) caused by WE",
"Error");
private static final HashMap<String, String> replacements = new HashMap<>();
/**
@ -194,6 +260,19 @@ public enum BBC {
}
}
@Override
public String toString() {
return s();
}
public boolean isEmpty() {
return length() == 0;
}
public int length() {
return toString().length();
}
public static String color(String string) {
return StringMan.replaceFromMap(string, replacements);
}
@ -210,11 +289,25 @@ public enum BBC {
return this.cat;
}
public void send(final FawePlayer<?> player, final Object... args) {
if (player == null) {
Fawe.debug(this.format(args));
public void send(Actor actor, final Object... args) {
if (isEmpty()) {
return;
}
if (actor == null) {
Fawe.debug((PREFIX.isEmpty() ? "" : PREFIX.s() + " ") + this.format(args));
} else {
player.sendMessage(this.format(args));
actor.print((PREFIX.isEmpty() ? "" : PREFIX.s() + " ") + this.format(args));
}
}
public void send(final FawePlayer<?> player, final Object... args) {
if (isEmpty()) {
return;
}
if (player == null) {
Fawe.debug((PREFIX.isEmpty() ? "" : PREFIX.s() + " ") + this.format(args));
} else {
player.sendMessage((PREFIX.isEmpty() ? "" : PREFIX.s() + " ") + this.format(args));
}
}

View File

@ -77,7 +77,7 @@ public abstract class CharFaweChunk<T> extends FaweChunk<T> {
public int getTotalCount() {
int total = 0;
for (int i = 0; i < 16; i++) {
total += this.count[i];
total += Math.min(4096, this.count[i]);
}
return total;
}

View File

@ -120,7 +120,7 @@ public abstract class FawePlayer<T> {
}
} catch (EmptyClipboardException e) {}
if (player != null && session != null) {
sendMessage("&d" + BBC.PREFIX.s() + " " + BBC.LOADING_CLIPBOARD.s());
BBC.LOADING_CLIPBOARD.send(this);
WorldData worldData = player.getWorld().getWorldData();
Clipboard clip = doc.toClipboard();
ClipboardHolder holder = new ClipboardHolder(clip, worldData);
@ -162,7 +162,7 @@ public abstract class FawePlayer<T> {
}
}
if (editIds.size() > 0) {
sendMessage("&d" + BBC.PREFIX.s() + " " + BBC.INDEXING_HISTORY.format(editIds.size()));
BBC.INDEXING_HISTORY.send(this, editIds.size());
TaskManager.IMP.async(new Runnable() {
@Override
public void run() {
@ -177,7 +177,7 @@ public abstract class FawePlayer<T> {
return;
}
}
sendMessage("&d" + BBC.PREFIX.s() + " " + BBC.INDEXING_COMPLETE.format((System.currentTimeMillis() - start) / 1000d));
BBC.INDEXING_COMPLETE.send(FawePlayer.this, (System.currentTimeMillis() - start) / 1000d);
}
});
}

View File

@ -28,7 +28,14 @@ public class NullChangeSet implements FaweChangeSet {
}
@Override
public void flush() {}
public boolean flush() {
return false;
}
@Override
public int getCompressedSize() {
return 0;
}
@Override
public void add(Vector location, BaseBlock from, BaseBlock to) {}

View File

@ -0,0 +1,110 @@
package com.boydti.fawe.object.brush;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.brush.heightmap.ArrayHeightMap;
import com.boydti.fawe.object.brush.heightmap.HeightMap;
import com.boydti.fawe.object.exception.FaweException;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.awt.image.BufferedImage;
import java.awt.image.Raster;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class HeightBrush implements Brush {
public final HeightMap heightMap;
private final int rotation;
double yscale = 1;
public HeightBrush(File file, int rotation, double yscale) {
this.rotation = (rotation / 90) % 4;
this.yscale = yscale;
if (file == null || !file.exists()) {
heightMap = new HeightMap();
} else {
try {
BufferedImage heightFile = ImageIO.read(file);
int width = heightFile.getWidth();
int length = heightFile.getHeight();
Raster data = heightFile.getData();
byte[][] array = new byte[width][length];
for (int x = 0; x < width; x++) {
for (int z = 0; z < length; z++) {
int pixel = heightFile.getRGB(x, z);
int red = (pixel >> 16) & 0xFF;
int green = (pixel >> 8) & 0xFF;
int blue = (pixel >> 0) & 0xFF;
int intensity = (red + green + blue) / 3;
array[x][z] = (byte) intensity;
}
}
heightMap = new ArrayHeightMap(array);
} catch (IOException e) {
throw new FaweException(BBC.BRUSH_HEIGHT_INVALID);
}
}
}
@Override
public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
int size = (int) sizeDouble;
heightMap.setSize(size);
int size2 = size * size;
int startY = position.getBlockY() + size;
int endY = position.getBlockY() - size;
int cx = position.getBlockX();
int cz = position.getBlockZ();
Vector mutablePos = new Vector(0, 0, 0);
for (int x = -size; x <= size; x++) {
int xx = cx + x;
for (int z = -size; z <= size; z++) {
int zz = cz + z;
int raise;
switch (rotation) {
default:
raise = heightMap.getHeight(x, z);
break;
case 1:
raise = heightMap.getHeight(z, x);
break;
case 2:
raise = heightMap.getHeight(-x, -z);
break;
case 3:
raise = heightMap.getHeight(-z, -x);
break;
}
raise = (int) (yscale * raise);
if (raise == 0) {
continue;
}
int foundHeight = Integer.MAX_VALUE;
BaseBlock block = null;
for (int y = startY; y >= endY; y--) {
block = editSession.getLazyBlock(xx, y, zz);
if (block != EditSession.nullBlock) {
foundHeight = y;
break;
}
}
if (foundHeight == Integer.MAX_VALUE) {
continue;
}
for (int y = foundHeight + 1; y <= foundHeight + raise; y++) {
mutablePos.x = xx;
mutablePos.y = y;
mutablePos.z = zz;
editSession.setBlock(mutablePos, block);
}
}
}
}
}

View File

@ -0,0 +1,33 @@
package com.boydti.fawe.object.brush.heightmap;
public class ArrayHeightMap extends HeightMap {
// The heights
private final byte[][] height;
// The height map width/length
private final int width, length;
// The size to width/length ratio
private double rx,rz;
public ArrayHeightMap(byte[][] height) {
setSize(5);
this.height = height;
this.width = height.length;
this.length = height[0].length;
}
@Override
public void setSize(int size) {
super.setSize(size);
this.rx = (double) width / (size << 1);
this.rz = (double) width / (size << 1);
}
@Override
public int getHeight(int x, int z) {
x = (int) Math.max(0, Math.min(width - 1, (x + size) * rx));
z = (int) Math.max(0, Math.min(length - 1, (z + size) * rz));
return (((int) height[x][z] & 0xFF) * size) / 256;
}
}

View File

@ -0,0 +1,31 @@
package com.boydti.fawe.object.brush.heightmap;
import com.boydti.fawe.util.MathMan;
public class HeightMap {
public int size2;
public int size;
public HeightMap() {
setSize(5);
}
public HeightMap(int size) {
setSize(size);
}
public void setSize(int size) {
this.size = size;
this.size2 = size * size;
}
public int getHeight(int x, int z) {
int dx = Math.abs(x);
int dz = Math.abs(z);
int d2 = dx * dx + dz * dz;
if (d2 > size2) {
return 0;
}
return size - MathMan.sqrt(d2);
}
}

View File

@ -2,7 +2,6 @@ package com.boydti.fawe.object.changeset;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.IntegerPair;
import com.boydti.fawe.object.RegionWrapper;
@ -96,7 +95,7 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
private int ox;
private int oz;
private AtomicInteger size = new AtomicInteger();
private int size;
private World world;
public void deleteFiles() {
@ -108,7 +107,6 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
}
public DiskStorageHistory(World world, UUID uuid) {
size = new AtomicInteger();
String base = "history" + File.separator + world.getName() + File.separator + uuid;
File folder = new File(Fawe.imp().getDirectory(), base);
int max = 0;
@ -159,29 +157,32 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
@Override
public void add(Change change) {
size.incrementAndGet();
if ((change instanceof BlockChange)) {
add((BlockChange) change);
} else {
Fawe.debug(BBC.PREFIX.s() + "Does not support " + change + " yet! (Please bug Empire92)");
Fawe.debug("Does not support " + change + " yet! (Please bug Empire92)");
}
}
@Override
public void flush() {
public boolean flush() {
boolean flushed = false;
try {
if (osBD != null) {
flushed = true;
osBD.flush();
osBD.close();
osBD = null;
}
if (osNBTF != null) {
flushed = true;
osNBTFG.flush();
osNBTF.close();
osNBTF = null;
osNBTFG = null;
}
if (osNBTT != null) {
flushed = true;
osNBTTG.flush();
osNBTT.close();
osNBTT = null;
@ -190,10 +191,17 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
} catch (Exception e) {
e.printStackTrace();
}
return flushed;
}
@Override
public int getCompressedSize() {
return bdFile.exists() ? (int) bdFile.length() : 0;
}
@Override
public void add(int x, int y, int z, int combinedFrom, int combinedTo) {
size++;
try {
OutputStream stream = getBAOS(x, y, z);
//x
@ -548,7 +556,7 @@ public class DiskStorageHistory implements ChangeSet, FaweChangeSet {
@Override
public int size() {
flush();
return size.get();
return size;
}
public static class DiskStorageSummary {

View File

@ -5,7 +5,9 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.history.changeset.ChangeSet;
public interface FaweChangeSet extends ChangeSet {
void flush();
boolean flush();
int getCompressedSize();
void add(Vector location, BaseBlock from, BaseBlock to);

View File

@ -1,8 +1,6 @@
package com.boydti.fawe.object.changeset;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.ReflectionUtils;
@ -281,43 +279,26 @@ public class MemoryOptimizedHistory implements ChangeSet, FaweChangeSet {
}
@Override
public void flush() {
public boolean flush() {
if (idsStreamZip != null) {
try {
idsStream.flush();
idsStreamZip.flush();
idsStreamZip.close();
ids = idsStream.toByteArray();
/*
* BlockVector
* - reference to the object --> 8 bytes
* - object header (java internals) --> 8 bytes
* - double x, y, z --> 24 bytes
*
* BaseBlock
* - reference to the object --> 8 bytes
* - object header (java internals) --> 8 bytes
* - short id, data --> 4 bytes
* - NBTCompound (assuming null) --> 4 bytes
*
* There are usually two lists for the block changes:
* 2 * BlockVector + 2 * BaseBlock = 128b
*
* This compares FAWE's usage to standard WE.
*/
int total = 128 * size;
int current = ids.length + 16;
int ratio = total / current;
int saved = total - current;
if (ratio > 3 && Thread.currentThread() != Fawe.get().getMainThread() && actor != null && actor.isPlayer() && actor.getSessionKey().isActive() && BBC.COMPRESSED.s().length() > 0) {
actor.print(BBC.PREFIX.s() + " " + BBC.COMPRESSED.format(saved, ratio));
}
idsStream = null;
idsStreamZip = null;
} catch (IOException e) {
e.printStackTrace();
}
return true;
}
return false;
}
@Override
public int getCompressedSize() {
return ids == null ? 0 : ids.length;
}
}

View File

@ -94,7 +94,7 @@ public abstract class FaweQueue {
try {
return getCombinedId4Data(x, y, z);
} catch (FaweException ignore) {
session.debug(BBC.WORLDEDIT_FAILED_LOAD_CHUNK.format(x >> 4, z >> 4));
session.debug(BBC.WORLDEDIT_FAILED_LOAD_CHUNK, x >> 4, z >> 4);
return def;
}
}

View File

@ -5,10 +5,12 @@ import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.EndTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.extension.platform.Actor;
import java.io.File;
import java.lang.reflect.Array;
import java.util.Map;
@ -37,6 +39,44 @@ public class MainUtil {
Fawe.debug(s);
}
public static void sendCompressedMessage(FaweChangeSet set, Actor actor)
{
try {
int elements = set.size();
int compressedSize = set.getCompressedSize();
/*
* BlockVector
* - reference to the object --> 8 bytes
* - object header (java internals) --> 8 bytes
* - double x, y, z --> 24 bytes
*
* BaseBlock
* - reference to the object --> 8 bytes
* - object header (java internals) --> 8 bytes
* - short id, data --> 4 bytes
* - NBTCompound (assuming null) --> 4 bytes
*
* There are usually two lists for the block changes:
* 2 * BlockVector + 2 * BaseBlock = 128b
*
* WE has a lot more overhead, this is just a generous lower bound
*
* This compares FAWE's usage to standard WE.
*/
int total = 128 * elements;
int current = compressedSize;
int ratio = total / current;
int saved = total - current;
if (ratio > 3 && Thread.currentThread() != Fawe.get().getMainThread() && actor != null && actor.isPlayer() && actor.getSessionKey().isActive()) {
BBC.COMPRESSED.send(actor, saved, ratio);
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void warnDeprecated(Class... alternatives) {
StackTraceElement[] stack = new RuntimeException().getStackTrace();
if (stack.length > 1) {

View File

@ -21,6 +21,96 @@ public class MathMan {
}
}
private final static int[] table = {
0, 16, 22, 27, 32, 35, 39, 42, 45, 48, 50, 53, 55, 57,
59, 61, 64, 65, 67, 69, 71, 73, 75, 76, 78, 80, 81, 83,
84, 86, 87, 89, 90, 91, 93, 94, 96, 97, 98, 99, 101, 102,
103, 104, 106, 107, 108, 109, 110, 112, 113, 114, 115, 116, 117, 118,
119, 120, 121, 122, 123, 124, 125, 126, 128, 128, 129, 130, 131, 132,
133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144, 144, 145,
146, 147, 148, 149, 150, 150, 151, 152, 153, 154, 155, 155, 156, 157,
158, 159, 160, 160, 161, 162, 163, 163, 164, 165, 166, 167, 167, 168,
169, 170, 170, 171, 172, 173, 173, 174, 175, 176, 176, 177, 178, 178,
179, 180, 181, 181, 182, 183, 183, 184, 185, 185, 186, 187, 187, 188,
189, 189, 190, 191, 192, 192, 193, 193, 194, 195, 195, 196, 197, 197,
198, 199, 199, 200, 201, 201, 202, 203, 203, 204, 204, 205, 206, 206,
207, 208, 208, 209, 209, 210, 211, 211, 212, 212, 213, 214, 214, 215,
215, 216, 217, 217, 218, 218, 219, 219, 220, 221, 221, 222, 222, 223,
224, 224, 225, 225, 226, 226, 227, 227, 228, 229, 229, 230, 230, 231,
231, 232, 232, 233, 234, 234, 235, 235, 236, 236, 237, 237, 238, 238,
239, 240, 240, 241, 241, 242, 242, 243, 243, 244, 244, 245, 245, 246,
246, 247, 247, 248, 248, 249, 249, 250, 250, 251, 251, 252, 252, 253,
253, 254, 254, 255
};
public static int sqrt(int x) {
int xn;
if (x >= 0x10000) {
if (x >= 0x1000000) {
if (x >= 0x10000000) {
if (x >= 0x40000000) {
xn = table[x >> 24] << 8;
} else {
xn = table[x >> 22] << 7;
}
} else {
if (x >= 0x4000000) {
xn = table[x >> 20] << 6;
} else {
xn = table[x >> 18] << 5;
}
}
xn = (xn + 1 + (x / xn)) >> 1;
xn = (xn + 1 + (x / xn)) >> 1;
return ((xn * xn) > x) ? --xn : xn;
} else {
if (x >= 0x100000) {
if (x >= 0x400000) {
xn = table[x >> 16] << 4;
} else {
xn = table[x >> 14] << 3;
}
} else {
if (x >= 0x40000) {
xn = table[x >> 12] << 2;
} else {
xn = table[x >> 10] << 1;
}
}
xn = (xn + 1 + (x / xn)) >> 1;
return ((xn * xn) > x) ? --xn : xn;
}
} else {
if (x >= 0x100) {
if (x >= 0x1000) {
if (x >= 0x4000) {
xn = (table[x >> 8]) + 1;
} else {
xn = (table[x >> 6] >> 1) + 1;
}
} else {
if (x >= 0x400) {
xn = (table[x >> 4] >> 2) + 1;
} else {
xn = (table[x >> 2] >> 3) + 1;
}
}
return ((xn * xn) > x) ? --xn : xn;
} else {
if (x >= 0) {
return table[x] >> 4;
}
}
}
throw new IllegalArgumentException("Invalid number:" + x);
}
public static double getMean(int[] array) {
double count = 0;
for (int i : array) {

View File

@ -359,10 +359,8 @@ public class EditSession implements Extent {
return;
}
public void debug(String message) {
if (actor != null && message != null && message.length() > 0) {
actor.print(BBC.PREFIX.s() + " " + message);
}
public void debug(BBC message, Object... args) {
message.send(actor, args);
}
public FaweQueue getQueue() {

View File

@ -22,6 +22,7 @@ package com.sk89q.worldedit;
import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.clipboard.DiskOptimizedClipboard;
import com.boydti.fawe.util.FaweQueue;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.SetQueue;
import com.sk89q.jchronic.Chronic;
import com.sk89q.jchronic.Options;
@ -217,7 +218,11 @@ public class LocalSession {
}
ChangeSet set = editSession.getChangeSet();
if (set instanceof FaweChangeSet) {
((FaweChangeSet) set).flush();
FaweChangeSet fcs = (FaweChangeSet) set;
if (fcs.flush() && append) {
MainUtil.sendCompressedMessage(fcs, editSession.actor);
}
}
if (append) {
history.add(editSession);

View File

@ -19,9 +19,12 @@
package com.sk89q.worldedit.command;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.brush.HeightBrush;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
@ -51,6 +54,8 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.parametric.Optional;
import java.io.File;
import static com.google.common.base.Preconditions.checkNotNull;
@ -96,8 +101,7 @@ public class BrushCommands {
} else {
tool.setBrush(new SphereBrush(), "worldedit.brush.sphere");
}
player.print(String.format("Sphere brush shape equipped (%.0f).", radius));
BBC.BRUSH_SPHERE.send(player, radius);
}
@Command(
@ -126,8 +130,7 @@ public class BrushCommands {
} else {
tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder");
}
player.print(String.format("Cylinder brush shape equipped (%.0f by %d).", radius, height));
BBC.BRUSH_CYLINDER.send(player, radius, height);
}
@Command(
@ -154,8 +157,7 @@ public class BrushCommands {
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin), "worldedit.brush.clipboard");
player.print("Clipboard brush shape equipped.");
BBC.BRUSH_CLIPBOARD.send(player);
}
@Command(
@ -183,8 +185,7 @@ public class BrushCommands {
tool.setSize(radius);
tool.setBrush(new SmoothBrush(iterations, naturalBlocksOnly), "worldedit.brush.smooth");
player.print(String.format("Smooth brush equipped (%.0f x %dx, using " + (naturalBlocksOnly ? "natural blocks only" : "any block") + ").",
radius, iterations));
BBC.BRUSH_SMOOTH.send(player, radius, iterations, (naturalBlocksOnly ? "natural blocks only" : "any block"));
}
@Command(
@ -204,8 +205,7 @@ public class BrushCommands {
tool.setSize(radius);
tool.setMask(new BlockMask(editSession, new BaseBlock(BlockID.FIRE)));
tool.setBrush(new SphereBrush(), "worldedit.brush.ex");
player.print(String.format("Extinguisher equipped (%.0f).", radius));
BBC.BRUSH_EXTINGUISHER.send(player, radius);
}
@Command(
@ -227,9 +227,27 @@ public class BrushCommands {
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new GravityBrush(fromMaxY), "worldedit.brush.gravity");
BBC.BRUSH_GRAVITY.send(player, radius);
}
player.print(String.format("Gravity brush equipped (%.0f).",
radius));
@Command(
aliases = { "height", "high" },
usage = "[radius] [file] [rotation] [yscale]",
flags = "h",
desc = "Height brush",
help =
"This brush raises land.\n",
min = 0,
max = 4
)
@CommandPermissions("worldedit.brush.height")
public void heightBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
File file = new File(Fawe.imp().getDirectory(), "heightmap" + File.separator + (filename.endsWith(".png") ? filename : filename + ".png"));
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new HeightBrush(file, rotation, yscale), "worldedit.brush.height");
BBC.BRUSH_HEIGHT.send(player, radius);
}
@Command(
@ -274,8 +292,7 @@ public class BrushCommands {
BrushTool tool = session.getBrushTool(player.getItemInHand());
tool.setSize(radius);
tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher");
player.print(String.format("Butcher brush equipped (%.0f).", radius));
BBC.BRUSH_BUTCHER.send(player, radius);
}
public static Class<?> inject() {

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.command;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.RunnableVal2;
import com.boydti.fawe.object.clipboard.LazyClipboard;
import com.sk89q.minecraft.util.commands.Command;
@ -135,7 +136,7 @@ public class ClipboardCommands {
BlockArrayClipboard clipboard = new BlockArrayClipboard(region, lazyClipboard);
clipboard.setOrigin(session.getPlacementPosition(player));
session.setClipboard(new ClipboardHolder(clipboard, editSession.getWorld().getWorldData()));
player.print(region.getArea() + " block(s) were not copied. I'll do it later, promise!");
BBC.COMMAND_COPY.send(player, region.getArea());
}
@ -167,7 +168,7 @@ public class ClipboardCommands {
Operations.completeLegacy(copy);
session.setClipboard(new ClipboardHolder(clipboard, editSession.getWorld().getWorldData()));
player.print(region.getArea() + " block(s) were copied. Note: For faster copying use //lazycopy");
BBC.COMMAND_COPY.send(player, region.getArea());
}
@Command(
@ -199,7 +200,7 @@ public class ClipboardCommands {
Operations.completeLegacy(copy);
session.setClipboard(new ClipboardHolder(clipboard, editSession.getWorld().getWorldData()));
player.print(region.getArea() + " block(s) were copied.");
BBC.COMMAND_COPY.send(player, region.getArea());
}
@Command(
@ -244,8 +245,7 @@ public class ClipboardCommands {
selector.learnChanges();
selector.explainRegionAdjust(player, session);
}
player.print("The clipboard has been pasted at " + to);
BBC.COMMAND_PASTE.send(player, to);
}
@Command(
@ -332,7 +332,7 @@ public class ClipboardCommands {
selector.learnChanges();
selector.explainRegionAdjust(player, session);
}
player.print("The clipboard has been placed at " + to);
BBC.COMMAND_PASTE.send(player, to);
}
@Command(
@ -357,7 +357,7 @@ public class ClipboardCommands {
transform = transform.rotateX(-(xRotate != null ? xRotate : 0));
transform = transform.rotateZ(-(zRotate != null ? zRotate : 0));
holder.setTransform(holder.getTransform().combine(transform));
player.print("The clipboard copy has been rotated.");
BBC.COMMAND_ROTATE.send(player);
}
@Command(
@ -377,7 +377,7 @@ public class ClipboardCommands {
AffineTransform transform = new AffineTransform();
transform = transform.scale(direction.positive().multiply(-2).add(1, 1, 1));
holder.setTransform(holder.getTransform().combine(transform));
player.print("The clipboard copy has been flipped.");
BBC.COMMAND_FLIPPED.send(player);
}
@Command(
@ -416,7 +416,7 @@ public class ClipboardCommands {
@CommandPermissions("worldedit.clipboard.clear")
public void clearClipboard(Player player, LocalSession session, EditSession editSession) throws WorldEditException {
session.setClipboard(null);
player.print("Clipboard cleared.");
BBC.CLIPBOARD_CLEARED.send(player);
}
public static Class<?> inject() {
return ClipboardCommands.class;

View File

@ -0,0 +1,131 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command;
import com.boydti.fawe.config.BBC;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.*;
import com.sk89q.worldedit.entity.Player;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Commands to undo, redo, and clear history.
*/
public class HistoryCommands {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public HistoryCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command(
aliases = { "/undo", "undo" },
usage = "[times] [player]",
desc = "Undoes the last action",
min = 0,
max = 2
)
@CommandPermissions("worldedit.history.undo")
public void undo(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
int times = Math.max(1, args.getInteger(0, 1));
for (int i = 0; i < times; ++i) {
EditSession undone;
if (args.argsLength() < 2) {
undone = session.undo(session.getBlockBag(player), player);
} else {
player.checkPermission("worldedit.history.undo.other");
LocalSession sess = worldEdit.getSession(args.getString(1));
if (sess == null) {
player.printError("Unable to find session for " + args.getString(1));
break;
}
undone = sess.undo(session.getBlockBag(player), player);
}
if (undone != null) {
BBC.COMMAND_UNDO_SUCCESS.send(player);
worldEdit.flushBlockBag(player, undone);
} else {
BBC.COMMAND_UNDO_FAIL.send(player);
break;
}
}
}
@Command(
aliases = { "/redo", "redo" },
usage = "[times] [player]",
desc = "Redoes the last action (from history)",
min = 0,
max = 2
)
@CommandPermissions("worldedit.history.redo")
public void redo(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
int times = Math.max(1, args.getInteger(0, 1));
for (int i = 0; i < times; ++i) {
EditSession redone;
if (args.argsLength() < 2) {
redone = session.redo(session.getBlockBag(player), player);
} else {
player.checkPermission("worldedit.history.redo.other");
LocalSession sess = worldEdit.getSession(args.getString(1));
if (sess == null) {
player.printError("Unable to find session for " + args.getString(1));
break;
}
redone = sess.redo(session.getBlockBag(player), player);
}
if (redone != null) {
BBC.COMMAND_REDO_SUCCESS.send(player);
worldEdit.flushBlockBag(player, redone);
} else {
BBC.COMMAND_REDO_FAIL.send(player);
}
}
}
@Command(
aliases = { "/clearhistory", "clearhistory" },
usage = "",
desc = "Clear your history",
min = 0,
max = 0
)
@CommandPermissions("worldedit.history.clear")
public void clearHistory(Player player, LocalSession session, EditSession editSession) throws WorldEditException {
session.clearHistory();
BBC.COMMAND_HISTORY_CLEAR.send(player);
}
public static Class<?> inject() {
return HistoryCommands.class;
}
}

View File

@ -0,0 +1,483 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command;
import com.boydti.fawe.config.BBC;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.function.GroundFunction;
import com.sk89q.worldedit.function.generator.FloraGenerator;
import com.sk89q.worldedit.function.generator.ForestGenerator;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.NoiseFilter2D;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.pattern.Patterns;
import com.sk89q.worldedit.function.visitor.LayerVisitor;
import com.sk89q.worldedit.internal.annotation.Direction;
import com.sk89q.worldedit.internal.annotation.Selection;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.math.convolution.GaussianKernel;
import com.sk89q.worldedit.math.convolution.HeightMap;
import com.sk89q.worldedit.math.convolution.HeightMapFilter;
import com.sk89q.worldedit.math.noise.RandomNoise;
import com.sk89q.worldedit.regions.ConvexPolyhedralRegion;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.TreeGenerator.TreeType;
import com.sk89q.worldedit.util.command.binding.Range;
import com.sk89q.worldedit.util.command.binding.Switch;
import com.sk89q.worldedit.util.command.binding.Text;
import com.sk89q.worldedit.util.command.parametric.Optional;
import java.util.ArrayList;
import java.util.List;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.ALL;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.ORIENTATION_REGION;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
import static com.sk89q.worldedit.regions.Regions.asFlatRegion;
import static com.sk89q.worldedit.regions.Regions.maximumBlockY;
import static com.sk89q.worldedit.regions.Regions.minimumBlockY;
/**
* Commands that operate on regions.
*/
public class RegionCommands {
private final WorldEdit worldEdit;
/**
* Create a new instance.
*
* @param worldEdit reference to WorldEdit
*/
public RegionCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@Command(
aliases = { "/line" },
usage = "<block> [thickness]",
desc = "Draws a line segment between cuboid selection corners",
help =
"Draws a line segment between cuboid selection corners.\n" +
"Can only be used with cuboid selections.\n" +
"Flags:\n" +
" -h generates only a shell",
flags = "h",
min = 1,
max = 2
)
@CommandPermissions("worldedit.region.line")
@Logging(REGION)
public void line(Player player, EditSession editSession,
@Selection Region region,
Pattern pattern,
@Optional("0") @Range(min = 0) int thickness,
@Switch('h') boolean shell) throws WorldEditException {
if (!(region instanceof CuboidRegion)) {
player.printError("//line only works with cuboid selections");
return;
}
CuboidRegion cuboidregion = (CuboidRegion) region;
Vector pos1 = cuboidregion.getPos1();
Vector pos2 = cuboidregion.getPos2();
int blocksChanged = editSession.drawLine(Patterns.wrap(pattern), pos1, pos2, thickness, !shell);
BBC.VISITOR_BLOCK.send(player, blocksChanged);
}
@Command(
aliases = { "/curve" },
usage = "<block> [thickness]",
desc = "Draws a spline through selected points",
help =
"Draws a spline through selected points.\n" +
"Can only be used with convex polyhedral selections.\n" +
"Flags:\n" +
" -h generates only a shell",
flags = "h",
min = 1,
max = 2
)
@CommandPermissions("worldedit.region.curve")
@Logging(REGION)
public void curve(Player player, EditSession editSession,
@Selection Region region,
Pattern pattern,
@Optional("0") @Range(min = 0) int thickness,
@Switch('h') boolean shell) throws WorldEditException {
if (!(region instanceof ConvexPolyhedralRegion)) {
player.printError("//line only works with convex polyhedral selections");
return;
}
ConvexPolyhedralRegion cpregion = (ConvexPolyhedralRegion) region;
List<Vector> vectors = new ArrayList<Vector>(cpregion.getVertices());
int blocksChanged = editSession.drawSpline(Patterns.wrap(pattern), vectors, 0, 0, 0, 10, thickness, !shell);
BBC.VISITOR_BLOCK.send(player, blocksChanged);
}
@Command(
aliases = { "/replace", "/re", "/rep" },
usage = "[from-block] <to-block>",
desc = "Replace all blocks in the selection with another",
flags = "f",
min = 1,
max = 2
)
@CommandPermissions("worldedit.region.replace")
@Logging(REGION)
public void replace(Player player, EditSession editSession, @Selection Region region, @Optional Mask from, Pattern to) throws WorldEditException {
if (from == null) {
from = new ExistingBlockMask(editSession);
}
int affected = editSession.replaceBlocks(region, from, Patterns.wrap(to));
BBC.VISITOR_BLOCK.send(player, affected);
}
@Command(
aliases = { "/overlay" },
usage = "<block>",
desc = "Set a block on top of blocks in the region",
min = 1,
max = 1
)
@CommandPermissions("worldedit.region.overlay")
@Logging(REGION)
public void overlay(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
int affected = editSession.overlayCuboidBlocks(region, Patterns.wrap(pattern));
BBC.VISITOR_BLOCK.send(player, affected);
}
@Command(
aliases = { "/center", "/middle" },
usage = "<block>",
desc = "Set the center block(s)",
min = 1,
max = 1
)
@Logging(REGION)
@CommandPermissions("worldedit.region.center")
public void center(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
int affected = editSession.center(region, Patterns.wrap(pattern));
BBC.VISITOR_BLOCK.send(player, affected);
}
@Command(
aliases = { "/naturalize" },
usage = "",
desc = "3 layers of dirt on top then rock below",
min = 0,
max = 0
)
@CommandPermissions("worldedit.region.naturalize")
@Logging(REGION)
public void naturalize(Player player, EditSession editSession, @Selection Region region) throws WorldEditException {
int affected = editSession.naturalizeCuboidBlocks(region);
BBC.VISITOR_BLOCK.send(player, affected);
}
@Command(
aliases = { "/walls" },
usage = "<block>",
desc = "Build the four sides of the selection",
min = 1,
max = 1
)
@CommandPermissions("worldedit.region.walls")
@Logging(REGION)
public void walls(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
int affected = editSession.makeCuboidWalls(region, Patterns.wrap(pattern));
BBC.VISITOR_BLOCK.send(player, affected);
}
@Command(
aliases = { "/faces", "/outline" },
usage = "<block>",
desc = "Build the walls, ceiling, and floor of a selection",
min = 1,
max = 1
)
@CommandPermissions("worldedit.region.faces")
@Logging(REGION)
public void faces(Player player, EditSession editSession, @Selection Region region, Pattern pattern) throws WorldEditException {
int affected = editSession.makeCuboidFaces(region, Patterns.wrap(pattern));
BBC.VISITOR_BLOCK.send(player, affected);
}
@Command(
aliases = { "/smooth" },
usage = "[iterations]",
flags = "n",
desc = "Smooth the elevation in the selection",
help =
"Smooths the elevation in the selection.\n" +
"The -n flag makes it only consider naturally occuring blocks.",
min = 0,
max = 1
)
@CommandPermissions("worldedit.region.smooth")
@Logging(REGION)
public void smooth(Player player, EditSession editSession, @Selection Region region, @Optional("1") int iterations, @Switch('n') boolean affectNatural) throws WorldEditException {
HeightMap heightMap = new HeightMap(editSession, region, affectNatural);
HeightMapFilter filter = new HeightMapFilter(new GaussianKernel(5, 1.0));
int affected = heightMap.applyFilter(filter, iterations);
BBC.VISITOR_BLOCK.send(player, affected);
}
@Command(
aliases = { "/move" },
usage = "[count] [direction] [leave-id]",
flags = "s",
desc = "Move the contents of the selection",
help =
"Moves the contents of the selection.\n" +
"The -s flag shifts the selection to the target location.\n" +
"Optionally fills the old location with <leave-id>.",
min = 0,
max = 3
)
@CommandPermissions("worldedit.region.move")
@Logging(ORIENTATION_REGION)
public void move(Player player, EditSession editSession, LocalSession session,
@Selection Region region,
@Optional("1") @Range(min = 1) int count,
@Optional(Direction.AIM) @Direction Vector direction,
@Optional("air") BaseBlock replace,
@Switch('s') boolean moveSelection) throws WorldEditException {
int affected = editSession.moveRegion(region, direction, count, true, replace);
if (moveSelection) {
try {
region.shift(direction.multiply(count));
session.getRegionSelector(player.getWorld()).learnChanges();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
} catch (RegionOperationException e) {
player.printError(e.getMessage());
}
}
BBC.VISITOR_BLOCK.send(player, affected);
}
@Command(
aliases = { "/stack" },
usage = "[count] [direction]",
flags = "sa",
desc = "Repeat the contents of the selection",
help =
"Repeats the contents of the selection.\n" +
"Flags:\n" +
" -s shifts the selection to the last stacked copy\n" +
" -a skips air blocks",
min = 0,
max = 2
)
@CommandPermissions("worldedit.region.stack")
@Logging(ORIENTATION_REGION)
public void stack(Player player, EditSession editSession, LocalSession session,
@Selection Region region,
@Optional("1") @Range(min = 1) int count,
@Optional(Direction.AIM) @Direction Vector direction,
@Switch('s') boolean moveSelection,
@Switch('a') boolean ignoreAirBlocks) throws WorldEditException {
int affected = editSession.stackCuboidRegion(region, direction, count, !ignoreAirBlocks);
if (moveSelection) {
try {
final Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint());
final Vector shiftVector = direction.multiply(count * (Math.abs(direction.dot(size)) + 1));
region.shift(shiftVector);
session.getRegionSelector(player.getWorld()).learnChanges();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
} catch (RegionOperationException e) {
player.printError(e.getMessage());
}
}
BBC.VISITOR_BLOCK.send(player, affected);
}
@Command(
aliases = { "/regen" },
usage = "",
desc = "Regenerates the contents of the selection",
help =
"Regenerates the contents of the current selection.\n" +
"This command might affect things outside the selection,\n" +
"if they are within the same chunk.",
min = 0,
max = 0
)
@CommandPermissions("worldedit.regen")
@Logging(REGION)
public void regenerateChunk(Player player, LocalSession session, EditSession editSession, @Selection Region region) throws WorldEditException {
Mask mask = session.getMask();
try {
session.setMask((Mask) null);
player.getWorld().regenerate(region, editSession);
} finally {
session.setMask(mask);
}
BBC.COMMAND_REGEN.send(player);
}
@Command(
aliases = { "/deform" },
usage = "<expression>",
desc = "Deforms a selected region with an expression",
help =
"Deforms a selected region with an expression\n" +
"The expression is executed for each block and is expected\n" +
"to modify the variables x, y and z to point to a new block\n" +
"to fetch. See also tinyurl.com/wesyntax.",
flags = "ro",
min = 1,
max = -1
)
@CommandPermissions("worldedit.region.deform")
@Logging(ALL)
public void deform(Player player, LocalSession session, EditSession editSession,
@Selection Region region,
@Text String expression,
@Switch('r') boolean useRawCoords,
@Switch('o') boolean offset) throws WorldEditException {
final Vector zero;
Vector unit;
if (useRawCoords) {
zero = Vector.ZERO;
unit = Vector.ONE;
} else if (offset) {
zero = session.getPlacementPosition(player);
unit = Vector.ONE;
} else {
final Vector min = region.getMinimumPoint();
final Vector max = region.getMaximumPoint();
zero = max.add(min).multiply(0.5);
unit = max.subtract(zero);
if (unit.getX() == 0) unit = unit.setX(1.0);
if (unit.getY() == 0) unit = unit.setY(1.0);
if (unit.getZ() == 0) unit = unit.setZ(1.0);
}
try {
final int affected = editSession.deformRegion(region, zero, unit, expression);
player.findFreePosition();
BBC.VISITOR_BLOCK.send(player, affected);
} catch (ExpressionException e) {
player.printError(e.getMessage());
}
}
@Command(
aliases = { "/hollow" },
usage = "[<thickness>[ <block>]]",
desc = "Hollows out the object contained in this selection",
help =
"Hollows out the object contained in this selection.\n" +
"Optionally fills the hollowed out part with the given block.\n" +
"Thickness is measured in manhattan distance.",
min = 0,
max = 2
)
@CommandPermissions("worldedit.region.hollow")
@Logging(REGION)
public void hollow(Player player, EditSession editSession,
@Selection Region region,
@Optional("0") @Range(min = 0) int thickness,
@Optional("air") Pattern pattern) throws WorldEditException {
int affected = editSession.hollowOutRegion(region, thickness, Patterns.wrap(pattern));
BBC.VISITOR_BLOCK.send(player, affected);
}
@Command(
aliases = { "/forest" },
usage = "[type] [density]",
desc = "Make a forest within the region",
min = 0,
max = 2
)
@CommandPermissions("worldedit.region.forest")
@Logging(REGION)
public void forest(Player player, EditSession editSession, @Selection Region region, @Optional("tree") TreeType type,
@Optional("5") @Range(min = 0, max = 100) double density) throws WorldEditException {
density = density / 100;
ForestGenerator generator = new ForestGenerator(editSession, new TreeGenerator(type));
GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator);
LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
Operations.completeLegacy(visitor);
BBC.COMMAND_TREE.send(player, ground.getAffected());
}
@Command(
aliases = { "/flora" },
usage = "[density]",
desc = "Make flora within the region",
min = 0,
max = 1
)
@CommandPermissions("worldedit.region.flora")
@Logging(REGION)
public void flora(Player player, EditSession editSession, @Selection Region region, @Optional("10") @Range(min = 0, max = 100) double density) throws WorldEditException {
density = density / 100;
FloraGenerator generator = new FloraGenerator(editSession);
GroundFunction ground = new GroundFunction(new ExistingBlockMask(editSession), generator);
LayerVisitor visitor = new LayerVisitor(asFlatRegion(region), minimumBlockY(region), maximumBlockY(region), ground);
visitor.setMask(new NoiseFilter2D(new RandomNoise(), density));
Operations.completeLegacy(visitor);
BBC.COMMAND_FLORA.send(player, ground.getAffected());
}
public static Class<?> inject() {
return RegionCommands.class;
}
}

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.command;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.util.SetQueue;
import com.boydti.fawe.util.TaskManager;
import com.sk89q.minecraft.util.commands.Command;
@ -119,7 +120,7 @@ public class SchematicCommands {
}
session.setClipboard(new ClipboardHolder(clipboard, worldData));
log.info(player.getName() + " loaded " + filePath);
player.print(filename + " loaded. Paste it with //paste");
BBC.SCHEMATIC_LOADED.send(player, filename);
}
} catch (final IOException e) {
player.printError("Schematic could not read or it does not exist: " + e.getMessage());
@ -183,7 +184,7 @@ public class SchematicCommands {
final ClipboardWriter writer = closer.register(format.getWriter(bos));
writer.write(target, holder.getWorldData());
log.info(player.getName() + " saved " + f.getCanonicalPath());
player.print(filename + " saved.");
BBC.SCHEMATIC_SAVED.send(player, filename);
} catch (final IOException e) {
player.printError("Schematic could not written: " + e.getMessage());
log.log(Level.WARNING, "Failed to write a saved clipboard", e);
@ -219,7 +220,7 @@ public class SchematicCommands {
return;
}
player.print(filename + " has been deleted.");
BBC.SCHEMATIC_DELETE.send(player, filename);
}
});
}
@ -227,7 +228,7 @@ public class SchematicCommands {
@Command(aliases = { "formats", "listformats", "f" }, desc = "List available formats", max = 0)
@CommandPermissions("worldedit.schematic.formats")
public void formats(final Actor actor) throws WorldEditException {
actor.print("Available clipboard formats (Name: Lookup names)");
BBC.SCHEMATIC_FORMAT.send(actor);
StringBuilder builder;
boolean first = true;
for (final ClipboardFormat format : ClipboardFormat.values()) {
@ -284,8 +285,7 @@ public class SchematicCommands {
return result;
}
});
actor.print("Available schematics (Filename (Format)):");
BBC.SCHEMATIC_LIST.send(actor);
actor.print(this.listFiles("", files));
}

View File

@ -0,0 +1,795 @@
/*
* WorldEdit, a Minecraft world manipulation toolkit
* Copyright (C) sk89q <http://www.sk89q.com>
* Copyright (C) WorldEdit team and contributors
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sk89q.worldedit.command;
import com.boydti.fawe.config.BBC;
import com.google.common.base.Optional;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.Logging;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.platform.permission.ActorSelectorLimits;
import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionOperationException;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.ConvexPolyhedralRegionSelector;
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
import com.sk89q.worldedit.regions.selector.CylinderRegionSelector;
import com.sk89q.worldedit.regions.selector.EllipsoidRegionSelector;
import com.sk89q.worldedit.regions.selector.ExtendingCuboidRegionSelector;
import com.sk89q.worldedit.regions.selector.Polygonal2DRegionSelector;
import com.sk89q.worldedit.regions.selector.RegionSelectorType;
import com.sk89q.worldedit.regions.selector.SphereRegionSelector;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.util.Countable;
import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
import com.sk89q.worldedit.util.formatting.Style;
import com.sk89q.worldedit.util.formatting.StyledFragment;
import com.sk89q.worldedit.util.formatting.component.CommandListBox;
import com.sk89q.worldedit.world.World;
import com.sk89q.worldedit.world.storage.ChunkStore;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.POSITION;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
/**
* Selection commands.
*/
public class SelectionCommands {
private final WorldEdit we;
public SelectionCommands(WorldEdit we) {
this.we = we;
}
@Command(
aliases = { "/pos1" },
usage = "[coordinates]",
desc = "Set position 1",
min = 0,
max = 1
)
@Logging(POSITION)
@CommandPermissions("worldedit.selection.pos")
public void pos1(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
Vector pos;
if (args.argsLength() == 1) {
if (args.getString(0).matches("-?\\d+,-?\\d+,-?\\d+")) {
String[] coords = args.getString(0).split(",");
pos = new Vector(Integer.parseInt(coords[0]), Integer.parseInt(coords[1]), Integer.parseInt(coords[2]));
} else {
player.printError("Invalid coordinates " + args.getString(0));
return;
}
} else {
pos = player.getBlockIn();
}
if (!session.getRegionSelector(player.getWorld()).selectPrimary(pos, ActorSelectorLimits.forActor(player))) {
player.printError("Position already set.");
return;
}
session.getRegionSelector(player.getWorld())
.explainPrimarySelection(player, session, pos);
}
@Command(
aliases = { "/pos2" },
usage = "[coordinates]",
desc = "Set position 2",
min = 0,
max = 1
)
@Logging(POSITION)
@CommandPermissions("worldedit.selection.pos")
public void pos2(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
Vector pos;
if (args.argsLength() == 1) {
if (args.getString(0).matches("-?\\d+,-?\\d+,-?\\d+")) {
String[] coords = args.getString(0).split(",");
pos = new Vector(Integer.parseInt(coords[0]),
Integer.parseInt(coords[1]),
Integer.parseInt(coords[2]));
} else {
player.printError("Invalid coordinates " + args.getString(0));
return;
}
} else {
pos = player.getBlockIn();
}
if (!session.getRegionSelector(player.getWorld()).selectSecondary(pos, ActorSelectorLimits.forActor(player))) {
player.printError("Position already set.");
return;
}
session.getRegionSelector(player.getWorld())
.explainSecondarySelection(player, session, pos);
}
@Command(
aliases = { "/hpos1" },
usage = "",
desc = "Set position 1 to targeted block",
min = 0,
max = 0
)
@CommandPermissions("worldedit.selection.hpos")
public void hpos1(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
Vector pos = player.getBlockTrace(300);
if (pos != null) {
if (!session.getRegionSelector(player.getWorld()).selectPrimary(pos, ActorSelectorLimits.forActor(player))) {
player.printError("Position already set.");
return;
}
session.getRegionSelector(player.getWorld())
.explainPrimarySelection(player, session, pos);
} else {
player.printError("No block in sight!");
}
}
@Command(
aliases = { "/hpos2" },
usage = "",
desc = "Set position 2 to targeted block",
min = 0,
max = 0
)
@CommandPermissions("worldedit.selection.hpos")
public void hpos2(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
Vector pos = player.getBlockTrace(300);
if (pos != null) {
if (!session.getRegionSelector(player.getWorld()).selectSecondary(pos, ActorSelectorLimits.forActor(player))) {
player.printError("Position already set.");
return;
}
session.getRegionSelector(player.getWorld())
.explainSecondarySelection(player, session, pos);
} else {
player.printError("No block in sight!");
}
}
@Command(
aliases = { "/chunk" },
usage = "[x,z coordinates]",
flags = "sc",
desc = "Set the selection to your current chunk.",
help =
"Set the selection to the chunk you are currently in.\n" +
"With the -s flag, your current selection is expanded\n" +
"to encompass all chunks that are part of it.\n\n" +
"Specifying coordinates will use those instead of your\n"+
"current position. Use -c to specify chunk coordinates,\n" +
"otherwise full coordinates will be implied.\n" +
"(for example, the coordinates 5,5 are the same as -c 0,0)",
min = 0,
max = 1
)
@Logging(POSITION)
@CommandPermissions("worldedit.selection.chunk")
public void chunk(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
final Vector min;
final Vector max;
final World world = player.getWorld();
if (args.hasFlag('s')) {
Region region = session.getSelection(world);
final Vector2D min2D = ChunkStore.toChunk(region.getMinimumPoint());
final Vector2D max2D = ChunkStore.toChunk(region.getMaximumPoint());
min = new Vector(min2D.getBlockX() * 16, 0, min2D.getBlockZ() * 16);
max = new Vector(max2D.getBlockX() * 16 + 15, world.getMaxY(), max2D.getBlockZ() * 16 + 15);
BBC.SELECTION_CHUNKS.send(player, min2D.getBlockX() + ", " + min2D.getBlockZ(), max2D.getBlockX() + ", " + max2D.getBlockZ());
} else {
final Vector2D min2D;
if (args.argsLength() == 1) {
// coords specified
String[] coords = args.getString(0).split(",");
if (coords.length != 2) {
throw new InsufficientArgumentsException("Invalid coordinates specified.");
}
int x = Integer.parseInt(coords[0]);
int z = Integer.parseInt(coords[1]);
Vector2D pos = new Vector2D(x, z);
min2D = (args.hasFlag('c')) ? pos : ChunkStore.toChunk(pos.toVector());
} else {
// use player loc
min2D = ChunkStore.toChunk(player.getBlockIn());
}
min = new Vector(min2D.getBlockX() * 16, 0, min2D.getBlockZ() * 16);
max = min.add(15, world.getMaxY(), 15);
BBC.SELECTION_CHUNK.send(player, min2D.getBlockX() + ", " + min2D.getBlockZ());
}
final CuboidRegionSelector selector;
if (session.getRegionSelector(world) instanceof ExtendingCuboidRegionSelector) {
selector = new ExtendingCuboidRegionSelector(world);
} else {
selector = new CuboidRegionSelector(world);
}
selector.selectPrimary(min, ActorSelectorLimits.forActor(player));
selector.selectSecondary(max, ActorSelectorLimits.forActor(player));
session.setRegionSelector(world, selector);
session.dispatchCUISelection(player);
}
@Command(
aliases = { "/wand" },
usage = "",
desc = "Get the wand object",
min = 0,
max = 0
)
@CommandPermissions("worldedit.wand")
public void wand(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
player.giveItem(we.getConfiguration().wandItem, 1);
BBC.SELECTION_WAND.send(player);
}
@Command(
aliases = { "toggleeditwand" },
usage = "",
desc = "Toggle functionality of the edit wand",
min = 0,
max = 0
)
@CommandPermissions("worldedit.wand.toggle")
public void toggleWand(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
session.setToolControl(!session.isToolControlEnabled());
if (session.isToolControlEnabled()) {
BBC.SELECTION_WAND_ENABLE.send(player);
} else {
BBC.SELECTION_WAND_DISABLE.send(player);
}
}
@Command(
aliases = { "/expand" },
usage = "<amount> [reverse-amount] <direction>",
desc = "Expand the selection area",
min = 1,
max = 3
)
@Logging(REGION)
@CommandPermissions("worldedit.selection.expand")
public void expand(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
// Special syntax (//expand vert) to expand the selection between
// sky and bedrock.
if (args.getString(0).equalsIgnoreCase("vert")
|| args.getString(0).equalsIgnoreCase("vertical")) {
Region region = session.getSelection(player.getWorld());
try {
int oldSize = region.getArea();
region.expand(
new Vector(0, (player.getWorld().getMaxY() + 1), 0),
new Vector(0, -(player.getWorld().getMaxY() + 1), 0));
session.getRegionSelector(player.getWorld()).learnChanges();
int newSize = region.getArea();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
BBC.SELECTION_EXPAND_VERT.send(player, (newSize - oldSize));
} catch (RegionOperationException e) {
player.printError(e.getMessage());
}
return;
}
List<Vector> dirs = new ArrayList<Vector>();
int change = args.getInteger(0);
int reverseChange = 0;
switch (args.argsLength()) {
case 2:
// Either a reverse amount or a direction
try {
reverseChange = args.getInteger(1);
dirs.add(we.getDirection(player, "me"));
} catch (NumberFormatException e) {
if (args.getString(1).contains(",")) {
String[] split = args.getString(1).split(",");
for (String s : split) {
dirs.add(we.getDirection(player, s.toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
}
}
break;
case 3:
// Both reverse amount and direction
reverseChange = args.getInteger(1);
if (args.getString(2).contains(",")) {
String[] split = args.getString(2).split(",");
for (String s : split) {
dirs.add(we.getDirection(player, s.toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, args.getString(2).toLowerCase()));
}
break;
default:
dirs.add(we.getDirection(player, "me"));
break;
}
Region region = session.getSelection(player.getWorld());
int oldSize = region.getArea();
if (reverseChange == 0) {
for (Vector dir : dirs) {
region.expand(dir.multiply(change));
}
} else {
for (Vector dir : dirs) {
region.expand(dir.multiply(change), dir.multiply(-reverseChange));
}
}
session.getRegionSelector(player.getWorld()).learnChanges();
int newSize = region.getArea();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
BBC.SELECTION_EXPAND.send(player, (newSize - oldSize));
}
@Command(
aliases = { "/contract" },
usage = "<amount> [reverse-amount] [direction]",
desc = "Contract the selection area",
min = 1,
max = 3
)
@Logging(REGION)
@CommandPermissions("worldedit.selection.contract")
public void contract(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
List<Vector> dirs = new ArrayList<Vector>();
int change = args.getInteger(0);
int reverseChange = 0;
switch (args.argsLength()) {
case 2:
// Either a reverse amount or a direction
try {
reverseChange = args.getInteger(1);
dirs.add(we.getDirection(player, "me"));
} catch (NumberFormatException e) {
if (args.getString(1).contains(",")) {
String[] split = args.getString(1).split(",");
for (String s : split) {
dirs.add(we.getDirection(player, s.toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
}
}
break;
case 3:
// Both reverse amount and direction
reverseChange = args.getInteger(1);
if (args.getString(2).contains(",")) {
String[] split = args.getString(2).split(",");
for (String s : split) {
dirs.add(we.getDirection(player, s.toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, args.getString(2).toLowerCase()));
}
break;
default:
dirs.add(we.getDirection(player, "me"));
break;
}
try {
Region region = session.getSelection(player.getWorld());
int oldSize = region.getArea();
if (reverseChange == 0) {
for (Vector dir : dirs) {
region.contract(dir.multiply(change));
}
} else {
for (Vector dir : dirs) {
region.contract(dir.multiply(change), dir.multiply(-reverseChange));
}
}
session.getRegionSelector(player.getWorld()).learnChanges();
int newSize = region.getArea();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
BBC.SELECTION_CONTRACT.send(player, (oldSize - newSize));
} catch (RegionOperationException e) {
player.printError(e.getMessage());
}
}
@Command(
aliases = { "/shift" },
usage = "<amount> [direction]",
desc = "Shift the selection area",
min = 1,
max = 2
)
@Logging(REGION)
@CommandPermissions("worldedit.selection.shift")
public void shift(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
List<Vector> dirs = new ArrayList<Vector>();
int change = args.getInteger(0);
if (args.argsLength() == 2) {
if (args.getString(1).contains(",")) {
for (String s : args.getString(1).split(",")) {
dirs.add(we.getDirection(player, s.toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, args.getString(1).toLowerCase()));
}
} else {
dirs.add(we.getDirection(player, "me"));
}
try {
Region region = session.getSelection(player.getWorld());
for (Vector dir : dirs) {
region.shift(dir.multiply(change));
}
session.getRegionSelector(player.getWorld()).learnChanges();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
BBC.SELECTION_SHIFT.send(player);
} catch (RegionOperationException e) {
player.printError(e.getMessage());
}
}
@Command(
aliases = { "/outset" },
usage = "<amount>",
desc = "Outset the selection area",
help =
"Expands the selection by the given amount in all directions.\n" +
"Flags:\n" +
" -h only expand horizontally\n" +
" -v only expand vertically\n",
flags = "hv",
min = 1,
max = 1
)
@Logging(REGION)
@CommandPermissions("worldedit.selection.outset")
public void outset(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
Region region = session.getSelection(player.getWorld());
region.expand(getChangesForEachDir(args));
session.getRegionSelector(player.getWorld()).learnChanges();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
BBC.SELECTION_OUTSET.send(player);
}
@Command(
aliases = { "/inset" },
usage = "<amount>",
desc = "Inset the selection area",
help =
"Contracts the selection by the given amount in all directions.\n" +
"Flags:\n" +
" -h only contract horizontally\n" +
" -v only contract vertically\n",
flags = "hv",
min = 1,
max = 1
)
@Logging(REGION)
@CommandPermissions("worldedit.selection.inset")
public void inset(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
Region region = session.getSelection(player.getWorld());
region.contract(getChangesForEachDir(args));
session.getRegionSelector(player.getWorld()).learnChanges();
session.getRegionSelector(player.getWorld()).explainRegionAdjust(player, session);
BBC.SELECTION_INSET.send(player);
}
private Vector[] getChangesForEachDir(CommandContext args) {
List<Vector> changes = new ArrayList<Vector>(6);
int change = args.getInteger(0);
if (!args.hasFlag('h')) {
changes.add((new Vector(0, 1, 0)).multiply(change));
changes.add((new Vector(0, -1, 0)).multiply(change));
}
if (!args.hasFlag('v')) {
changes.add((new Vector(1, 0, 0)).multiply(change));
changes.add((new Vector(-1, 0, 0)).multiply(change));
changes.add((new Vector(0, 0, 1)).multiply(change));
changes.add((new Vector(0, 0, -1)).multiply(change));
}
return changes.toArray(new Vector[0]);
}
@Command(
aliases = { "/size" },
flags = "c",
usage = "",
desc = "Get information about the selection",
min = 0,
max = 0
)
@CommandPermissions("worldedit.selection.size")
public void size(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
if (args.hasFlag('c')) {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
Region region = clipboard.getRegion();
Vector size = region.getMaximumPoint().subtract(region.getMinimumPoint());
Vector origin = clipboard.getOrigin();
player.print("Cuboid dimensions (max - min): " + size);
player.print("Offset: " + origin);
player.print("Cuboid distance: " + size.distance(Vector.ONE));
player.print("# of blocks: " + (int) (size.getX() * size.getY() * size.getZ()));
return;
}
Region region = session.getSelection(player.getWorld());
Vector size = region.getMaximumPoint()
.subtract(region.getMinimumPoint())
.add(1, 1, 1);
player.print("Type: " + session.getRegionSelector(player.getWorld())
.getTypeName());
for (String line : session.getRegionSelector(player.getWorld())
.getInformationLines()) {
player.print(line);
}
player.print("Size: " + size);
player.print("Cuboid distance: " + region.getMaximumPoint().distance(region.getMinimumPoint()));
player.print("# of blocks: " + region.getArea());
}
@Command(
aliases = { "/count" },
usage = "<block>",
desc = "Counts the number of a certain type of block",
flags = "d",
min = 1,
max = 1
)
@CommandPermissions("worldedit.analysis.count")
public void count(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
boolean useData = args.hasFlag('d');
if (args.getString(0).contains(":")) {
useData = true; //override d flag, if they specified data they want it
}
int count;
if (useData) {
Set<BaseBlock> searchBlocks = we.getBlocks(player, args.getString(0), true);
count = editSession.countBlocks(session.getSelection(player.getWorld()), searchBlocks);
} else {
Set<Integer> searchIDs = we.getBlockIDs(player, args.getString(0), true);
count = editSession.countBlock(session.getSelection(player.getWorld()), searchIDs);
}
BBC.SELECTION_COUNT.send(player, count);
}
@Command(
aliases = { "/distr" },
usage = "",
desc = "Get the distribution of blocks in the selection",
help =
"Gets the distribution of blocks in the selection.\n" +
"The -c flag gets the distribution of your clipboard.\n" +
"The -d flag separates blocks by data",
flags = "cd",
min = 0,
max = 0
)
@CommandPermissions("worldedit.analysis.distr")
public void distr(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException, CommandException {
int size;
boolean useData = args.hasFlag('d');
List<Countable<Integer>> distribution = null;
List<Countable<BaseBlock>> distributionData = null;
if (args.hasFlag('c')) {
// TODO: Update for new clipboard
throw new CommandException("Needs to be re-written again");
} else {
if (useData) {
distributionData = editSession.getBlockDistributionWithData(session.getSelection(player.getWorld()));
} else {
distribution = editSession.getBlockDistribution(session.getSelection(player.getWorld()));
}
size = session.getSelection(player.getWorld()).getArea();
}
if ((useData && distributionData.size() <= 0)
|| (!useData && distribution.size() <= 0)) { // *Should* always be false
player.printError("No blocks counted.");
return;
}
BBC.SELECTION_DISTR.send(player, size);
if (useData) {
for (Countable<BaseBlock> c : distributionData) {
String name = BlockType.fromID(c.getID().getId()).getName();
String str = String.format("%-7s (%.3f%%) %s #%d:%d",
String.valueOf(c.getAmount()),
c.getAmount() / (double) size * 100,
name == null ? "Unknown" : name,
c.getID().getType(), c.getID().getData());
player.print(str);
}
} else {
for (Countable<Integer> c : distribution) {
BlockType block = BlockType.fromID(c.getID());
String str = String.format("%-7s (%.3f%%) %s #%d",
String.valueOf(c.getAmount()),
c.getAmount() / (double) size * 100,
block == null ? "Unknown" : block.getName(), c.getID());
player.print(str);
}
}
}
@Command(
aliases = { "/sel", ";", "/desel", "/deselect" },
flags = "d",
usage = "[cuboid|extend|poly|ellipsoid|sphere|cyl|convex]",
desc = "Choose a region selector",
min = 0,
max = 1
)
public void select(Player player, LocalSession session, EditSession editSession, CommandContext args) throws WorldEditException {
final World world = player.getWorld();
if (args.argsLength() == 0) {
session.getRegionSelector(world).clear();
session.dispatchCUISelection(player);
BBC.SELECTION_CLEARED.send(player);
return;
}
final String typeName = args.getString(0);
final RegionSelector oldSelector = session.getRegionSelector(world);
final RegionSelector selector;
if (typeName.equalsIgnoreCase("cuboid")) {
selector = new CuboidRegionSelector(oldSelector);
player.print("Cuboid: left click for point 1, right click for point 2");
} else if (typeName.equalsIgnoreCase("extend")) {
selector = new ExtendingCuboidRegionSelector(oldSelector);
player.print("Cuboid: left click for a starting point, right click to extend");
} else if (typeName.equalsIgnoreCase("poly")) {
selector = new Polygonal2DRegionSelector(oldSelector);
player.print("2D polygon selector: Left/right click to add a point.");
Optional<Integer> limit = ActorSelectorLimits.forActor(player).getPolygonVertexLimit();
if (limit.isPresent()) {
player.print(limit.get() + " points maximum.");
}
} else if (typeName.equalsIgnoreCase("ellipsoid")) {
selector = new EllipsoidRegionSelector(oldSelector);
player.print("Ellipsoid selector: left click=center, right click to extend");
} else if (typeName.equalsIgnoreCase("sphere")) {
selector = new SphereRegionSelector(oldSelector);
player.print("Sphere selector: left click=center, right click to set radius");
} else if (typeName.equalsIgnoreCase("cyl")) {
selector = new CylinderRegionSelector(oldSelector);
player.print("Cylindrical selector: Left click=center, right click to extend.");
} else if (typeName.equalsIgnoreCase("convex") || typeName.equalsIgnoreCase("hull") || typeName.equalsIgnoreCase("polyhedron")) {
selector = new ConvexPolyhedralRegionSelector(oldSelector);
player.print("Convex polyhedral selector: Left click=First vertex, right click to add more.");
Optional<Integer> limit = ActorSelectorLimits.forActor(player).getPolyhedronVertexLimit();
if (limit.isPresent()) {
player.print(limit.get() + " points maximum.");
}
} else {
CommandListBox box = new CommandListBox("Selection modes");
StyledFragment contents = box.getContents();
StyledFragment tip = contents.createFragment(Style.RED);
tip.append("Select one of the modes below:").newLine();
box.appendCommand("cuboid", "Select two corners of a cuboid");
box.appendCommand("extend", "Fast cuboid selection mode");
box.appendCommand("poly", "Select a 2D polygon with height");
box.appendCommand("ellipsoid", "Select an ellipsoid");
box.appendCommand("sphere", "Select a sphere");
box.appendCommand("cyl", "Select a cylinder");
box.appendCommand("convex", "Select a convex polyhedral");
player.printRaw(ColorCodeBuilder.asColorCodes(box));
return;
}
if (args.hasFlag('d')) {
RegionSelectorType found = null;
for (RegionSelectorType type : RegionSelectorType.values()) {
if (type.getSelectorClass() == selector.getClass()) {
found = type;
break;
}
}
if (found != null) {
session.setDefaultRegionSelector(found);
player.print("Your default region selector is now " + found.name() + ".");
} else {
throw new RuntimeException("Something unexpected happened. Please report this.");
}
}
session.setRegionSelector(world, selector);
session.dispatchCUISelection(player);
}
public static Class<?> inject() {
return SelectionCommands.class;
}
}

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.command.composition;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.NullChangeSet;
@ -138,15 +139,24 @@ public class SelectionCommand extends SimpleCommand<Operation> {
newChunk = fc.copy(true);
newChunk.setLoc(queue, value[0], value[1]);
} else {
newChunk = queue.getChunk(value[0], value[1]);
newChunk.fillCuboid(value[2] & 15, value[4] & 15, minY, maxY, value[3] & 15, value[5] & 15, id, data);
int bx = value[2] & 15;
int tx = value[4] & 15;
int bz = value[3] & 15;
int tz = value[4] & 15;
if (bx == 0 && tx == 15 && bz == 0 && tz == 15) {
newChunk = fc.copy(true);
newChunk.setLoc(queue, value[0], value[1]);
} else {
newChunk = queue.getChunk(value[0], value[1]);
newChunk.fillCuboid(value[2] & 15, value[4] & 15, minY, maxY, value[3] & 15, value[5] & 15, id, data);
}
}
newChunk.addToQueue();
}
});
queue.enqueue();
editSession.setChangeSet(new NullChangeSet());
actor.print("[FAWE] Finished queueing " + cuboid.getArea() + " blocks.");
BBC.OPERATION.send(actor, BBC.VISITOR_BLOCK.format(cuboid.getArea()));
return null;
}
} catch (Throwable e) {
@ -159,9 +169,9 @@ public class SelectionCommand extends SimpleCommand<Operation> {
List<String> messages = Lists.newArrayList();
operation.addStatusMessages(messages);
if (messages.isEmpty()) {
actor.print("Operation completed.");
BBC.OPERATION.send(actor, 0);
} else {
actor.print("Operation completed (" + Joiner.on(", ").join(messages) + ").");
BBC.OPERATION.send(actor, Joiner.on(", ").join(messages));
}
return operation;

View File

@ -23,7 +23,6 @@ import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.MaxChangedBlocksException;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
import com.sk89q.worldedit.function.pattern.Pattern;
public class GravityBrush implements Brush {
@ -37,7 +36,6 @@ public class GravityBrush implements Brush {
@Override
public void build(EditSession editSession, Vector position, Pattern pattern, double sizeDouble) throws MaxChangedBlocksException {
int size = (int) sizeDouble;
BaseBlock air = new BaseBlock(BlockID.AIR, 0);
int endY = position.getBlockY() + size;
int startPerformY = Math.max(0, position.getBlockY() - size);
int startCheckY = fullHeight ? 0 : startPerformY;

View File

@ -268,7 +268,7 @@ public final class CommandManager {
} catch (WrappedCommandException e) {
FaweException faweException = FaweException.get(e);
if (faweException != null) {
actor.printError(BBC.PREFIX.s() + " " + BBC.WORLDEDIT_CANCEL_REASON.format(faweException.getMessage()));
BBC.WORLDEDIT_CANCEL_REASON.send(actor, faweException.getMessage());
} else {
Throwable t = e.getCause();
actor.printError("Please report this error: [See console]");
@ -298,7 +298,7 @@ public final class CommandManager {
@Override
public void run() {
final long time = System.currentTimeMillis() - start;
actor.print(BBC.PREFIX.s() + " Action completed in " + (time / 1000d) + " seconds");
BBC.ACTION_COMPLETE.send(actor, (time / 1000d));
}
});
}

View File

@ -409,7 +409,7 @@ public class PlatformManager {
} catch (Throwable e) {
FaweException faweException = FaweException.get(e);
if (faweException != null) {
actor.printError(BBC.PREFIX.s() + " " + BBC.WORLDEDIT_CANCEL_REASON.format(faweException.getMessage()));
BBC.WORLDEDIT_CANCEL_REASON.send(actor, faweException.getMessage());
} else {
actor.printError("Please report this error: [See console]");
actor.printRaw(e.getClass().getName() + ": " + e.getMessage());
@ -496,7 +496,7 @@ public class PlatformManager {
} catch (Throwable e) {
FaweException faweException = FaweException.get(e);
if (faweException != null) {
player.printError(BBC.PREFIX.s() + " " + BBC.WORLDEDIT_CANCEL_REASON.format(faweException.getMessage()));
BBC.WORLDEDIT_CANCEL_REASON.send(player, faweException.getMessage());
} else {
player.printError("Please report this error: [See console]");
player.printRaw(e.getClass().getName() + ": " + e.getMessage());

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.function.visitor;
import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@ -186,6 +187,6 @@ public abstract class BreadthFirstSearch implements Operation {
@Override
public void addStatusMessages(final List<String> messages) {
messages.add(this.getAffected() + " blocks affected");
messages.add(BBC.VISITOR_BLOCK.format(getAffected()));
}
}

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.function.visitor;
import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.entity.Entity;
import com.sk89q.worldedit.function.EntityFunction;
@ -78,7 +79,7 @@ public class EntityVisitor implements Operation {
@Override
public void addStatusMessages(final List<String> messages) {
messages.add(this.getAffected() + " blocks affected");
messages.add(BBC.VISITOR_ENTITY.format(getAffected()));
}
public static Class<?> inject() {

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.function.visitor;
import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.Vector2D;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.FlatRegionFunction;
@ -77,7 +78,7 @@ public class FlatRegionVisitor implements Operation {
@Override
public void addStatusMessages(final List<String> messages) {
messages.add(this.getAffected() + " columns affected");
messages.add(BBC.VISITOR_FLAT.format(getAffected()));
}
public static Class<?> inject() {

View File

@ -19,6 +19,7 @@
package com.sk89q.worldedit.function.visitor;
import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.function.RegionFunction;
@ -66,7 +67,7 @@ public class RegionVisitor implements Operation {
@Override
public void addStatusMessages(final List<String> messages) {
messages.add(this.getAffected() + " blocks affected");
messages.add(BBC.VISITOR_BLOCK.format(getAffected()));
}
public static Class<?> inject() {

View File

@ -0,0 +1,301 @@
/*
* 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.selector;
import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.BlockVector;
import com.sk89q.worldedit.IncompleteRegionException;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.internal.cui.CUIRegion;
import com.sk89q.worldedit.internal.cui.SelectionPointEvent;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.regions.RegionSelector;
import com.sk89q.worldedit.regions.selector.limit.SelectorLimits;
import com.sk89q.worldedit.world.World;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
/**
* Creates a {@code CuboidRegion} from a user's selections.
*/
public class CuboidRegionSelector extends com.sk89q.worldedit.regions.CuboidRegionSelector implements RegionSelector, CUIRegion {
public transient BlockVector position1;
public transient BlockVector position2;
public transient CuboidRegion region;
/**
* Create a new region selector with a {@code null} world.
*/
public CuboidRegionSelector() {
this((World) null);
}
/**
* Create a new region selector.
*
* @param world the world, which may be {@code null}
*/
public CuboidRegionSelector(@Nullable World world) {
region = new CuboidRegion(world, new Vector(), new Vector());
}
/**
* Create a copy of another selector.
*
* @param oldSelector another selector
*/
public CuboidRegionSelector(RegionSelector oldSelector) {
this(checkNotNull(oldSelector).getIncompleteRegion().getWorld());
if (oldSelector instanceof CuboidRegionSelector) {
final CuboidRegionSelector cuboidRegionSelector = (CuboidRegionSelector) oldSelector;
position1 = cuboidRegionSelector.position1;
position2 = cuboidRegionSelector.position2;
} else {
final Region oldRegion;
try {
oldRegion = oldSelector.getRegion();
} catch (IncompleteRegionException e) {
return;
}
position1 = oldRegion.getMinimumPoint().toBlockVector();
position2 = oldRegion.getMaximumPoint().toBlockVector();
}
region.setPos1(position1);
region.setPos2(position2);
}
/**
* Create a new region selector with the given two positions.
*
* @param world the world
* @param position1 position 1
* @param position2 position 2
*/
public CuboidRegionSelector(@Nullable World world, Vector position1, Vector position2) {
this(world);
checkNotNull(position1);
checkNotNull(position2);
this.position1 = position1.toBlockVector();
this.position2 = position2.toBlockVector();
region.setPos1(position1);
region.setPos2(position2);
}
@Nullable
@Override
public World getWorld() {
return region.getWorld();
}
@Override
public void setWorld(@Nullable World world) {
region.setWorld(world);
}
@Override
public boolean selectPrimary(Vector position, SelectorLimits limits) {
checkNotNull(position);
if (position1 != null && (position.compareTo(position1) == 0)) {
return false;
}
position1 = position.toBlockVector();
region.setPos1(position1);
return true;
}
@Override
public boolean selectSecondary(Vector position, SelectorLimits limits) {
checkNotNull(position);
if (position2 != null && (position.compareTo(position2)) == 0) {
return false;
}
position2 = position.toBlockVector();
region.setPos2(position2);
return true;
}
@Override
public void explainPrimarySelection(Actor player, LocalSession session, Vector pos) {
checkNotNull(player);
checkNotNull(session);
checkNotNull(pos);
if (position1 != null && position2 != null) {
BBC.SELECTOR_CUBOID_POS1.send(player, position1, "(" + region.getArea() + ")");
} else {
BBC.SELECTOR_CUBOID_POS1.send(player, position1, "");
}
session.dispatchCUIEvent(player, new SelectionPointEvent(0, pos, getArea()));
}
@Override
public void explainSecondarySelection(Actor player, LocalSession session, Vector pos) {
checkNotNull(player);
checkNotNull(session);
checkNotNull(pos);
if (position1 != null && position2 != null) {
BBC.SELECTOR_CUBOID_POS2.send(player, position1, "(" + region.getArea() + ")");
} else {
BBC.SELECTOR_CUBOID_POS2.send(player, position1, "");
}
session.dispatchCUIEvent(player, new SelectionPointEvent(1, pos, getArea()));
}
@Override
public void explainRegionAdjust(Actor player, LocalSession session) {
checkNotNull(player);
checkNotNull(session);
if (position1 != null) {
session.dispatchCUIEvent(player, new SelectionPointEvent(0, position1, getArea()));
}
if (position2 != null) {
session.dispatchCUIEvent(player, new SelectionPointEvent(1, position2, getArea()));
}
}
@Override
public BlockVector getPrimaryPosition() throws IncompleteRegionException {
if (position1 == null) {
throw new IncompleteRegionException();
}
return position1;
}
@Override
public boolean isDefined() {
return position1 != null && position2 != null;
}
@Override
public CuboidRegion getRegion() throws IncompleteRegionException {
if (position1 == null || position2 == null) {
throw new IncompleteRegionException();
}
return region;
}
@Override
public CuboidRegion getIncompleteRegion() {
return region;
}
@Override
public void learnChanges() {
position1 = region.getPos1().toBlockVector();
position2 = region.getPos2().toBlockVector();
}
@Override
public void clear() {
position1 = null;
position2 = null;
}
@Override
public String getTypeName() {
return "cuboid";
}
@Override
public List<String> getInformationLines() {
final List<String> lines = new ArrayList<String>();
if (position1 != null) {
lines.add("Position 1: " + position1);
}
if (position2 != null) {
lines.add("Position 2: " + position2);
}
return lines;
}
@Override
public int getArea() {
if (position1 == null) {
return -1;
}
if (position2 == null) {
return -1;
}
return region.getArea();
}
@Override
public void describeCUI(LocalSession session, Actor player) {
if (position1 != null) {
session.dispatchCUIEvent(player, new SelectionPointEvent(0, position1, getArea()));
}
if (position2 != null) {
session.dispatchCUIEvent(player, new SelectionPointEvent(1, position2, getArea()));
}
}
@Override
public void describeLegacyCUI(LocalSession session, Actor player) {
describeCUI(session, player);
}
@Override
public int getProtocolVersion() {
return 0;
}
@Override
public String getTypeID() {
return "cuboid";
}
@Override
public String getLegacyTypeID() {
return "cuboid";
}
public static Class<?> inject() {
return CuboidRegionSelector.class;
}
}

View File

@ -96,7 +96,7 @@ public class FaweSponge implements IFawe {
@Override
public void setupVault() {
debug(BBC.PREFIX.s() + "Permission hook not implemented yet!");
debug("Permission hook not implemented yet!");
}
@Override