diff --git a/bukkit/build.gradle b/bukkit/build.gradle
index 1f5463eb..a05b954a 100644
--- a/bukkit/build.gradle
+++ b/bukkit/build.gradle
@@ -5,6 +5,7 @@ dependencies {
compile project(':core')
compile 'org.bukkit.craftbukkitv1_10:craftbukkitv1_10:1.10'
compile 'org.bukkit.craftbukkitv1_11:Craftbukkit:1.11'
+ compile 'org.bukkit.craftbukkitv1_12_P2:Craftbukkit:1.12'
compile 'net.milkbowl.vault:VaultAPI:1.5'
compile 'com.massivecraft:factions:2.8.0'
compile 'com.drtshock:factions:1.6.9.5'
diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java
index 5048e878..b5b9283f 100644
--- a/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java
+++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java
@@ -5,6 +5,7 @@ import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
import com.boydti.fawe.bukkit.v1_10.BukkitQueue_1_10;
import com.boydti.fawe.bukkit.v1_11.BukkitQueue_1_11;
+import com.boydti.fawe.bukkit.v1_12.BukkitQueue_1_12;
import com.boydti.fawe.bukkit.v1_7.BukkitQueue17;
import com.boydti.fawe.bukkit.v1_8.BukkitQueue18R3;
import com.boydti.fawe.bukkit.v1_9.BukkitQueue_1_9_R1;
@@ -76,6 +77,7 @@ public class BukkitMain extends JavaPlugin {
v1_9_R2,
v1_10_R1,
v1_11_R1,
+ v1_12_R1,
NONE,
}
@@ -91,6 +93,8 @@ public class BukkitMain extends JavaPlugin {
return new BukkitQueue_1_10(world);
case v1_11_R1:
return new BukkitQueue_1_11(world);
+ case v1_12_R1:
+ return new BukkitQueue_1_12(world);
default:
case NONE:
return new BukkitQueue_All(world);
@@ -109,6 +113,8 @@ public class BukkitMain extends JavaPlugin {
return new BukkitQueue_1_10(world);
case v1_11_R1:
return new BukkitQueue_1_11(world);
+ case v1_12_R1:
+ return new BukkitQueue_1_12(world);
default:
case NONE:
return new BukkitQueue_All(world);
diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java
index 9cbdb084..18bc7088 100644
--- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java
+++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v0/ChunkListener.java
@@ -5,12 +5,11 @@ import com.boydti.fawe.bukkit.FaweBukkit;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.TaskManager;
+import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
-import java.util.HashSet;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
-import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType;
@@ -23,7 +22,8 @@ import org.bukkit.event.entity.ItemSpawnEvent;
public class ChunkListener implements Listener {
- int rateLimit = 0;
+ private int rateLimit = 0;
+ private int[] badLimit = new int[]{Settings.IMP.TICK_LIMITER.PHYSICS, Settings.IMP.TICK_LIMITER.FALLING, Settings.IMP.TICK_LIMITER.ITEMS};
public ChunkListener() {
if (Settings.IMP.TICK_LIMITER.ENABLED) {
@@ -34,10 +34,14 @@ public class ChunkListener implements Listener {
rateLimit--;
physicsFreeze = false;
itemFreeze = false;
- counter.clear();
lastZ = Integer.MIN_VALUE;
- for (Long badChunk : badChunks) {
- counter.put(badChunk, new int[]{Settings.IMP.TICK_LIMITER.PHYSICS, Settings.IMP.TICK_LIMITER.ITEMS, Settings.IMP.TICK_LIMITER.FALLING});
+
+ counter.clear();
+ for (Long2ObjectMap.Entry entry : badChunks.long2ObjectEntrySet()) {
+ long key = entry.getLongKey();
+ int x = MathMan.unpairIntX(key);
+ int z = MathMan.unpairIntY(key);
+ counter.put(key, badLimit);
}
badChunks.clear();
}
@@ -48,7 +52,7 @@ public class ChunkListener implements Listener {
public static boolean physicsFreeze = false;
public static boolean itemFreeze = false;
- private HashSet badChunks = new HashSet<>();
+ private Long2ObjectOpenHashMap badChunks = new Long2ObjectOpenHashMap<>();
private Long2ObjectOpenHashMap counter = new Long2ObjectOpenHashMap<>();
private int lastX = Integer.MIN_VALUE, lastZ = Integer.MIN_VALUE;
private int[] lastCount;
@@ -100,11 +104,12 @@ public class ChunkListener implements Listener {
if (y != lastPhysY) {
lastPhysY = y;
if (++count[0] == Settings.IMP.TICK_LIMITER.PHYSICS) {
- badChunks.add(MathMan.pairInt(cx, cz));
+ cancelNearby(cx, cz);
if (rateLimit <= 0) {
- rateLimit = 120;
+ rateLimit = 20;
Fawe.debug("[FAWE `tick-limiter`] Detected and cancelled physics lag source at " + block.getLocation());
}
+ event.setCancelled(true);
}
return;
}
@@ -112,24 +117,41 @@ public class ChunkListener implements Listener {
}
}
+ private void cancelNearby(int cx, int cz) {
+ cancel(cx, cz);
+ cancel(cx + 1, cz);
+ cancel(cx - 1, cz);
+ cancel(cx, cz + 1);
+ cancel(cx, cz - 1);
+ }
+
+ private void cancel(int cx, int cz) {
+ long key = MathMan.pairInt(cx, cz);
+ badChunks.put(key, (Boolean) true);
+ counter.put(key, badLimit);
+ }
+
@EventHandler(priority = EventPriority.LOWEST)
public void onBlockChange(EntityChangeBlockEvent event) {
if (physicsFreeze) {
event.setCancelled(true);
return;
}
- Material to = event.getTo();
- if (to == Material.AIR) {
- Block block = event.getBlock();
- int x = block.getX();
- int z = block.getZ();
- int cx = x >> 4;
- int cz = z >> 4;
- int[] count = getCount(cx, cz);
+ Block block = event.getBlock();
+ int x = block.getX();
+ int z = block.getZ();
+ int cx = x >> 4;
+ int cz = z >> 4;
+ int[] count = getCount(cx, cz);
+ if (count[1] >= Settings.IMP.TICK_LIMITER.FALLING) {
+ event.setCancelled(true);
+ return;
+ }
+ if (event.getEntityType() == EntityType.FALLING_BLOCK) {
if (++count[1] >= Settings.IMP.TICK_LIMITER.FALLING) {
- if (count[1] == Settings.IMP.TICK_LIMITER.FALLING) {
- count[0] = Settings.IMP.TICK_LIMITER.PHYSICS;
- badChunks.add(MathMan.pairInt(cx, cz));
+ cancelNearby(cx, cz);
+ if (rateLimit <= 0) {
+ rateLimit = 20;
Fawe.debug("[FAWE `tick-limiter`] Detected and cancelled falling block lag source at " + block.getLocation());
}
event.setCancelled(true);
@@ -148,15 +170,16 @@ public class ChunkListener implements Listener {
int cx = loc.getBlockX() >> 4;
int cz = loc.getBlockZ() >> 4;
int[] count = getCount(cx, cz);
+ if (count[2] >= Settings.IMP.TICK_LIMITER.ITEMS) {
+ event.setCancelled(true);
+ return;
+ }
if (++count[2] >= Settings.IMP.TICK_LIMITER.ITEMS) {
- if (count[2] == Settings.IMP.TICK_LIMITER.ITEMS) {
- count[0] = Settings.IMP.TICK_LIMITER.PHYSICS;
- cleanup(loc.getChunk());
- badChunks.add(MathMan.pairInt(cx, cz));
- if (rateLimit <= 0) {
- rateLimit = 120;
- Fawe.debug("[FAWE `tick-limiter`] Detected and cancelled item lag source at " + loc);
- }
+ cleanup(loc.getChunk());
+ cancelNearby(cx, cz);
+ if (rateLimit <= 0) {
+ rateLimit = 20;
+ Fawe.debug("[FAWE `tick-limiter`] Detected and cancelled item lag source at " + loc);
}
event.setCancelled(true);
return;
diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitQueue_1_11.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitQueue_1_11.java
index 0ea15699..ecb5b98d 100644
--- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitQueue_1_11.java
+++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/BukkitQueue_1_11.java
@@ -10,7 +10,6 @@ import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.RegionWrapper;
import com.boydti.fawe.object.RunnableVal;
import com.boydti.fawe.object.brush.visualization.VisualChunk;
-import com.boydti.fawe.object.number.LongAdder;
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan;
@@ -35,6 +34,7 @@ import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
+import java.util.concurrent.atomic.LongAdder;
import net.minecraft.server.v1_11_R1.BiomeBase;
import net.minecraft.server.v1_11_R1.BiomeCache;
import net.minecraft.server.v1_11_R1.Block;
diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/FaweChunkLoader.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/FaweChunkLoader.java
deleted file mode 100644
index b370d83d..00000000
--- a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_11/FaweChunkLoader.java
+++ /dev/null
@@ -1,243 +0,0 @@
-package com.boydti.fawe.bukkit.v1_11;
-
-import com.boydti.fawe.object.FaweInputStream;
-import com.boydti.fawe.util.MainUtil;
-import com.boydti.fawe.util.MathMan;
-import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
-import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.util.Iterator;
-import java.util.List;
-import javax.annotation.Nullable;
-import net.minecraft.server.v1_11_R1.Block;
-import net.minecraft.server.v1_11_R1.Chunk;
-import net.minecraft.server.v1_11_R1.ChunkSection;
-import net.minecraft.server.v1_11_R1.Entity;
-import net.minecraft.server.v1_11_R1.ExceptionWorldConflict;
-import net.minecraft.server.v1_11_R1.IAsyncChunkSaver;
-import net.minecraft.server.v1_11_R1.IChunkLoader;
-import net.minecraft.server.v1_11_R1.MinecraftKey;
-import net.minecraft.server.v1_11_R1.NBTCompressedStreamTools;
-import net.minecraft.server.v1_11_R1.NBTReadLimiter;
-import net.minecraft.server.v1_11_R1.NBTTagCompound;
-import net.minecraft.server.v1_11_R1.NBTTagList;
-import net.minecraft.server.v1_11_R1.NextTickListEntry;
-import net.minecraft.server.v1_11_R1.NibbleArray;
-import net.minecraft.server.v1_11_R1.TileEntity;
-import net.minecraft.server.v1_11_R1.World;
-
-public class FaweChunkLoader implements IChunkLoader, IAsyncChunkSaver {
-
- private final File folder;
- private Long2ObjectMap hashes = new Long2ObjectOpenHashMap<>();
-
- public FaweChunkLoader(File folder) {
- this.folder = folder;
- System.out.println(folder);
- }
-
- // writeNextIO (save)
- @Override
- public boolean c() {
- return false;
- }
-
- // loadChunk
- @Nullable
- @Override
- public Chunk a(World world, int x, int z) throws IOException {
- long pair = MathMan.pairInt(x, z);
- Long hash = hashes.get(pair);
- if (hash == null) {
- return null;
- }
- File file = new File(folder, hash.toString());
- int length = (int) file.length();
- try (FaweInputStream in = MainUtil.getCompressedIS(new FileInputStream(file), Math.min(length, 8192))) {
- NBTTagCompound nbttagcompound = NBTCompressedStreamTools.a(in, NBTReadLimiter.a);
- return readChunkFromNBT(world, nbttagcompound);
- }
- }
-
- private Chunk readChunkFromNBT(World world, NBTTagCompound nbttagcompound) {
- int i = nbttagcompound.getInt("xPos");
- int j = nbttagcompound.getInt("zPos");
- Chunk chunk = new Chunk(world, i, j);
- chunk.a(nbttagcompound.getIntArray("HeightMap"));
- chunk.d(nbttagcompound.getBoolean("TerrainPopulated"));
- chunk.e(nbttagcompound.getBoolean("LightPopulated"));
- chunk.c(nbttagcompound.getLong("InhabitedTime"));
- NBTTagList nbttaglist = nbttagcompound.getList("Sections", 10);
- ChunkSection[] achunksection = new ChunkSection[16];
- boolean flag1 = world.worldProvider.m();
-
- for(int k = 0; k < nbttaglist.size(); ++k) {
- NBTTagCompound nbttagcompound1 = nbttaglist.get(k);
- byte b0 = nbttagcompound1.getByte("Y");
- ChunkSection chunksection = new ChunkSection(b0 << 4, flag1);
- byte[] abyte = nbttagcompound1.getByteArray("Blocks");
- NibbleArray nibblearray = new NibbleArray(nbttagcompound1.getByteArray("Data"));
- NibbleArray nibblearray1 = nbttagcompound1.hasKeyOfType("Add", 7) ? new NibbleArray(nbttagcompound1.getByteArray("Add")):null;
- chunksection.getBlocks().a(abyte, nibblearray, nibblearray1);
- chunksection.a(new NibbleArray(nbttagcompound1.getByteArray("BlockLight")));
- if(flag1) {
- chunksection.b(new NibbleArray(nbttagcompound1.getByteArray("SkyLight")));
- }
-
- chunksection.recalcBlockCounts();
- achunksection[b0] = chunksection;
- }
-
- chunk.a(achunksection);
- if(nbttagcompound.hasKeyOfType("Biomes", 7)) {
- chunk.a(nbttagcompound.getByteArray("Biomes"));
- }
-
- return chunk;
- }
-
-
- // saveChunk
- @Override
- public void a(World world, Chunk chunk) throws IOException, ExceptionWorldConflict {
- try {
- NBTTagCompound exception = new NBTTagCompound();
- NBTTagCompound nbttagcompound1 = new NBTTagCompound();
- exception.set("Level", nbttagcompound1);
- exception.setInt("DataVersion", 819);
- this.writeChunkToNBT(chunk, world, nbttagcompound1);
-// this.a(chunk.k(), exception);
- } catch (Exception var5) {
- }
- }
-
- private void writeChunkToNBT(Chunk chunk, World world, NBTTagCompound nbttagcompound) {
- nbttagcompound.setInt("xPos", chunk.locX);
- nbttagcompound.setInt("zPos", chunk.locZ);
- nbttagcompound.setLong("LastUpdate", world.getTime());
- nbttagcompound.setIntArray("HeightMap", chunk.r());
- nbttagcompound.setBoolean("TerrainPopulated", chunk.isDone());
- nbttagcompound.setBoolean("LightPopulated", chunk.v());
- nbttagcompound.setLong("InhabitedTime", chunk.x());
- ChunkSection[] achunksection = chunk.getSections();
- NBTTagList nbttaglist = new NBTTagList();
- boolean flag = world.worldProvider.m();
- ChunkSection[] achunksection1 = achunksection;
- int i = achunksection.length;
-
- NBTTagCompound nbttagcompound1;
- for(int nbttaglist1 = 0; nbttaglist1 < i; ++nbttaglist1) {
- ChunkSection iterator = achunksection1[nbttaglist1];
- if(iterator != Chunk.a) {
- nbttagcompound1 = new NBTTagCompound();
- nbttagcompound1.setByte("Y", (byte)(iterator.getYPosition() >> 4 & 255));
- byte[] nbttaglist2 = new byte[4096];
- NibbleArray list = new NibbleArray();
- NibbleArray nibblearray1 = iterator.getBlocks().exportData(nbttaglist2, list);
- nbttagcompound1.setByteArray("Blocks", nbttaglist2);
- nbttagcompound1.setByteArray("Data", list.asBytes());
- if(nibblearray1 != null) {
- nbttagcompound1.setByteArray("Add", nibblearray1.asBytes());
- }
-
- nbttagcompound1.setByteArray("BlockLight", iterator.getEmittedLightArray().asBytes());
- if(flag) {
- nbttagcompound1.setByteArray("SkyLight", iterator.getSkyLightArray().asBytes());
- } else {
- nbttagcompound1.setByteArray("SkyLight", new byte[iterator.getEmittedLightArray().asBytes().length]);
- }
-
- nbttaglist.add(nbttagcompound1);
- }
- }
-
- nbttagcompound.set("Sections", nbttaglist);
- nbttagcompound.setByteArray("Biomes", chunk.getBiomeIndex());
- chunk.g(false);
- NBTTagList var22 = new NBTTagList();
-
- Iterator var23;
- for(i = 0; i < chunk.getEntitySlices().length; ++i) {
- var23 = chunk.getEntitySlices()[i].iterator();
-
- while(var23.hasNext()) {
- Entity var24 = (Entity)var23.next();
- nbttagcompound1 = new NBTTagCompound();
- if(var24.d(nbttagcompound1)) {
- chunk.g(true);
- var22.add(nbttagcompound1);
- }
- }
- }
-
- nbttagcompound.set("Entities", var22);
- NBTTagList var25 = new NBTTagList();
- var23 = chunk.getTileEntities().values().iterator();
-
- while(var23.hasNext()) {
- TileEntity var26 = (TileEntity)var23.next();
- nbttagcompound1 = var26.save(new NBTTagCompound());
- var25.add(nbttagcompound1);
- }
-
- nbttagcompound.set("TileEntities", var25);
- List var27 = world.a(chunk, false);
- if(var27 != null) {
- long k = world.getTime();
- NBTTagList nbttaglist3 = new NBTTagList();
- Iterator iterator1 = var27.iterator();
-
- while(iterator1.hasNext()) {
- NextTickListEntry nextticklistentry = (NextTickListEntry)iterator1.next();
- NBTTagCompound nbttagcompound2 = new NBTTagCompound();
- MinecraftKey minecraftkey = (MinecraftKey) Block.REGISTRY.b(nextticklistentry.a());
- nbttagcompound2.setString("i", minecraftkey == null?"":minecraftkey.toString());
- nbttagcompound2.setInt("x", nextticklistentry.a.getX());
- nbttagcompound2.setInt("y", nextticklistentry.a.getY());
- nbttagcompound2.setInt("z", nextticklistentry.a.getZ());
- nbttagcompound2.setInt("t", (int)(nextticklistentry.b - k));
- nbttagcompound2.setInt("p", nextticklistentry.c);
- nbttaglist3.add(nbttagcompound2);
- }
-
- nbttagcompound.set("TileTicks", nbttaglist3);
- }
-
- }
-
- // saveExtraChunkData
- @Override
- public void b(World world, Chunk chunk) throws IOException {
-
- }
-
- // chunkTick
- @Override
- public void a() {
-
- }
-
- // saveExtraData
- @Override
- public void b() {
-// try {
-// this.savingExtraData = true;
-//
-// while(true) {
-// if(this.writeNextIO()) {
-// continue;
-// }
-// }
-// } finally {
-// this.savingExtraData = false;
-// }
- }
-
- // isChunkGeneratedAt
- @Override
- public boolean a(int x, int z) {
- return hashes.containsKey(MathMan.pairInt(x, z));
- }
-}
diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12.java
new file mode 100644
index 00000000..36433cb5
--- /dev/null
+++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12.java
@@ -0,0 +1,499 @@
+package com.boydti.fawe.bukkit.v1_12;
+
+import com.boydti.fawe.Fawe;
+import com.boydti.fawe.FaweCache;
+import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
+import com.boydti.fawe.example.CharFaweChunk;
+import com.boydti.fawe.object.FaweChunk;
+import com.boydti.fawe.object.FaweQueue;
+import com.boydti.fawe.util.MainUtil;
+import com.boydti.fawe.util.ReflectionUtils;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.ListTag;
+import com.sk89q.jnbt.LongTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.internal.Constants;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import net.minecraft.server.v1_12_R1.Block;
+import net.minecraft.server.v1_12_R1.BlockPosition;
+import net.minecraft.server.v1_12_R1.ChunkSection;
+import net.minecraft.server.v1_12_R1.DataBits;
+import net.minecraft.server.v1_12_R1.DataPalette;
+import net.minecraft.server.v1_12_R1.DataPaletteBlock;
+import net.minecraft.server.v1_12_R1.DataPaletteGlobal;
+import net.minecraft.server.v1_12_R1.Entity;
+import net.minecraft.server.v1_12_R1.EntityPlayer;
+import net.minecraft.server.v1_12_R1.EntityTypes;
+import net.minecraft.server.v1_12_R1.IBlockData;
+import net.minecraft.server.v1_12_R1.MinecraftKey;
+import net.minecraft.server.v1_12_R1.NBTTagCompound;
+import net.minecraft.server.v1_12_R1.TileEntity;
+import org.bukkit.Chunk;
+import org.bukkit.World;
+import org.bukkit.craftbukkit.v1_12_R1.CraftChunk;
+import org.bukkit.event.entity.CreatureSpawnEvent;
+
+public class BukkitChunk_1_12 extends CharFaweChunk {
+
+ public DataPaletteBlock[] sectionPalettes;
+
+ public static Map> entityKeys;
+
+ /**
+ * A FaweSections object represents a chunk and the blocks that you wish to change in it.
+ *
+ * @param parent
+ * @param x
+ * @param z
+ */
+ public BukkitChunk_1_12(FaweQueue parent, int x, int z) {
+ super(parent, x, z);
+ }
+
+ public BukkitChunk_1_12(FaweQueue parent, int x, int z, char[][] ids, short[] count, short[] air, byte[] heightMap) {
+ super(parent, x, z, ids, count, air, heightMap);
+ }
+
+ public void storeBiomes(byte[] biomes) {
+ this.biomes = Arrays.copyOf(biomes, biomes.length);
+ }
+
+ public boolean storeTile(TileEntity tile, BlockPosition pos) {
+ NBTTagCompound tag = new NBTTagCompound();
+ CompoundTag nativeTag = getParent().getTag(tile);
+ setTile(pos.getX() & 15, pos.getY(), pos.getZ() & 15, nativeTag);
+ return true;
+ }
+
+ public boolean storeEntity(Entity ent) throws InvocationTargetException, IllegalAccessException {
+ if (ent instanceof EntityPlayer) {
+ return false;
+ }
+ int x = ((int) Math.round(ent.locX) & 15);
+ int z = ((int) Math.round(ent.locZ) & 15);
+ int y = ((int) Math.round(ent.locY) & 0xFF);
+ int i = FaweCache.CACHE_I[y][z][x];
+ int j = FaweCache.CACHE_J[y][z][x];
+ String id = EntityTypes.b(ent);
+ if (id != null) {
+ NBTTagCompound tag = new NBTTagCompound();
+ ent.save(tag); // readEntityIntoTag
+ CompoundTag nativeTag = (CompoundTag) getParent().methodToNative.invoke(getParent().adapter, tag);
+ Map map = ReflectionUtils.getMap(nativeTag.getValue());
+ map.put("Id", new StringTag(id));
+ setEntity(nativeTag);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ @Override
+ public CharFaweChunk copy(boolean shallow) {
+ BukkitChunk_1_12 copy;
+ if (shallow) {
+ copy = new BukkitChunk_1_12(getParent(), getX(), getZ(), ids, count, air, heightMap);
+ copy.biomes = biomes;
+ copy.chunk = chunk;
+ } else {
+ copy = new BukkitChunk_1_12(getParent(), getX(), getZ(), (char[][]) MainUtil.copyNd(ids), count.clone(), air.clone(), heightMap.clone());
+ copy.biomes = biomes;
+ copy.chunk = chunk;
+ copy.biomes = biomes.clone();
+ copy.chunk = chunk;
+ }
+ if (sectionPalettes != null) {
+ copy.sectionPalettes = new DataPaletteBlock[16];
+ try {
+ for (int i = 0; i < sectionPalettes.length; i++) {
+ DataPaletteBlock current = sectionPalettes[i];
+ if (current == null) {
+ continue;
+ }
+ // Clone palette
+ DataPalette currentPalette = (DataPalette) BukkitQueue_1_12.fieldPalette.get(current);
+ if (!(currentPalette instanceof DataPaletteGlobal)) {
+ current.a(128, null);
+ }
+ DataPaletteBlock paletteBlock = newDataPaletteBlock();
+ currentPalette = (DataPalette) BukkitQueue_1_12.fieldPalette.get(current);
+ if (!(currentPalette instanceof DataPaletteGlobal)) {
+ throw new RuntimeException("Palette must be global!");
+ }
+ BukkitQueue_1_12.fieldPalette.set(paletteBlock, currentPalette);
+ // Clone size
+ BukkitQueue_1_12.fieldSize.set(paletteBlock, BukkitQueue_1_12.fieldSize.get(current));
+ // Clone palette
+ DataBits currentBits = (DataBits) BukkitQueue_1_12.fieldBits.get(current);
+ DataBits newBits = new DataBits(1, 0);
+ for (Field field : DataBits.class.getDeclaredFields()) {
+ field.setAccessible(true);
+ Object currentValue = field.get(currentBits);
+ if (currentValue instanceof long[]) {
+ currentValue = ((long[]) currentValue).clone();
+ }
+ field.set(newBits, currentValue);
+ }
+ BukkitQueue_1_12.fieldBits.set(paletteBlock, newBits);
+ copy.sectionPalettes[i] = paletteBlock;
+ }
+ } catch (Throwable e) {
+ MainUtil.handleError(e);
+ }
+ }
+ return copy;
+ }
+
+ @Override
+ public Chunk getNewChunk() {
+ return ((BukkitQueue_1_12) getParent()).getWorld().getChunkAt(getX(), getZ());
+ }
+
+ public DataPaletteBlock newDataPaletteBlock() {
+ try {
+ return new DataPaletteBlock();
+ } catch (Throwable e) {
+ try {
+ Constructor constructor = DataPaletteBlock.class.getDeclaredConstructor(IBlockData[].class);
+ return constructor.newInstance((Object) null);
+ } catch (Throwable e2) {
+ throw new RuntimeException(e2);
+ }
+ }
+ }
+
+ public void optimize() {
+ if (sectionPalettes != null) {
+ return;
+ }
+ char[][] arrays = getCombinedIdArrays();
+ IBlockData lastBlock = null;
+ char lastChar = Character.MAX_VALUE;
+ for (int layer = 0; layer < 16; layer++) {
+ if (getCount(layer) > 0) {
+ if (sectionPalettes == null) {
+ sectionPalettes = new DataPaletteBlock[16];
+ }
+ DataPaletteBlock palette = newDataPaletteBlock();
+ char[] blocks = getIdArray(layer);
+ for (int y = 0; y < 16; y++) {
+ for (int z = 0; z < 16; z++) {
+ for (int x = 0; x < 16; x++) {
+ char combinedId = blocks[FaweCache.CACHE_J[y][z][x]];
+ if (combinedId > 1) {
+ palette.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @Override
+ public void start() {
+ getChunk().load(true);
+ }
+
+ private void removeEntity(Entity entity) {
+ entity.b(false);
+ entity.die();
+ entity.valid = false;
+ }
+
+ @Override
+ public FaweChunk call() {
+ try {
+ BukkitChunk_1_12_Copy copy = getParent().getChangeTask() != null ? new BukkitChunk_1_12_Copy(getParent(), getX(), getZ()) : null;
+ final Chunk chunk = this.getChunk();
+ final World world = chunk.getWorld();
+ int bx = this.getX() << 4;
+ int bz = this.getZ() << 4;
+ final boolean flag = world.getEnvironment() == World.Environment.NORMAL;
+ net.minecraft.server.v1_12_R1.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
+ nmsChunk.f(true); // Set Modified
+ nmsChunk.mustSave = true;
+ net.minecraft.server.v1_12_R1.World nmsWorld = nmsChunk.world;
+ ChunkSection[] sections = nmsChunk.getSections();
+ final Collection[] entities = (Collection[]) getParent().getEntitySlices.invoke(nmsChunk);
+ Map tiles = nmsChunk.getTileEntities();
+ // Set heightmap
+ getParent().setHeightMap(this, heightMap);
+ // Remove entities
+ HashSet entsToRemove = this.getEntityRemoves();
+ if (!entsToRemove.isEmpty()) {
+ for (int i = 0; i < entities.length; i++) {
+ Collection ents = entities[i];
+ if (!ents.isEmpty()) {
+ Iterator iter = ents.iterator();
+ while (iter.hasNext()) {
+ Entity entity = iter.next();
+ if (entsToRemove.contains(entity.getUniqueID())) {
+ if (copy != null) {
+ copy.storeEntity(entity);
+ }
+ removeEntity(entity);
+ iter.remove();
+ }
+ }
+ }
+ }
+ }
+ for (int i = 0; i < entities.length; i++) {
+ int count = this.getCount(i);
+ if (count == 0) {
+ continue;
+ } else if (count >= 4096) {
+ Collection ents = entities[i];
+ if (!ents.isEmpty()) {
+ if (copy != null) {
+ for (Entity entity : ents) {
+ copy.storeEntity(entity);
+ }
+ }
+ synchronized (BukkitQueue_0.class) {
+ ents.clear();
+ }
+ }
+ } else {
+ Collection ents = entities[i];
+ if (!ents.isEmpty()) {
+ char[] array = this.getIdArray(i);
+ if (array == null) continue;
+ Iterator iter = ents.iterator();
+ while (iter.hasNext()) {
+ Entity entity = iter.next();
+ if (entity instanceof EntityPlayer) {
+ continue;
+ }
+ int x = ((int) Math.round(entity.locX) & 15);
+ int z = ((int) Math.round(entity.locZ) & 15);
+ int y = (int) Math.round(entity.locY);
+ if (y < 0 || y > 255) continue;
+ if (array[FaweCache.CACHE_J[y][z][x]] != 0) {
+ if (copy != null) {
+ copy.storeEntity(entity);
+ }
+ iter.remove();
+ removeEntity(entity);
+ }
+ }
+ }
+ }
+ }
+ // Set entities
+ Set entitiesToSpawn = this.getEntities();
+ Set createdEntities = new HashSet<>();
+ if (!entitiesToSpawn.isEmpty()) {
+ synchronized (BukkitQueue_0.class) {
+ for (CompoundTag nativeTag : entitiesToSpawn) {
+ Map entityTagMap = ReflectionUtils.getMap(nativeTag.getValue());
+ StringTag idTag = (StringTag) entityTagMap.get("Id");
+ ListTag posTag = (ListTag) entityTagMap.get("Pos");
+ ListTag rotTag = (ListTag) entityTagMap.get("Rotation");
+ if (idTag == null || posTag == null || rotTag == null) {
+ Fawe.debug("Unknown entity tag: " + nativeTag);
+ continue;
+ }
+ double x = posTag.getDouble(0);
+ double y = posTag.getDouble(1);
+ double z = posTag.getDouble(2);
+ float yaw = rotTag.getFloat(0);
+ float pitch = rotTag.getFloat(1);
+ String id = idTag.getValue();
+ if (entityKeys == null) {
+ entityKeys = new HashMap<>();
+ for (MinecraftKey key : EntityTypes.a()) {
+ String currentId = EntityTypes.a(key);
+ Class extends Entity> clazz = EntityTypes.b.get(key);
+ entityKeys.put(currentId, clazz);
+ entityKeys.put(key.getKey(), clazz);
+ }
+ }
+ Class extends Entity> clazz = entityKeys.get(id);
+ if (clazz != null) {
+ Entity entity = EntityTypes.a(clazz, nmsWorld);
+ if (entity != null) {
+ UUID uuid = entity.getUniqueID();
+ entityTagMap.put("UUIDMost", new LongTag(uuid.getMostSignificantBits()));
+ entityTagMap.put("UUIDLeast", new LongTag(uuid.getLeastSignificantBits()));
+ if (nativeTag != null) {
+ NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_12.methodFromNative.invoke(BukkitQueue_1_12.adapter, nativeTag);
+ for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
+ tag.remove(name);
+ }
+ entity.f(tag);
+ }
+ entity.setLocation(x, y, z, yaw, pitch);
+ nmsWorld.addEntity(entity, CreatureSpawnEvent.SpawnReason.CUSTOM);
+ createdEntities.add(entity.getUniqueID());
+ }
+ }
+ }
+ }
+ }
+ // Trim tiles
+ Iterator> iterator = tiles.entrySet().iterator();
+ HashMap toRemove = null;
+ while (iterator.hasNext()) {
+ Map.Entry tile = iterator.next();
+ BlockPosition pos = tile.getKey();
+ int lx = pos.getX() & 15;
+ int ly = pos.getY();
+ int lz = pos.getZ() & 15;
+ int j = FaweCache.CACHE_I[ly][lz][lx];
+ char[] array = this.getIdArray(j);
+ if (array == null) {
+ continue;
+ }
+ int k = FaweCache.CACHE_J[ly][lz][lx];
+ if (array[k] != 0) {
+ if (toRemove == null) {
+ toRemove = new HashMap<>();
+ }
+ if (copy != null) {
+ copy.storeTile(tile.getValue(), tile.getKey());
+ }
+ toRemove.put(tile.getKey(), tile.getValue());
+ }
+ }
+ if (toRemove != null) {
+ for (Map.Entry entry : toRemove.entrySet()) {
+ BlockPosition bp = entry.getKey();
+ TileEntity tile = entry.getValue();
+ tiles.remove(bp);
+ tile.z();
+ nmsWorld.s(bp);
+ tile.invalidateBlockCache();
+ }
+
+ }
+ // Set blocks
+ for (int j = 0; j < sections.length; j++) {
+ int count = this.getCount(j);
+ if (count == 0) {
+ continue;
+ }
+ int countAir = this.getAir(j);
+ final char[] array = this.getIdArray(j);
+ if (array == null) {
+ continue;
+ }
+ ChunkSection section = sections[j];
+ if (copy != null) {
+ copy.storeSection(section, j);
+ }
+ if (section == null) {
+ if (count == countAir) {
+ continue;
+ }
+ if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
+ section = sections[j] = getParent().newChunkSection(j << 4, flag, null);
+ getParent().setPalette(section, this.sectionPalettes[j]);
+ getParent().setCount(0, count - this.getAir(j), section);
+ continue;
+ } else {
+ sections[j] = getParent().newChunkSection(j << 4, flag, array);
+ continue;
+ }
+ } else if (count >= 4096) {
+ if (countAir >= 4096) {
+ sections[j] = null;
+ continue;
+ }
+ if (this.sectionPalettes != null && this.sectionPalettes[j] != null) {
+ getParent().setPalette(section, this.sectionPalettes[j]);
+ getParent().setCount(0, count - this.getAir(j), section);
+ continue;
+ } else {
+ sections[j] = getParent().newChunkSection(j << 4, flag, array);
+ continue;
+ }
+ }
+ int by = j << 4;
+ DataPaletteBlock nibble = section.getBlocks();
+ int nonEmptyBlockCount = 0;
+ IBlockData existing;
+ for (int y = 0; y < 16; y++) {
+ short[][] i1 = FaweCache.CACHE_J[y];
+ for (int z = 0; z < 16; z++) {
+ short[] i2 = i1[z];
+ for (int x= 0; x < 16; x++) {
+ char combinedId = array[i2[x]];
+ switch (combinedId) {
+ case 0:
+ continue;
+ case 1:
+ existing = nibble.a(x, y, z);
+ if (existing != BukkitQueue_1_12.air) {
+ if (existing.d() > 0) {
+ getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
+ }
+ nonEmptyBlockCount--;
+ }
+ nibble.setBlock(x, y, z, BukkitQueue_1_12.air);
+ continue;
+ default:
+ existing = nibble.a(x, y, z);
+ if (existing != BukkitQueue_1_12.air) {
+ if (existing.d() > 0) {
+ getParent().getRelighter().addLightUpdate(bx + x, by + y, bz + z);
+ }
+ } else {
+ nonEmptyBlockCount++;
+ }
+ nibble.setBlock(x, y, z, getParent().IBD_CACHE[(int) combinedId]);
+ }
+ }
+ }
+ }
+ getParent().setCount(0, getParent().getNonEmptyBlockCount(section) + nonEmptyBlockCount, section);
+ }
+ // Set biomes
+ if (this.biomes != null) {
+ if (copy != null) {
+ copy.storeBiomes(nmsChunk.getBiomeIndex());
+ }
+ byte[] currentBiomes = nmsChunk.getBiomeIndex();
+ for (int i = 0 ; i < this.biomes.length; i++) {
+ if (this.biomes[i] != 0) {
+ currentBiomes[i] = this.biomes[i];
+ }
+ }
+ }
+ // Set tiles
+ Map tilesToSpawn = this.getTiles();
+ for (Map.Entry entry : tilesToSpawn.entrySet()) {
+ CompoundTag nativeTag = entry.getValue();
+ short blockHash = entry.getKey();
+ int x = (blockHash >> 12 & 0xF) + bx;
+ int y = (blockHash & 0xFF);
+ int z = (blockHash >> 8 & 0xF) + bz;
+ BlockPosition pos = new BlockPosition(x, y, z); // Set pos
+ TileEntity tileEntity = nmsWorld.getTileEntity(pos);
+ if (tileEntity != null) {
+ NBTTagCompound tag = (NBTTagCompound) BukkitQueue_1_12.methodFromNative.invoke(BukkitQueue_1_12.adapter, nativeTag);
+ tileEntity.a(tag); // ReadTagIntoTile
+ }
+ }
+ // Change task
+ if (copy != null) {
+ getParent().getChangeTask().run(copy, this);
+ }
+ } catch (Throwable e) {
+ MainUtil.handleError(e);
+ }
+ return this;
+ }
+}
diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12_Copy.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12_Copy.java
new file mode 100644
index 00000000..10e39f1d
--- /dev/null
+++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitChunk_1_12_Copy.java
@@ -0,0 +1,80 @@
+package com.boydti.fawe.bukkit.v1_12;
+
+import com.boydti.fawe.object.FaweQueue;
+import net.minecraft.server.v1_12_R1.ChunkSection;
+import net.minecraft.server.v1_12_R1.DataPaletteBlock;
+import net.minecraft.server.v1_12_R1.NibbleArray;
+
+public class BukkitChunk_1_12_Copy extends BukkitChunk_1_12 {
+ public final byte[][] idsBytes;
+ public final byte[][] datasBytes;
+
+ public BukkitChunk_1_12_Copy(FaweQueue parent, int x, int z) {
+ super(parent, x, z);
+ idsBytes = new byte[16][];
+ datasBytes = new byte[16][];
+ }
+
+ public void set(int i, byte[] ids, byte[] data) {
+ this.idsBytes[i] = ids;
+ this.datasBytes[i] = data;
+ }
+
+ public boolean storeSection(ChunkSection section, int layer) throws IllegalAccessException {
+ if (section == null) {
+ return false;
+ }
+ DataPaletteBlock blocks = section.getBlocks();
+ byte[] ids = new byte[4096];
+ NibbleArray data = new NibbleArray();
+ blocks.exportData(ids, data);
+ set(layer, ids, data.asBytes());
+ short solid = (short) getParent().fieldNonEmptyBlockCount.getInt(section);
+ count[layer] = solid;
+ air[layer] = (short) (4096 - solid);
+ return true;
+ }
+
+ @Override
+ public char[][] getCombinedIdArrays() {
+ for (int i = 0; i < ids.length; i++) {
+ getIdArray(i);
+ }
+ return super.getCombinedIdArrays();
+ }
+
+ @Override
+ public char[] getIdArray(int i) {
+ char[] combined = this.ids[i];
+ if (combined != null) {
+ return combined;
+ }
+ byte[] idsBytesArray = idsBytes[i];
+ if (idsBytesArray == null) {
+ return null;
+ }
+ byte[] datasBytesArray = datasBytes[i];
+
+ idsBytes[i] = null;
+ datasBytes[i] = null;
+
+ this.ids[i] = combined = new char[4096];
+ for (int j = 0, k = 0; j < 2048; j++, k += 2) {
+ combined[k] = (char) (((idsBytesArray[k] & 0xFF) << 4) + (datasBytesArray[j] & 15));
+ }
+ for (int j = 0, k = 1; j < 2048; j++, k += 2) {
+ combined[k] = (char) (((idsBytesArray[k] & 0xFF) << 4) + ((datasBytesArray[j] >> 4) & 15));
+ }
+ return combined;
+ }
+
+ @Override
+ public void setBlock(int x, int y, int z, int id) {
+ throw new UnsupportedOperationException("This chunk is an immutable copy");
+ }
+
+ @Override
+ public void setBlock(int x, int y, int z, int id, int data) {
+ throw new UnsupportedOperationException("This chunk is an immutable copy");
+ }
+}
diff --git a/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitQueue_1_12.java b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitQueue_1_12.java
new file mode 100644
index 00000000..1dfa2ca3
--- /dev/null
+++ b/bukkit/src/main/java/com/boydti/fawe/bukkit/v1_12/BukkitQueue_1_12.java
@@ -0,0 +1,803 @@
+package com.boydti.fawe.bukkit.v1_12;
+
+import com.boydti.fawe.Fawe;
+import com.boydti.fawe.FaweCache;
+import com.boydti.fawe.bukkit.BukkitPlayer;
+import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
+import com.boydti.fawe.example.CharFaweChunk;
+import com.boydti.fawe.object.FaweChunk;
+import com.boydti.fawe.object.FawePlayer;
+import com.boydti.fawe.object.RegionWrapper;
+import com.boydti.fawe.object.RunnableVal;
+import com.boydti.fawe.object.brush.visualization.VisualChunk;
+import com.boydti.fawe.object.visitor.FaweChunkVisitor;
+import com.boydti.fawe.util.MainUtil;
+import com.boydti.fawe.util.MathMan;
+import com.boydti.fawe.util.ReflectionUtils;
+import com.boydti.fawe.util.TaskManager;
+import com.sk89q.jnbt.CompoundTag;
+import com.sk89q.jnbt.StringTag;
+import com.sk89q.jnbt.Tag;
+import com.sk89q.worldedit.world.biome.BaseBiome;
+import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufAllocator;
+import java.io.File;
+import java.io.IOException;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.util.ArrayDeque;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.LongAdder;
+import net.minecraft.server.v1_12_R1.BiomeBase;
+import net.minecraft.server.v1_12_R1.BiomeCache;
+import net.minecraft.server.v1_12_R1.Block;
+import net.minecraft.server.v1_12_R1.BlockPosition;
+import net.minecraft.server.v1_12_R1.ChunkProviderGenerate;
+import net.minecraft.server.v1_12_R1.ChunkProviderServer;
+import net.minecraft.server.v1_12_R1.ChunkSection;
+import net.minecraft.server.v1_12_R1.DataPaletteBlock;
+import net.minecraft.server.v1_12_R1.Entity;
+import net.minecraft.server.v1_12_R1.EntityPlayer;
+import net.minecraft.server.v1_12_R1.EntityTracker;
+import net.minecraft.server.v1_12_R1.EntityTypes;
+import net.minecraft.server.v1_12_R1.EnumDifficulty;
+import net.minecraft.server.v1_12_R1.EnumGamemode;
+import net.minecraft.server.v1_12_R1.EnumSkyBlock;
+import net.minecraft.server.v1_12_R1.IBlockData;
+import net.minecraft.server.v1_12_R1.IDataManager;
+import net.minecraft.server.v1_12_R1.MinecraftServer;
+import net.minecraft.server.v1_12_R1.NBTTagCompound;
+import net.minecraft.server.v1_12_R1.NibbleArray;
+import net.minecraft.server.v1_12_R1.PacketDataSerializer;
+import net.minecraft.server.v1_12_R1.PacketPlayOutMapChunk;
+import net.minecraft.server.v1_12_R1.PacketPlayOutMultiBlockChange;
+import net.minecraft.server.v1_12_R1.PlayerChunk;
+import net.minecraft.server.v1_12_R1.PlayerChunkMap;
+import net.minecraft.server.v1_12_R1.RegionFile;
+import net.minecraft.server.v1_12_R1.RegionFileCache;
+import net.minecraft.server.v1_12_R1.ServerNBTManager;
+import net.minecraft.server.v1_12_R1.TileEntity;
+import net.minecraft.server.v1_12_R1.WorldChunkManager;
+import net.minecraft.server.v1_12_R1.WorldData;
+import net.minecraft.server.v1_12_R1.WorldManager;
+import net.minecraft.server.v1_12_R1.WorldServer;
+import net.minecraft.server.v1_12_R1.WorldSettings;
+import net.minecraft.server.v1_12_R1.WorldType;
+import org.bukkit.Bukkit;
+import org.bukkit.Chunk;
+import org.bukkit.World;
+import org.bukkit.WorldCreator;
+import org.bukkit.block.Biome;
+import org.bukkit.craftbukkit.v1_12_R1.CraftChunk;
+import org.bukkit.craftbukkit.v1_12_R1.CraftServer;
+import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;
+import org.bukkit.craftbukkit.v1_12_R1.entity.CraftPlayer;
+import org.bukkit.event.world.WorldInitEvent;
+import org.bukkit.event.world.WorldLoadEvent;
+import org.bukkit.generator.ChunkGenerator;
+
+public class BukkitQueue_1_12 extends BukkitQueue_0 {
+
+ protected static IBlockData air;
+ protected static Field fieldBits;
+ protected static Field fieldPalette;
+ protected static Field fieldSize;
+ protected static Method getEntitySlices;
+ protected static Field fieldTickingBlockCount;
+ protected static Field fieldNonEmptyBlockCount;
+ protected static Field fieldSection;
+ protected static Field fieldBiomes;
+ protected static Field fieldChunkGenerator;
+ protected static Field fieldSeed;
+ protected static Field fieldBiomeCache;
+ protected static Field fieldBiomes2;
+ protected static Field fieldGenLayer1;
+ protected static Field fieldGenLayer2;
+ protected static MutableGenLayer genLayer;
+ protected static ChunkSection emptySection;
+
+ public static final IBlockData[] IBD_CACHE = new IBlockData[Character.MAX_VALUE + 1];
+
+ static {
+ try {
+ emptySection = new ChunkSection(0, true);
+ fieldSection = ChunkSection.class.getDeclaredField("blockIds");
+ fieldTickingBlockCount = ChunkSection.class.getDeclaredField("tickingBlockCount");
+ fieldNonEmptyBlockCount = ChunkSection.class.getDeclaredField("nonEmptyBlockCount");
+ fieldSection.setAccessible(true);
+ fieldTickingBlockCount.setAccessible(true);
+ fieldNonEmptyBlockCount.setAccessible(true);
+
+ fieldBiomes = ChunkProviderGenerate.class.getDeclaredField("D");
+ fieldBiomes.setAccessible(true);
+ fieldChunkGenerator = ChunkProviderServer.class.getDeclaredField("chunkGenerator");
+ fieldChunkGenerator.setAccessible(true);
+ fieldSeed = WorldData.class.getDeclaredField("e");
+ fieldSeed.setAccessible(true);
+ fieldBiomeCache = WorldChunkManager.class.getDeclaredField("d");
+ fieldBiomeCache.setAccessible(true);
+ fieldBiomes2 = WorldChunkManager.class.getDeclaredField("e");
+ fieldBiomes2.setAccessible(true);
+ fieldGenLayer1 = WorldChunkManager.class.getDeclaredField("b") ;
+ fieldGenLayer2 = WorldChunkManager.class.getDeclaredField("c") ;
+ fieldGenLayer1.setAccessible(true);
+ fieldGenLayer2.setAccessible(true);
+
+ fieldPalette = DataPaletteBlock.class.getDeclaredField("c");
+ fieldPalette.setAccessible(true);
+ fieldSize = DataPaletteBlock.class.getDeclaredField("e");
+ fieldSize.setAccessible(true);
+
+ Field fieldAir = DataPaletteBlock.class.getDeclaredField("a");
+ fieldAir.setAccessible(true);
+ air = (IBlockData) fieldAir.get(null);
+ fieldBits = DataPaletteBlock.class.getDeclaredField("b");
+ fieldBits.setAccessible(true);
+ getEntitySlices = net.minecraft.server.v1_12_R1.Chunk.class.getDeclaredMethod("getEntitySlices");
+ getEntitySlices.setAccessible(true);
+ setupAdapter(new FaweAdapter_1_12());
+ Fawe.debug("Using adapter: " + adapter);
+ Fawe.debug("=========================================");
+ for (int i = 0; i < IBD_CACHE.length; i++) {
+ try {
+ IBD_CACHE[i] = Block.getById(i >> 4).fromLegacyData(i & 0xF);
+ } catch (Throwable ignore) {}
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+
+ public BukkitQueue_1_12(final com.sk89q.worldedit.world.World world) {
+ super(world);
+ getImpWorld();
+ }
+
+ public BukkitQueue_1_12(final String world) {
+ super(world);
+ getImpWorld();
+ }
+
+ @Override
+ public ChunkSection[] getSections(net.minecraft.server.v1_12_R1.Chunk chunk) {
+ return chunk.getSections();
+ }
+
+ @Override
+ public net.minecraft.server.v1_12_R1.Chunk loadChunk(World world, int x, int z, boolean generate) {
+ ChunkProviderServer provider = ((CraftWorld) world).getHandle().getChunkProviderServer();
+ if (generate) {
+ return provider.getOrLoadChunkAt(x, z);
+ } else {
+ return provider.loadChunk(x, z);
+ }
+ }
+
+ @Override
+ public ChunkSection[] getCachedSections(World world, int cx, int cz) {
+ net.minecraft.server.v1_12_R1.Chunk chunk = ((CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz);
+ if (chunk != null) {
+ return chunk.getSections();
+ }
+ return null;
+ }
+
+ @Override
+ public net.minecraft.server.v1_12_R1.Chunk getCachedChunk(World world, int cx, int cz) {
+ return ((CraftWorld) world).getHandle().getChunkProviderServer().getChunkIfLoaded(cx, cz);
+ }
+
+ @Override
+ public ChunkSection getCachedSection(ChunkSection[] chunkSections, int cy) {
+ return chunkSections[cy];
+ }
+
+ @Override
+ public void saveChunk(net.minecraft.server.v1_12_R1.Chunk chunk) {
+ chunk.f(true); // Set Modified
+ chunk.mustSave = true;
+ }
+
+ @Override
+ public boolean regenerateChunk(World world, int x, int z, BaseBiome biome, Long seed) {
+ if (biome != null) {
+ try {
+ if (seed == null) {
+ seed = world.getSeed();
+ }
+ nmsWorld.worldData.getSeed();
+ boolean result;
+ ChunkProviderGenerate generator = new ChunkProviderGenerate(nmsWorld, seed, false, "");
+ Biome bukkitBiome = adapter.getBiome(biome.getId());
+ BiomeBase base = BiomeBase.getBiome(biome.getId());
+ fieldBiomes.set(generator, new BiomeBase[]{base});
+ boolean cold = base.getTemperature() <= 1;
+ net.minecraft.server.v1_12_R1.ChunkGenerator existingGenerator = nmsWorld.getChunkProviderServer().chunkGenerator;
+ long existingSeed = world.getSeed();
+ {
+ if (genLayer == null) genLayer = new MutableGenLayer(seed);
+ genLayer.set(biome.getId());
+ Object existingGenLayer1 = fieldGenLayer1.get(nmsWorld.getWorldChunkManager());
+ Object existingGenLayer2 = fieldGenLayer2.get(nmsWorld.getWorldChunkManager());
+ fieldGenLayer1.set(nmsWorld.getWorldChunkManager(), genLayer);
+ fieldGenLayer2.set(nmsWorld.getWorldChunkManager(), genLayer);
+
+ fieldSeed.set(nmsWorld.worldData, seed);
+
+ ReflectionUtils.setFailsafeFieldValue(fieldBiomeCache, this.nmsWorld.getWorldChunkManager(), new BiomeCache(this.nmsWorld.getWorldChunkManager()));
+
+ ReflectionUtils.setFailsafeFieldValue(fieldChunkGenerator, this.nmsWorld.getChunkProviderServer(), generator);
+
+ result = getWorld().regenerateChunk(x, z);
+
+ ReflectionUtils.setFailsafeFieldValue(fieldChunkGenerator, this.nmsWorld.getChunkProviderServer(), existingGenerator);
+
+ fieldSeed.set(nmsWorld.worldData, existingSeed);
+
+ fieldGenLayer1.set(nmsWorld.getWorldChunkManager(), existingGenLayer1);
+ fieldGenLayer2.set(nmsWorld.getWorldChunkManager(), existingGenLayer2);
+ }
+ return result;
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ }
+ return super.regenerateChunk(world, x, z, biome, seed);
+ }
+
+ @Override
+ public boolean setMCA(Runnable whileLocked, final RegionWrapper allowed, boolean unload) {
+ try {
+ TaskManager.IMP.sync(new RunnableVal
*/
@SuppressWarnings("deprecation")
-public class BaseBlock extends Block implements TileEntityBlock, Pattern {
+public class BaseBlock extends Block implements TileEntityBlock, Pattern, Serializable {
/**
* Indicates the highest possible block ID (inclusive) that can be used.
@@ -79,10 +83,10 @@ public class BaseBlock extends Block implements TileEntityBlock, Pattern {
// Instances of this class should be _as small as possible_ because there will
// be millions of instances of this object.
- private short id;
- private short data;
+ private transient short id;
+ private transient short data;
@Nullable
- private CompoundTag nbtData;
+ private transient CompoundTag nbtData;
/**
* Construct a block with the given ID and a data value of 0.
@@ -170,6 +174,11 @@ public class BaseBlock extends Block implements TileEntityBlock, Pattern {
internalSetId(id);
}
+ public void setCombined(int combined) {
+ setId(FaweCache.getId(combined));
+ setData(FaweCache.getData(combined));
+ }
+
/**
* Get the block's data value.
*
@@ -442,6 +451,21 @@ public class BaseBlock extends Block implements TileEntityBlock, Pattern {
return extent.setBlock(setPosition, this);
}
+ private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
+ stream.writeChar(getCombined());
+ stream.writeBoolean(nbtData != null);
+ if (nbtData != null) {
+ new NBTOutputStream(stream).writeTag(nbtData);
+ }
+ }
+
+ private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
+ setCombined(stream.readChar());
+ if (stream.readBoolean()) {
+ this.nbtData = (CompoundTag) new NBTInputStream(new DataInputStream(stream)).readTag();
+ }
+ }
+
public static Class inject() {
return BaseBlock.class;
}
diff --git a/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java
index fa3ac031..c9936ef2 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/BiomeCommands.java
@@ -63,7 +63,7 @@ import static com.sk89q.minecraft.util.commands.Logging.LogMode.REGION;
/**
* Implements biome-related commands such as "/biomelist".
*/
-@Command(aliases = "/biome", desc = "Change, list and inspect biomes")
+@Command(aliases = {}, desc = "Change, list and inspect biomes")
public class BiomeCommands {
private final WorldEdit worldEdit;
diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
index a14e11ed..8b6ac558 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/BrushCommands.java
@@ -26,6 +26,7 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.brush.BlendBall;
+import com.boydti.fawe.object.brush.BrushSettings;
import com.boydti.fawe.object.brush.CircleBrush;
import com.boydti.fawe.object.brush.CommandBrush;
import com.boydti.fawe.object.brush.CopyPastaBrush;
@@ -50,6 +51,7 @@ import com.boydti.fawe.object.brush.heightmap.ScalableHeightMap;
import com.boydti.fawe.object.mask.IdMask;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
+import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.EmptyClipboardException;
@@ -60,7 +62,7 @@ import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.blocks.BlockID;
-import com.sk89q.worldedit.command.tool.BrushTool;
+import com.sk89q.worldedit.command.tool.InvalidToolBindException;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.command.tool.brush.ButcherBrush;
import com.sk89q.worldedit.command.tool.brush.ClipboardBrush;
@@ -99,7 +101,7 @@ import javafx.scene.paint.Color;
/**
* Commands to set brush shape.
*/
-@Command(aliases = { "brush", "br" },
+@Command(aliases = { "brush", "br", "/b" },
desc = "Commands to build and draw from far away. [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/Brushes)"
)
public class BrushCommands extends MethodCommands {
@@ -108,6 +110,20 @@ public class BrushCommands extends MethodCommands {
super(worldEdit);
}
+ private BrushSettings get(CommandContext context) throws InvalidToolBindException {
+ BrushSettings bs = new BrushSettings();
+ bs.addPermissions(getPermissions());
+ CommandLocals locals = context.getLocals();
+ if (locals != null) {
+ String args = (String) locals.get("arguments");
+ if (args != null) {
+ bs.addSetting(BrushSettings.SettingType.BRUSH, args.substring(args.indexOf(' ') + 1));
+ }
+ }
+ return bs;
+ }
+
+
@Command(
aliases = { "blendball", "bb", "blend" },
usage = "[radius=5]",
@@ -118,12 +134,9 @@ public class BrushCommands extends MethodCommands {
max = 1
)
@CommandPermissions("worldedit.brush.blendball")
- public void blendBallBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException {
+ public BrushSettings blendBallBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
- tool.setBrush(new BlendBall(), "worldedit.brush.blendball", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_BLEND_BALL.f(radius));
+ return get(context).setBrush(new BlendBall()).setSize(radius);
}
@Command(
@@ -135,12 +148,9 @@ public class BrushCommands extends MethodCommands {
max = 1
)
@CommandPermissions("worldedit.brush.erode")
- public void erodeBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException {
+ public BrushSettings erodeBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
- tool.setBrush(new ErodeBrush(), "worldedit.brush.erode", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_ERODE.f(radius));
+ return get(context).setBrush(new ErodeBrush()).setSize(radius);
}
@Command(
@@ -152,12 +162,9 @@ public class BrushCommands extends MethodCommands {
max = 1
)
@CommandPermissions("worldedit.brush.pull")
- public void pullBrush(Player player, LocalSession session, @Optional("5") double radius) throws WorldEditException {
+ public BrushSettings pullBrush(Player player, LocalSession session, @Optional("5") double radius, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
- tool.setBrush(new RaiseBrush(), "worldedit.brush.pull", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_ERODE.f(radius));
+ return get(context).setBrush(new RaiseBrush()).setSize(radius);
}
@Command(
@@ -170,13 +177,9 @@ public class BrushCommands extends MethodCommands {
max = 2
)
@CommandPermissions("worldedit.brush.sphere")
- public void circleBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius) throws WorldEditException {
+ public BrushSettings circleBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
- tool.setFill(fill);
- tool.setBrush(new CircleBrush(player), "worldedit.brush.circle", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_CIRCLE.f(radius));
+ return get(context).setBrush(new CircleBrush(player)).setSize(radius).setFill(fill);
}
@Command(
@@ -190,14 +193,13 @@ public class BrushCommands extends MethodCommands {
max = 3
)
@CommandPermissions("worldedit.brush.recursive")
- public void recursiveBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("5") double radius, @Switch('d') boolean depthFirst) throws WorldEditException {
+ public BrushSettings recursiveBrush(Player player, LocalSession session, EditSession editSession, Pattern fill, @Optional("5") double radius, @Switch('d') boolean depthFirst, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
- tool.setBrush(new RecurseBrush(depthFirst), "worldedit.brush.recursive", player);
- tool.setMask(new IdMask(editSession));
- tool.setFill(fill);
- player.print(BBC.getPrefix() + BBC.BRUSH_RECURSIVE.f(radius));
+ return get(context)
+ .setBrush(new RecurseBrush(depthFirst))
+ .setSize(radius)
+ .setFill(fill)
+ .setMask(new IdMask(editSession));
}
@Command(
@@ -214,13 +216,12 @@ public class BrushCommands extends MethodCommands {
max = 2
)
@CommandPermissions("worldedit.brush.line")
- public void lineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Switch('h') boolean shell, @Switch('s') boolean select, @Switch('f') boolean flat) throws WorldEditException {
+ public BrushSettings lineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Switch('h') boolean shell, @Switch('s') boolean select, @Switch('f') boolean flat, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setFill(fill);
- tool.setSize(radius);
- tool.setBrush(new LineBrush(shell, select, flat), "worldedit.brush.line", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_LINE.f(radius));
+ return get(context)
+ .setBrush(new LineBrush(shell, select, flat))
+ .setSize(radius)
+ .setFill(fill);
}
@Command(
@@ -235,13 +236,13 @@ public class BrushCommands extends MethodCommands {
max = 2
)
@CommandPermissions("worldedit.brush.spline")
- public void splineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("25") double radius) throws WorldEditException {
+ public BrushSettings splineBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("25") double radius, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setFill(fill);
- tool.setSize(radius);
- tool.setBrush(new SplineBrush(player, session), "worldedit.brush.spline", player);
player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE.f(radius));
+ return get(context)
+ .setBrush(new SplineBrush(player, session))
+ .setSize(radius)
+ .setFill(fill);
}
// final double tension, final double bias, final double continuity, final double quality
@@ -256,13 +257,12 @@ public class BrushCommands extends MethodCommands {
max = 2
)
@CommandPermissions("worldedit.brush.surfacespline") // 0, 0, 0, 10, 0,
- public void surfaceSpline(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Optional("0") double tension, @Optional("0") double bias, @Optional("0") double continuity, @Optional("10") double quality) throws WorldEditException {
- worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setFill(fill);
- tool.setSize(radius);
- tool.setBrush(new SurfaceSpline(tension, bias, continuity, quality), "worldedit.brush.spline", player);
+ public BrushSettings surfaceSpline(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("0") double radius, @Optional("0") double tension, @Optional("0") double bias, @Optional("0") double continuity, @Optional("10") double quality, CommandContext context) throws WorldEditException {
player.print(BBC.getPrefix() + BBC.BRUSH_SPLINE.f(radius));
+ worldEdit.checkMaxBrushRadius(radius);return get(context)
+ .setBrush(new SurfaceSpline(tension, bias, continuity, quality))
+ .setSize(radius)
+ .setFill(fill);
}
@Command(
@@ -277,30 +277,28 @@ public class BrushCommands extends MethodCommands {
max = 2
)
@CommandPermissions("worldedit.brush.sphere")
- public void sphereBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("2") double radius, @Switch('h') boolean hollow) throws WorldEditException {
+ public BrushSettings sphereBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("2") double radius, @Switch('h') boolean hollow, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setFill(fill);
- tool.setSize(radius);
-
+ Brush brush;
if (hollow) {
- tool.setBrush(new HollowSphereBrush(), "worldedit.brush.sphere", player);
+ brush = new HollowSphereBrush();
} else {
- tool.setBrush(new SphereBrush(), "worldedit.brush.sphere", player);
+ brush = new SphereBrush();
}
if (fill instanceof BlockPattern) {
BaseBlock block = ((BlockPattern) fill).getBlock();
switch (block.getId()) {
case BlockID.SAND:
case BlockID.GRAVEL:
- player.print(BBC.getPrefix() + BBC.BRUSH_SPHERE.f(radius));
BBC.BRUSH_TRY_OTHER.send(player);
- return;
+ break;
}
}
- player.print(BBC.getPrefix() + BBC.BRUSH_SPHERE.f(radius));
- if (!FawePlayer.wrap(player).hasPermission("fawe.tips")) BBC.TIP_BRUSH_COMMAND.or(BBC.TIP_BRUSH_RELATIVE, BBC.TIP_BRUSH_TRANSFORM, BBC.TIP_BRUSH_MASK_SOURCE, BBC.TIP_BRUSH_MASK, BBC.TIP_BRUSH_COPY, BBC.TIP_BRUSH_HEIGHT, BBC.TIP_BRUSH_SPLINE).send(player);
+ return get(context)
+ .setBrush(brush)
+ .setSize(radius)
+ .setFill(fill);
}
@Command(
@@ -314,15 +312,13 @@ public class BrushCommands extends MethodCommands {
max = -1
)
@CommandPermissions("worldedit.brush.shatter")
- public void shatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") double radius, @Optional("10") int count) throws WorldEditException {
+ public BrushSettings shatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("10") double radius, @Optional("10") int count, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
-
- BrushTool tool = session.getBrushTool(player);
- tool.setFill(fill);
- tool.setSize(radius);
- tool.setMask(new ExistingBlockMask(editSession));
- tool.setBrush(new ShatterBrush(count), "worldedit.brush.shatter");
- player.print(BBC.getPrefix() + BBC.BRUSH_SHATTER.f(radius, count));
+ return get(context)
+ .setBrush(new ShatterBrush(count))
+ .setSize(radius)
+ .setFill(fill)
+ .setMask(new ExistingBlockMask(editSession));
}
@Command(
@@ -337,23 +333,22 @@ public class BrushCommands extends MethodCommands {
max = -1
)
@CommandPermissions("worldedit.brush.stencil")
- public void stencilBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('w') boolean onlyWhite, @Switch('r') boolean randomRotate) throws WorldEditException {
+ public BrushSettings stencilBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('w') boolean onlyWhite, @Switch('r') boolean randomRotate, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
InputStream stream = getHeightmapStream(filename);
- tool.setFill(fill);
- tool.setSize(radius);
HeightBrush brush;
try {
brush = new StencilBrush(stream, rotation, yscale, onlyWhite, filename.equalsIgnoreCase("#clipboard") ? session.getClipboard().getClipboard() : null);
} catch (EmptyClipboardException ignore) {
brush = new StencilBrush(stream, rotation, yscale, onlyWhite, null);
}
- tool.setBrush(brush, "worldedit.brush.height", player);
if (randomRotate) {
brush.setRandomRotate(true);
}
- player.print(BBC.getPrefix() + BBC.BRUSH_STENCIL.f(radius));
+ return get(context)
+ .setBrush(brush)
+ .setSize(radius)
+ .setFill(fill);
}
@Command(
@@ -368,13 +363,9 @@ public class BrushCommands extends MethodCommands {
max = -1
)
@CommandPermissions("worldedit.brush.surface")
- public void surfaceBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius) throws WorldEditException {
+ public BrushSettings surfaceBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setFill(fill);
- tool.setSize(radius);
- tool.setBrush(new SurfaceSphereBrush(), "worldedit.brush.surface");
- player.print(BBC.getPrefix() + BBC.BRUSH_SURFACE.f(radius));
+ return get(context).setBrush(new SurfaceSphereBrush()).setFill(fill).setSize(radius);
}
@Command(
@@ -390,19 +381,18 @@ public class BrushCommands extends MethodCommands {
max = 4
)
@CommandPermissions("worldedit.brush.scatter")
- public void scatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("5") double points, @Optional("1") double distance, @Switch('o') boolean overlay) throws WorldEditException {
+ public BrushSettings scatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("5") double points, @Optional("1") double distance, @Switch('o') boolean overlay, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setFill(fill);
- tool.setSize(radius);
Brush brush;
if (overlay) {
brush = new ScatterOverlayBrush((int) points, (int) distance);
} else {
brush = new ScatterBrush((int) points, (int) distance);
}
- tool.setBrush(brush, "worldedit.brush.scatter", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_SCATTER.f(radius, points));
+ return get(context)
+ .setBrush(brush)
+ .setSize(radius)
+ .setFill(fill);
}
@Command(
@@ -417,18 +407,18 @@ public class BrushCommands extends MethodCommands {
max = 4
)
@CommandPermissions("worldedit.brush.populateschematic")
- public void scatterSchemBrush(Player player, EditSession editSession, LocalSession session, Mask mask, String clipboard, @Optional("30") double radius, @Optional("50") double density, @Switch('r') boolean rotate) throws WorldEditException {
+ public BrushSettings scatterSchemBrush(Player player, EditSession editSession, LocalSession session, Mask mask, String clipboard, @Optional("30") double radius, @Optional("50") double density, @Switch('r') boolean rotate, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
+
+
try {
ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), clipboard, true);
if (clipboards == null) {
- return;
+ return null;
}
- Brush brush = new PopulateSchem(mask, clipboards, (int) density, rotate);
- tool.setBrush(brush, "worldedit.brush.populateschematic", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_POPULATE.f(radius, density));
+ return get(context)
+ .setBrush(new PopulateSchem(mask, clipboards, (int) density, rotate))
+ .setSize(radius);
} catch (IOException e) {
throw new RuntimeException(e);
}
@@ -445,10 +435,8 @@ public class BrushCommands extends MethodCommands {
max = 999
)
@CommandPermissions("worldedit.brush.layer")
- public void surfaceLayer(Player player, EditSession editSession, LocalSession session, double radius, CommandContext args) throws WorldEditException, InvalidUsageException {
+ public BrushSettings surfaceLayer(Player player, EditSession editSession, LocalSession session, double radius, CommandContext args, CommandContext context) throws WorldEditException, InvalidUsageException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
ParserContext parserContext = new ParserContext();
parserContext.setActor(player);
parserContext.setWorld(player.getWorld());
@@ -471,8 +459,9 @@ public class BrushCommands extends MethodCommands {
blocks.add(worldEdit.getBlockFactory().parseFromInput(arg, parserContext));
}
}
- tool.setBrush(new LayerBrush(blocks.toArray(new BaseBlock[blocks.size()])), "worldedit.brush.layer", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_LAYER.f(radius, args.getJoinedStrings(1)));
+ return get(context)
+ .setBrush(new LayerBrush(blocks.toArray(new BaseBlock[blocks.size()])))
+ .setSize(radius);
}
@Command(
@@ -487,13 +476,12 @@ public class BrushCommands extends MethodCommands {
max = 5
)
@CommandPermissions("worldedit.brush.splatter")
- public void splatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("1") double points, @Optional("5") double recursion, @Optional("true") boolean solid) throws WorldEditException {
+ public BrushSettings splatterBrush(Player player, EditSession editSession, LocalSession session, Pattern fill, @Optional("5") double radius, @Optional("1") double points, @Optional("5") double recursion, @Optional("true") boolean solid, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setFill(fill);
- tool.setSize(radius);
- tool.setBrush(new SplatterBrush((int) points, (int) recursion, solid), "worldedit.brush.splatter", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_SCATTER.f(radius, points));
+ return get(context)
+ .setBrush(new SplatterBrush((int) points, (int) recursion, solid))
+ .setSize(radius)
+ .setFill(fill);
}
@Command(
@@ -509,12 +497,11 @@ public class BrushCommands extends MethodCommands {
max = -1
)
@CommandPermissions("worldedit.brush.scattercommand")
- public void scatterCommandBrush(Player player, EditSession editSession, LocalSession session, double radius, double points, double distance, CommandContext args) throws WorldEditException {
+ public BrushSettings scatterCommandBrush(Player player, EditSession editSession, LocalSession session, double radius, double points, double distance, CommandContext args, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
- tool.setBrush(new ScatterCommand((int) points, (int) distance, args.getJoinedStrings(3)), "worldedit.brush.scattercommand", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_SCATTER.f(radius, points));
+ return get(context)
+ .setBrush(new ScatterCommand((int) points, (int) distance, args.getJoinedStrings(3)))
+ .setSize(radius);
}
@Command(
@@ -529,21 +516,20 @@ public class BrushCommands extends MethodCommands {
max = 3
)
@CommandPermissions("worldedit.brush.cylinder")
- public void cylinderBrush(Player player, EditSession editSession, LocalSession session, Pattern fill,
- @Optional("2") double radius, @Optional("1") int height, @Switch('h') boolean hollow) throws WorldEditException {
+ public BrushSettings cylinderBrush(Player player, EditSession editSession, LocalSession session, Pattern fill,
+ @Optional("2") double radius, @Optional("1") int height, @Switch('h') boolean hollow, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
worldEdit.checkMaxBrushRadius(height);
-
- BrushTool tool = session.getBrushTool(player);
- tool.setFill(fill);
- tool.setSize(radius);
+ BrushSettings settings = get(context);
if (hollow) {
- tool.setBrush(new HollowCylinderBrush(height), "worldedit.brush.cylinder", player);
+ settings.setBrush(new HollowCylinderBrush(height));
} else {
- tool.setBrush(new CylinderBrush(height), "worldedit.brush.cylinder", player);
+ settings.setBrush(new CylinderBrush(height));
}
- player.print(BBC.getPrefix() + BBC.BRUSH_SPHERE.f(radius, height));
+ settings.setSize(radius)
+ .setFill(fill);
+ return settings;
}
@Command(
@@ -558,7 +544,7 @@ public class BrushCommands extends MethodCommands {
"stood relative to the copied area when you copied it."
)
@CommandPermissions("worldedit.brush.clipboard")
- public void clipboardBrush(Player player, LocalSession session, @Switch('a') boolean ignoreAir, @Switch('p') boolean usingOrigin) throws WorldEditException {
+ public BrushSettings clipboardBrush(Player player, LocalSession session, @Switch('a') boolean ignoreAir, @Switch('p') boolean usingOrigin, CommandContext context) throws WorldEditException {
ClipboardHolder holder = session.getClipboard();
Clipboard clipboard = holder.getClipboard();
@@ -567,10 +553,7 @@ public class BrushCommands extends MethodCommands {
worldEdit.checkMaxBrushRadius(size.getBlockX());
worldEdit.checkMaxBrushRadius(size.getBlockY());
worldEdit.checkMaxBrushRadius(size.getBlockZ());
-
- BrushTool tool = session.getBrushTool(player);
- tool.setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin), "worldedit.brush.clipboard", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_CLIPBOARD.s());
+ return get(context).setBrush(new ClipboardBrush(holder, ignoreAir, usingOrigin));
}
@Command(
@@ -585,20 +568,19 @@ public class BrushCommands extends MethodCommands {
max = 2
)
@CommandPermissions("worldedit.brush.smooth")
- public void smoothBrush(Player player, LocalSession session, EditSession editSession,
+ public BrushSettings smoothBrush(Player player, LocalSession session, EditSession editSession,
@Optional("2") double radius, @Optional("4") int iterations, @Switch('n')
- boolean naturalBlocksOnly) throws WorldEditException {
+ boolean naturalBlocksOnly, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
FawePlayer fp = FawePlayer.wrap(player);
FaweLimit limit = Settings.IMP.getLimit(fp);
iterations = Math.min(limit.MAX_ITERATIONS, iterations);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
- tool.setBrush(new SmoothBrush(iterations, naturalBlocksOnly), "worldedit.brush.smooth", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_SMOOTH.f(radius, iterations, (naturalBlocksOnly ? "natural blocks only" : "any block")));
+ return get(context)
+ .setBrush(new SmoothBrush(iterations, naturalBlocksOnly))
+ .setSize(radius);
}
@Command(
@@ -609,17 +591,15 @@ public class BrushCommands extends MethodCommands {
max = 1
)
@CommandPermissions("worldedit.brush.ex")
- public void extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius) throws WorldEditException {
+ public BrushSettings extinguishBrush(Player player, LocalSession session, EditSession editSession, @Optional("5") double radius, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
Pattern fill = new BlockPattern(new BaseBlock(0));
- tool.setFill(fill);
- tool.setSize(radius);
- tool.setMask(new BlockMask(editSession, new BaseBlock(BlockID.FIRE)));
- tool.setBrush(new SphereBrush(), "worldedit.brush.ex", player);
- BBC.BRUSH_EXTINGUISHER.send(player, radius);
- player.print(BBC.getPrefix() + BBC.BRUSH_EXTINGUISHER.f(radius));
+ return get(context)
+ .setBrush(new SphereBrush())
+ .setSize(radius)
+ .setFill(fill)
+ .setMask(new BlockMask(editSession, new BaseBlock(BlockID.FIRE)));
}
@Command(
@@ -635,13 +615,12 @@ public class BrushCommands extends MethodCommands {
max = 1
)
@CommandPermissions("worldedit.brush.gravity")
- public void gravityBrush(Player player, LocalSession session, @Optional("5") double radius, @Switch('h') boolean fromMaxY) throws WorldEditException {
+ public BrushSettings gravityBrush(Player player, LocalSession session, @Optional("5") double radius, @Switch('h') boolean fromMaxY, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
- tool.setBrush(new GravityBrush(fromMaxY, tool), "worldedit.brush.gravity", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_GRAVITY.f(radius));
+ return get(context)
+ .setBrush(new GravityBrush(fromMaxY))
+ .setSize(radius);
}
@Command(
@@ -660,8 +639,8 @@ public class BrushCommands extends MethodCommands {
max = 4
)
@CommandPermissions("worldedit.brush.height")
- public void heightBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth) throws WorldEditException {
- terrainBrush(player, session, radius, filename, rotation, yscale, false, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE);
+ public BrushSettings heightBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException {
+ return terrainBrush(player, session, radius, filename, rotation, yscale, false, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE, context);
}
@Command(
@@ -678,8 +657,8 @@ public class BrushCommands extends MethodCommands {
max = 4
)
@CommandPermissions("worldedit.brush.height")
- public void cliffBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth) throws WorldEditException {
- terrainBrush(player, session, radius, filename, rotation, yscale, true, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CYLINDER);
+ public BrushSettings cliffBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException {
+ return terrainBrush(player, session, radius, filename, rotation, yscale, true, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CYLINDER, context);
}
@Command(
@@ -695,8 +674,8 @@ public class BrushCommands extends MethodCommands {
max = 4
)
@CommandPermissions("worldedit.brush.height")
- public void flattenBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth) throws WorldEditException {
- terrainBrush(player, session, radius, filename, rotation, yscale, true, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE);
+ public BrushSettings flattenBrush(Player player, LocalSession session, @Optional("5") double radius, @Optional("") final String filename, @Optional("0") final int rotation, @Optional("1") final double yscale, @Switch('r') boolean randomRotate, @Switch('l') boolean layers, @Switch('s') boolean dontSmooth, CommandContext context) throws WorldEditException {
+ return terrainBrush(player, session, radius, filename, rotation, yscale, true, randomRotate, layers, !dontSmooth, ScalableHeightMap.Shape.CONE, context);
}
private InputStream getHeightmapStream(String filename) {
@@ -730,11 +709,9 @@ public class BrushCommands extends MethodCommands {
return null;
}
- private void terrainBrush(Player player, LocalSession session, double radius, String filename, int rotation, double yscale, boolean flat, boolean randomRotate, boolean layers, boolean smooth, ScalableHeightMap.Shape shape) throws WorldEditException {
+ private BrushSettings terrainBrush(Player player, LocalSession session, double radius, String filename, int rotation, double yscale, boolean flat, boolean randomRotate, boolean layers, boolean smooth, ScalableHeightMap.Shape shape, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
InputStream stream = getHeightmapStream(filename);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
HeightBrush brush;
if (flat) {
try {
@@ -749,11 +726,12 @@ public class BrushCommands extends MethodCommands {
brush = new HeightBrush(stream, rotation, yscale, layers, smooth, null);
}
}
- tool.setBrush(brush, "worldedit.brush.height", player);
if (randomRotate) {
brush.setRandomRotate(true);
}
- player.print(BBC.getPrefix() + BBC.BRUSH_HEIGHT.f(radius));
+ return get(context)
+ .setBrush(brush)
+ .setSize(radius);
}
@@ -771,12 +749,12 @@ public class BrushCommands extends MethodCommands {
max = 1
)
@CommandPermissions("worldedit.brush.copy")
- public void copy(Player player, LocalSession session, @Optional("5") double radius, @Switch('r') boolean rotate) throws WorldEditException {
+ public BrushSettings copy(Player player, LocalSession session, @Optional("5") double radius, @Switch('r') boolean rotate, CommandContext context) throws WorldEditException {
worldEdit.checkMaxBrushRadius(radius);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
- tool.setBrush(new CopyPastaBrush(player, session, rotate), "worldedit.brush.copy", player);
player.print(BBC.getPrefix() + BBC.BRUSH_COPY.f(radius));
+ return get(context)
+ .setBrush(new CopyPastaBrush(player, session, rotate))
+ .setSize(radius);
}
@Command(
@@ -792,12 +770,11 @@ public class BrushCommands extends MethodCommands {
max = 99
)
@CommandPermissions("worldedit.brush.command")
- public void command(Player player, LocalSession session, double radius, CommandContext args) throws WorldEditException {
- BrushTool tool = session.getBrushTool(player);
+ public BrushSettings command(Player player, LocalSession session, double radius, CommandContext args, CommandContext context) throws WorldEditException {
String cmd = args.getJoinedStrings(1);
- tool.setBrush(new CommandBrush(cmd, radius), "worldedit.brush.copy", player);
- tool.setSize(radius);
- player.print(BBC.getPrefix() + BBC.BRUSH_COMMAND.f(cmd));
+ return get(context)
+ .setBrush(new CommandBrush(cmd, radius))
+ .setSize(radius);
}
@Command(
@@ -820,7 +797,7 @@ public class BrushCommands extends MethodCommands {
max = 1
)
@CommandPermissions("worldedit.brush.butcher")
- public void butcherBrush(Player player, LocalSession session, CommandContext args) throws WorldEditException {
+ public BrushSettings butcherBrush(Player player, LocalSession session, CommandContext args, CommandContext context) throws WorldEditException {
LocalConfiguration config = worldEdit.getConfiguration();
double radius = args.argsLength() > 0 ? args.getDouble(0) : 5;
@@ -833,16 +810,15 @@ public class BrushCommands extends MethodCommands {
}
if (radius > maxRadius && maxRadius != -1) {
BBC.TOOL_RADIUS_ERROR.send(player, maxRadius);
- return;
+ return null;
}
CreatureButcher flags = new CreatureButcher(player);
flags.fromCommand(args);
- BrushTool tool = session.getBrushTool(player);
- tool.setSize(radius);
- tool.setBrush(new ButcherBrush(flags), "worldedit.brush.butcher", player);
- player.print(BBC.getPrefix() + BBC.BRUSH_BUTCHER.f(radius));
+ return get(context)
+ .setBrush(new ButcherBrush(flags))
+ .setSize(radius);
}
public static Class> inject() {
diff --git a/core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java b/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java
similarity index 57%
rename from core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java
rename to core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java
index a4c780db..2d69356a 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/ToolUtilCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/BrushOptionsCommands.java
@@ -3,52 +3,150 @@ package com.sk89q.worldedit.command;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweAPI;
import com.boydti.fawe.config.BBC;
+import com.boydti.fawe.object.brush.BrushSettings;
import com.boydti.fawe.object.brush.TargetMode;
-import com.boydti.fawe.object.brush.scroll.ScrollClipboard;
-import com.boydti.fawe.object.brush.scroll.ScrollMask;
-import com.boydti.fawe.object.brush.scroll.ScrollPattern;
-import com.boydti.fawe.object.brush.scroll.ScrollRange;
-import com.boydti.fawe.object.brush.scroll.ScrollSize;
-import com.boydti.fawe.object.brush.scroll.ScrollTarget;
+import com.boydti.fawe.object.brush.scroll.ScrollAction;
import com.boydti.fawe.object.brush.visualization.VisualMode;
import com.boydti.fawe.object.extent.ResettableExtent;
+import com.boydti.fawe.object.io.PGZIPOutputStream;
+import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.EditSession;
-import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.tool.BrushTool;
-import com.sk89q.worldedit.command.tool.Tool;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.event.platform.CommandEvent;
import com.sk89q.worldedit.extension.factory.DefaultMaskParser;
import com.sk89q.worldedit.extension.factory.DefaultTransformParser;
import com.sk89q.worldedit.extension.factory.HashTagPatternParser;
import com.sk89q.worldedit.extension.input.ParserContext;
+import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.CommandManager;
-import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.function.mask.Mask;
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.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.util.zip.GZIPInputStream;
/**
* Tool commands.
*/
@Command(aliases = {}, desc = "Tool commands")
-public class ToolUtilCommands extends MethodCommands {
+public class BrushOptionsCommands extends MethodCommands {
- public ToolUtilCommands(WorldEdit we) {
+ public BrushOptionsCommands(WorldEdit we) {
super(we);
}
+ @Command(
+ aliases = { "/savebrush" },
+ usage = "[name]",
+ desc = "Save your current brush",
+ min = 1
+ )
+ @CommandPermissions("worldedit.brush.save")
+ public void saveBrush(Player player, LocalSession session, String name) throws WorldEditException, IOException {
+ BrushTool tool = session.getBrushTool(player);
+ if (tool != null) {
+ name = FileSystems.getDefault().getPath(name).getFileName().toString();
+ File folder = MainUtil.getFile(Fawe.imp().getDirectory(), "brushes");
+ name = name.endsWith(".jsgz") ? name : name + ".jsgz";
+ File file = new File(folder, player.getUniqueId() + File.separator + name);
+ File parent = file.getParentFile();
+ if (!parent.exists()) {
+ parent.mkdirs();
+ }
+ file.createNewFile();
+ try (DataOutputStream out = new DataOutputStream(new PGZIPOutputStream(new FileOutputStream(file)))) {
+ out.writeUTF(tool.toString());
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ BBC.SCHEMATIC_SAVED.send(player, name);
+ } else {
+ BBC.BRUSH_NONE.send(player);
+ }
+ }
+
+ @Command(
+ aliases = { "/loadbrush" },
+ desc = "load a brush",
+ usage = "[name]",
+ min = 1
+ )
+ @CommandPermissions("worldedit.brush.load")
+ public void loadBrush(Player player, LocalSession session, String name) throws WorldEditException, IOException {
+ name = FileSystems.getDefault().getPath(name).getFileName().toString();
+ File folder = MainUtil.getFile(Fawe.imp().getDirectory(), "brushes");
+ name = name.endsWith(".jsgz") ? name : name + ".jsgz";
+ File file = new File(folder, player.getUniqueId() + File.separator + name);
+ if (!file.exists()) {
+ file = new File(folder, name);
+ }
+ if (!file.exists()) {
+ File[] files = folder.listFiles(new FileFilter() {
+ @Override
+ public boolean accept(File pathname) {
+ return false;
+ }
+ });
+ BBC.BRUSH_NOT_FOUND.send(player, name);
+ return;
+ }
+ try (DataInputStream in = new DataInputStream(new GZIPInputStream(new FileInputStream(file)))) {
+ String json = in.readUTF();
+ BrushTool tool = BrushTool.fromString(player, session, json);
+ BaseBlock item = player.getBlockInHand();
+ session.setTool(item.getId(), item.getData(), tool, player);
+ BBC.BRUSH_EQUIPPED.send(player, name);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ BBC.BRUSH_INCOMPATIBLE.send(player);
+ }
+ }
+
+ @Command(
+ aliases = {"/listbrush"},
+ desc = "List saved brushes",
+ usage = "[mine|] [page=1]",
+ min = 0,
+ max = -1,
+ flags = "dnp",
+ help = "List all brushes in the brush directory\n" +
+ " -p prints the requested page\n"
+ )
+ @CommandPermissions("worldedit.brush.list")
+ public void list(Actor actor, CommandContext args, @Switch('p') @Optional("1") int page) throws WorldEditException {
+ File dir = MainUtil.getFile(Fawe.imp().getDirectory(), "brushes");
+ UtilityCommands.list(dir, actor, args, page, null, true);
+ }
+
+ @Command(
+ aliases = { "none", "/none" },
+ usage = "",
+ desc = "Unbind a bound tool from your current item",
+ min = 0,
+ max = 0
+ )
+ public void none(Player player, LocalSession session, CommandContext args) throws WorldEditException {
+ session.setTool(null, player);
+ BBC.TOOL_NONE.send(player);
+ }
+
@Command(
aliases = { "/", "," },
usage = "[on|off]",
@@ -219,77 +317,22 @@ public class ToolUtilCommands extends MethodCommands {
min = 1,
max = -1
)
- public void scroll(Player player, EditSession editSession, LocalSession session, CommandContext args) throws WorldEditException {
- BrushTool tool = session.getBrushTool(player, false);
- if (tool == null) {
+ public void scroll(Player player, EditSession editSession, LocalSession session, @Optional @Switch('h') boolean offHand, CommandContext args) throws WorldEditException {
+ BrushTool bt = session.getBrushTool(player, false);
+ if (bt == null) {
BBC.BRUSH_NONE.send(player);
return;
}
- ParserContext parserContext = new ParserContext();
- parserContext.setActor(player);
- parserContext.setWorld(player.getWorld());
- parserContext.setSession(session);
- parserContext.setExtent(editSession);
- final LocalConfiguration config = this.worldEdit.getConfiguration();
- switch (args.getString(0).toLowerCase()) {
- case "none":
- tool.setScrollAction(null);
- break;
- case "clipboard":
- if (args.argsLength() != 2) {
- BBC.COMMAND_SYNTAX.send(player, "clipboard [file]");
- return;
- }
- String filename = args.getString(1);
- try {
- ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), filename, true);
- if (clipboards == null) {
- return;
- }
- tool.setScrollAction(new ScrollClipboard(tool, session, clipboards));
- break;
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- case "mask":
- if (args.argsLength() < 2) {
- BBC.COMMAND_SYNTAX.send(player, "mask [mask 1] [mask 2] [mask 3]...");
- return;
- }
- Mask[] masks = new Mask[args.argsLength() - 1];
- for (int i = 1; i < args.argsLength(); i++) {
- String arg = args.getString(i);
- masks[i - 1] = worldEdit.getMaskFactory().parseFromInput(arg, parserContext);
- }
- tool.setScrollAction(new ScrollMask(tool, masks));
- break;
- case "pattern":
- if (args.argsLength() < 2) {
- BBC.COMMAND_SYNTAX.send(player, "pattern [pattern 1] [pattern 2] [pattern 3]...");
- return;
- }
- Pattern[] patterns = new Pattern[args.argsLength() - 1];
- for (int i = 1; i < args.argsLength(); i++) {
- String arg = args.getString(i);
- patterns[i - 1] = worldEdit.getPatternFactory().parseFromInput(arg, parserContext);
- }
- tool.setScrollAction(new ScrollPattern(tool, patterns));
- break;
- case "range":
- tool.setScrollAction(new ScrollRange(tool));
- break;
- case "size":
- tool.setScrollAction(new ScrollSize(tool));
- break;
- case "target":
- tool.setScrollAction(new ScrollTarget(tool));
- break;
- default:
- BBC.COMMAND_SYNTAX.send(player, "[none|clipboard|mask|pattern|range|size|visual|target]");
- return;
-
+ BrushSettings settings = offHand ? bt.getOffHand() : bt.getContext();
+ ScrollAction action = ScrollAction.fromArguments(bt, player, session, args.getJoinedStrings(0), true);
+ settings.setScrollAction(action);
+ if (args.getString(0).equalsIgnoreCase("none")) {
+ BBC.BRUSH_SCROLL_ACTION_UNSET.send(player);
+ } else if (action != null) {
+ String full = args.getJoinedStrings(0);
+ settings.addSetting(BrushSettings.SettingType.SCROLL_ACTION, full);
+ BBC.BRUSH_SCROLL_ACTION_SET.send(player, full);
}
- BBC.BRUSH_SCROLL_ACTION_SET.send(player, args.getJoinedStrings(0));
}
@Command(
@@ -300,36 +343,27 @@ public class ToolUtilCommands extends MethodCommands {
max = -1
)
@CommandPermissions("worldedit.brush.options.mask")
- public void mask(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context, @Switch('h') boolean offHand) throws WorldEditException {
- Tool tool = session.getTool(player);
+ public void mask(Player player, LocalSession session, EditSession editSession, @Optional @Switch('h') boolean offHand, CommandContext context) throws WorldEditException {
+ BrushTool tool = session.getBrushTool(player, false);
if (tool == null) {
player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f());
return;
}
- Mask mask;
- if (context == null || context.argsLength() == 0) {
- mask = null;
- } else {
- ParserContext parserContext = new ParserContext();
- parserContext.setActor(player);
- parserContext.setWorld(player.getWorld());
- parserContext.setSession(session);
- parserContext.setExtent(editSession);
- mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext);
- }
- if (tool instanceof BrushTool) {
- BrushTool bt = (BrushTool) tool;
- if (offHand) {
- bt.getSecondary().mask = mask;
- } else {
- ((BrushTool) tool).setMask(mask);
- }
- }
- if (mask == null) {
+ if (context.argsLength() == 0) {
BBC.BRUSH_MASK_DISABLED.send(player);
- } else {
- BBC.BRUSH_MASK.send(player);
+ tool.setMask(null);
+ return;
}
+ ParserContext parserContext = new ParserContext();
+ parserContext.setActor(player);
+ parserContext.setWorld(player.getWorld());
+ parserContext.setSession(session);
+ parserContext.setExtent(editSession);
+ Mask mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext);
+ BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext();
+ settings.addSetting(BrushSettings.SettingType.MASK, context.getString(context.argsLength() - 1));
+ settings.setMask(mask);
+ BBC.BRUSH_MASK.send(player);
}
@Command(
@@ -341,36 +375,27 @@ public class ToolUtilCommands extends MethodCommands {
max = -1
)
@CommandPermissions("worldedit.brush.options.mask")
- public void smask(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context, @Switch('h') boolean offHand) throws WorldEditException {
- Tool tool = session.getTool(player);
+ public void smask(Player player, LocalSession session, EditSession editSession, @Optional @Switch('h') boolean offHand, CommandContext context) throws WorldEditException {
+ BrushTool tool = session.getBrushTool(player, false);
if (tool == null) {
player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f());
return;
}
- Mask mask;
- if (context == null || context.argsLength() == 0) {
- mask = null;
- } else {
- ParserContext parserContext = new ParserContext();
- parserContext.setActor(player);
- parserContext.setWorld(player.getWorld());
- parserContext.setSession(session);
- parserContext.setExtent(editSession);
- mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext);
- }
- if (tool instanceof BrushTool) {
- BrushTool bt = (BrushTool) tool;
- if (offHand) {
- bt.getSecondary().sourceMask = mask;
- } else {
- ((BrushTool) tool).setSourceMask(mask);
- }
- }
- if (mask == null) {
+ if (context.argsLength() == 0) {
BBC.BRUSH_SOURCE_MASK_DISABLED.send(player);
- } else {
- BBC.BRUSH_SOURCE_MASK.send(player);
+ tool.setSourceMask(null);
+ return;
}
+ ParserContext parserContext = new ParserContext();
+ parserContext.setActor(player);
+ parserContext.setWorld(player.getWorld());
+ parserContext.setSession(session);
+ parserContext.setExtent(editSession);
+ Mask mask = worldEdit.getMaskFactory().parseFromInput(context.getJoinedStrings(0), parserContext);
+ BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext();
+ settings.addSetting(BrushSettings.SettingType.SOURCE_MASK, context.getString(context.argsLength() - 1));
+ settings.setSourceMask(mask);
+ BBC.BRUSH_SOURCE_MASK.send(player);
}
@Command(
@@ -381,35 +406,27 @@ public class ToolUtilCommands extends MethodCommands {
max = -1
)
@CommandPermissions("worldedit.brush.options.transform")
- public void transform(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context, @Switch('h') boolean offHand) throws WorldEditException {
- Tool tool = session.getTool(player);
+ public void transform(Player player, LocalSession session, EditSession editSession, @Optional @Switch('h') boolean offHand, CommandContext context) throws WorldEditException {
+ BrushTool tool = session.getBrushTool(player, false);
if (tool == null) {
+ player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f());
return;
}
- ResettableExtent transform;
- if (context == null || context.argsLength() == 0) {
- transform = null;
- } else {
- ParserContext parserContext = new ParserContext();
- parserContext.setActor(player);
- parserContext.setWorld(player.getWorld());
- parserContext.setSession(session);
- parserContext.setExtent(editSession);
- transform = Fawe.get().getTransformParser().parseFromInput(context.getJoinedStrings(0), parserContext);
- }
- if (tool instanceof BrushTool) {
- BrushTool bt = (BrushTool) tool;
- if (offHand) {
- bt.getSecondary().transform = transform;
- } else {
- ((BrushTool) tool).setTransform(transform);
- }
- }
- if (transform == null) {
+ if (context.argsLength() == 0) {
BBC.BRUSH_TRANSFORM_DISABLED.send(player);
- } else {
- BBC.BRUSH_TRANSFORM.send(player);
+ tool.setTransform(null);
+ return;
}
+ ParserContext parserContext = new ParserContext();
+ parserContext.setActor(player);
+ parserContext.setWorld(player.getWorld());
+ parserContext.setSession(session);
+ parserContext.setExtent(editSession);
+ ResettableExtent transform = Fawe.get().getTransformParser().parseFromInput(context.getJoinedStrings(0), parserContext);
+ BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext();
+ settings.addSetting(BrushSettings.SettingType.TRANSFORM, context.getString(context.argsLength() - 1));
+ settings.setTransform(transform);
+ BBC.BRUSH_TRANSFORM.send(player);
}
@Command(
@@ -420,16 +437,20 @@ public class ToolUtilCommands extends MethodCommands {
max = 1
)
@CommandPermissions("worldedit.brush.options.material")
- public void material(Player player, EditSession editSession, LocalSession session, Pattern pattern, @Switch('h') boolean offHand) throws WorldEditException {
- Tool tool = session.getTool(player);
- if (tool instanceof BrushTool) {
- BrushTool bt = (BrushTool) tool;
- if (offHand) {
- bt.getSecondary().material = pattern;
- } else {
- ((BrushTool) tool).setFill(pattern);
- }
+ public void material(Player player, EditSession editSession, LocalSession session, Pattern pattern, @Switch('h') boolean offHand, CommandContext context) throws WorldEditException {
+ BrushTool tool = session.getBrushTool(player, false);
+ if (tool == null) {
+ player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f());
+ return;
}
+ if (context.argsLength() == 0) {
+ BBC.BRUSH_TRANSFORM_DISABLED.send(player);
+ tool.setFill(null);
+ return;
+ }
+ BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext();
+ settings.setFill(pattern);
+ settings.addSetting(BrushSettings.SettingType.FILL, context.getString(context.argsLength() - 1));
BBC.BRUSH_MATERIAL.send(player);
}
@@ -443,11 +464,12 @@ public class ToolUtilCommands extends MethodCommands {
@CommandPermissions("worldedit.brush.options.range")
public void range(Player player, LocalSession session, CommandContext args) throws WorldEditException {
int range = Math.max(0, Math.min(256, args.getInteger(0)));
- Tool tool = session.getTool(player);
- if (tool instanceof BrushTool) {
- BrushTool bt = (BrushTool) tool;
- ((BrushTool) tool).setRange(range);
+ BrushTool tool = session.getBrushTool(player, false);
+ if (tool == null) {
+ player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f());
+ return;
}
+ tool.setRange(range);
BBC.BRUSH_RANGE.send(player);
}
@@ -460,23 +482,19 @@ public class ToolUtilCommands extends MethodCommands {
)
@CommandPermissions("worldedit.brush.options.size")
public void size(Player player, LocalSession session, CommandContext args, @Switch('h') boolean offHand) throws WorldEditException {
-
int radius = args.getInteger(0);
worldEdit.checkMaxBrushRadius(radius);
-
- Tool tool = session.getTool(player);
- if (tool instanceof BrushTool) {
- BrushTool bt = (BrushTool) tool;
- if (offHand) {
- bt.getSecondary().size = radius;
- } else {
- ((BrushTool) tool).setSize(radius);
- }
+ BrushTool tool = session.getBrushTool(player, false);
+ if (tool == null) {
+ player.print(BBC.getPrefix() + BBC.BRUSH_NONE.f());
+ return;
}
+ BrushSettings settings = offHand ? tool.getOffHand() : tool.getContext();
+ settings.setSize(radius);
BBC.BRUSH_SIZE.send(player);
}
public static Class> inject() {
- return ToolUtilCommands.class;
+ return BrushOptionsCommands.class;
}
}
\ No newline at end of file
diff --git a/core/src/main/java/com/sk89q/worldedit/command/BrushProcessor.java b/core/src/main/java/com/sk89q/worldedit/command/BrushProcessor.java
new file mode 100644
index 00000000..24702ce5
--- /dev/null
+++ b/core/src/main/java/com/sk89q/worldedit/command/BrushProcessor.java
@@ -0,0 +1,32 @@
+package com.sk89q.worldedit.command;
+
+import com.boydti.fawe.config.BBC;
+import com.boydti.fawe.object.brush.BrushSettings;
+import com.plotsquared.general.commands.Command;
+import com.sk89q.minecraft.util.commands.CommandLocals;
+import com.sk89q.worldedit.LocalSession;
+import com.sk89q.worldedit.WorldEdit;
+import com.sk89q.worldedit.WorldEditException;
+import com.sk89q.worldedit.command.tool.BrushTool;
+import com.sk89q.worldedit.entity.Player;
+import com.sk89q.worldedit.extension.platform.Actor;
+import com.sk89q.worldedit.util.command.CallableProcessor;
+
+public class BrushProcessor implements CallableProcessor {
+ private final WorldEdit worldEdit;
+
+ public BrushProcessor(WorldEdit worldEdit) {
+ this.worldEdit = worldEdit;
+ }
+
+ @Override
+ public BrushSettings process(CommandLocals locals, BrushSettings settings) throws Command.CommandException, WorldEditException {
+ Actor actor = locals.get(Actor.class);
+ LocalSession session = worldEdit.getSessionManager().get(actor);
+ BrushTool tool = session.getBrushTool((Player) actor);
+ tool.setPrimary(settings);
+ tool.setSecondary(settings);
+ BBC.BRUSH_EQUIPPED.send(actor, ((String) locals.get("arguments")).split(" ")[1]);
+ return null;
+ }
+}
diff --git a/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java b/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
index 57f7c781..2457a79c 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/GenerationCommands.java
@@ -114,7 +114,7 @@ public class GenerationCommands {
}
@Command(
- aliases = { "/image" },
+ aliases = { "/image", "/img" },
desc = "Generate an image",
usage = " [randomize=true] [complexity=100]",
min = 1,
diff --git a/core/src/main/java/com/sk89q/worldedit/command/MethodCommands.java b/core/src/main/java/com/sk89q/worldedit/command/MethodCommands.java
index ee08a2c9..1976e2ce 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/MethodCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/MethodCommands.java
@@ -2,6 +2,9 @@ package com.sk89q.worldedit.command;
import com.boydti.fawe.config.Commands;
import com.sk89q.minecraft.util.commands.Command;
+import com.sk89q.minecraft.util.commands.CommandContext;
+import com.sk89q.minecraft.util.commands.CommandLocals;
+import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.Dispatcher;
@@ -67,4 +70,30 @@ public class MethodCommands {
}
return null;
}
-}
+
+ public String getArguments(CommandContext context) {
+ CommandLocals locals = context.getLocals();
+ if (locals != null) {
+ return (String) locals.get("arguments");
+ }
+ return null;
+ }
+
+ public String[] getPermissions() {
+ try {
+ StackTraceElement[] stack = new Exception().getStackTrace();
+ for (StackTraceElement elem : stack) {
+ Class> clazz = Class.forName(elem.getClassName());
+ for (Method method : clazz.getMethods()) {
+ if (method.getName().equals(elem.getMethodName())) {
+ CommandPermissions perm = method.getAnnotation(CommandPermissions.class);
+ if (perm != null) return perm.value();
+ }
+ }
+ }
+ } catch (Throwable e) {
+ e.printStackTrace();
+ }
+ return new String[0];
+ }
+}
\ No newline at end of file
diff --git a/core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java b/core/src/main/java/com/sk89q/worldedit/command/OptionsCommands.java
similarity index 97%
rename from core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java
rename to core/src/main/java/com/sk89q/worldedit/command/OptionsCommands.java
index 4c2a897c..5665efdf 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/GeneralCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/OptionsCommands.java
@@ -25,7 +25,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
* General WorldEdit commands.
*/
@Command(aliases = {}, desc = "Player toggles, settings and item info")
-public class GeneralCommands {
+public class OptionsCommands {
private final WorldEdit worldEdit;
@@ -34,7 +34,7 @@ public class GeneralCommands {
*
* @param worldEdit reference to WorldEdit
*/
- public GeneralCommands(WorldEdit worldEdit) {
+ public OptionsCommands(WorldEdit worldEdit) {
checkNotNull(worldEdit);
this.worldEdit = worldEdit;
}
@@ -117,7 +117,7 @@ public class GeneralCommands {
)
@CommandPermissions("worldedit.global-mask")
public void gsmask(Player player, LocalSession session, EditSession editSession, @Optional CommandContext context) throws WorldEditException {
- if (context == null || context.argsLength() == 0) {
+ if (context.argsLength() == 0) {
session.setSourceMask((Mask) null);
BBC.SOURCE_MASK_DISABLED.send(player);
} else {
@@ -141,7 +141,7 @@ public class GeneralCommands {
)
@CommandPermissions("worldedit.global-trasnform")
public void gtransform(Player player, EditSession editSession, LocalSession session, @Optional CommandContext context) throws WorldEditException {
- if (context == null || context.argsLength() == 0) {
+ if (context.argsLength() == 0) {
session.setTransform(null);
BBC.TRANSFORM_DISABLED.send(player);
} else {
@@ -253,6 +253,6 @@ public class GeneralCommands {
}
public static Class> inject() {
- return GeneralCommands.class;
+ return OptionsCommands.class;
}
}
\ No newline at end of file
diff --git a/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java b/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java
index c5d75821..a3990b07 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/PatternCommands.java
@@ -119,7 +119,7 @@ public class PatternCommands extends MethodCommands {
)
public Pattern anglecolor(EditSession editSession, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
- return new AngleColorPattern(util, editSession);
+ return new AngleColorPattern(editSession, (int) maxComplexity, randomize);
}
@Command(
@@ -141,7 +141,7 @@ public class PatternCommands extends MethodCommands {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
Color color = Color.web(arg);
java.awt.Color awtColor = new java.awt.Color((float) color.getRed(), (float) color.getGreen(), (float) color.getBlue(), (float) color.getOpacity());
- return new SaturatePattern(editSession, util, awtColor.getRGB());
+ return new SaturatePattern(editSession, awtColor.getRGB(), (int) maxComplexity, randomize);
}
@Command(
@@ -155,7 +155,7 @@ public class PatternCommands extends MethodCommands {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
Color color = Color.web(arg);
java.awt.Color awtColor = new java.awt.Color((float) color.getRed(), (float) color.getGreen(), (float) color.getBlue(), (float) color.getOpacity());
- return new AverageColorPattern(editSession, util, awtColor.getRGB());
+ return new AverageColorPattern(editSession, awtColor.getRGB(), (int) maxComplexity, randomize);
}
@Command(
@@ -167,7 +167,7 @@ public class PatternCommands extends MethodCommands {
)
public Pattern desaturate(EditSession editSession, @Optional("100") double percent, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
- return new DesaturatePattern(editSession, util, percent / 100d);
+ return new DesaturatePattern(editSession, percent / 100d, (int) maxComplexity, randomize);
}
@Command(
@@ -179,7 +179,7 @@ public class PatternCommands extends MethodCommands {
)
public Pattern lighten(EditSession editSession, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
- return new ShadePattern(editSession, util, false);
+ return new ShadePattern(editSession, false, (int) maxComplexity, randomize);
}
@Command(
@@ -191,7 +191,7 @@ public class PatternCommands extends MethodCommands {
)
public Pattern darken(EditSession editSession, @Optional("true") boolean randomize, @Optional("100") double maxComplexity) {
TextureUtil util = Fawe.get().getCachedTextureUtil(randomize, 0, (int) maxComplexity);
- return new ShadePattern(editSession, util, true);
+ return new ShadePattern(editSession, true, (int) maxComplexity, randomize);
}
@Command(
@@ -371,8 +371,8 @@ public class PatternCommands extends MethodCommands {
min = 2,
max = 2
)
- public Pattern surfacespread(Actor actor, LocalSession session, EditSession editSession, double distance, Pattern pattern) {
- return new SurfaceRandomOffsetPattern(editSession, pattern, (int) distance);
+ public Pattern surfacespread(Actor actor, LocalSession session, double distance, Pattern pattern) {
+ return new SurfaceRandomOffsetPattern(pattern, (int) distance);
}
@Command(
diff --git a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
index 103109d9..0f3d5376 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/RegionCommands.java
@@ -316,7 +316,7 @@ public class RegionCommands {
}
@Command(
- aliases = { "/set" },
+ aliases = { "/set", "/s" },
usage = "[pattern]",
desc = "Set all blocks within selection",
min = 1,
diff --git a/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java
index 3bf47b19..aa5bb395 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/SchematicCommands.java
@@ -24,7 +24,6 @@ import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.clipboard.MultiClipboardHolder;
import com.boydti.fawe.object.schematic.StructureFormat;
import com.boydti.fawe.util.MainUtil;
-import com.boydti.fawe.util.MathMan;
import com.sk89q.minecraft.util.commands.Command;
import com.sk89q.minecraft.util.commands.CommandContext;
import com.sk89q.minecraft.util.commands.CommandException;
@@ -53,15 +52,10 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URI;
import java.net.URL;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.file.Files;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -78,7 +72,7 @@ public class SchematicCommands {
/**
* 9 schematics per page fits in the MC chat window.
*/
- private static final int SCHEMATICS_PER_PAGE = 9;
+
private static final Logger log = Logger.getLogger(SchematicCommands.class.getCanonicalName());
private final WorldEdit worldEdit;
@@ -336,154 +330,13 @@ public class SchematicCommands {
max = -1,
flags = "dnp",
help = "List all schematics in the schematics directory\n" +
- " -d sorts by date, oldest first\n" +
- " -n sorts by date, newest first\n" +
- " -p prints the requested page\n"
+ " -p prints the requested page\n" +
+ " -f restricts by format\n"
)
@CommandPermissions("worldedit.schematic.list")
- public void list(Actor actor, CommandContext args, @Switch('p') @Optional("1") int page) throws WorldEditException {
+ public void list(Actor actor, CommandContext args, @Switch('p') @Optional("1") int page, @Switch('f') String formatName) throws WorldEditException {
File dir = worldEdit.getWorkingDirectoryFile(worldEdit.getConfiguration().saveDir);
- List fileList = new ArrayList<>();
- int len = args.argsLength();
- List filters = new ArrayList<>();
- boolean mine = false;
- if (len > 0) {
- int max = len;
- if (MathMan.isInteger(args.getString(len - 1))) {
- page = args.getInteger(--len);
- }
- for (int i = 0; i < len; i++) {
- switch (args.getString(i).toLowerCase()) {
- case "me":
- case "mine":
- mine = true;
- break;
- default:
- filters.add(args.getString(i));
- break;
- }
- }
- }
- if (Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS) {
- File playerDir = new File(dir, actor.getUniqueId().toString());
- if (playerDir.exists()) {
- fileList.addAll(allFiles(playerDir, true));
- }
- if (!mine) {
- fileList.addAll(allFiles(dir, false));
- }
- } else {
- fileList.addAll(allFiles(dir, true));
- }
- if (!filters.isEmpty()) {
- for (String filter : filters) {
- fileList.removeIf(file -> !file.getPath().contains(filter));
- }
- }
- if (fileList.isEmpty()) {
- BBC.SCHEMATIC_NONE.send(actor);
- return;
- }
- File[] files = new File[fileList.size()];
- fileList.toArray(files);
- int pageCount = files.length / SCHEMATICS_PER_PAGE + 1;
- if (page < 1) {
- BBC.SCHEMATIC_PAGE.send(actor, ">0");
- return;
- }
- if (page > pageCount) {
- BBC.SCHEMATIC_PAGE.send(actor, "<" + (pageCount + 1));
- return;
- }
-
- final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0;
- // cleanup file list
- Arrays.sort(files, new Comparator(){
- @Override
- public int compare(File f1, File f2) {
- int res;
- if (sortType == 0) { // use name by default
- int p = f1.getParent().compareTo(f2.getParent());
- if (p == 0) { // same parent, compare names
- res = f1.getName().compareTo(f2.getName());
- } else { // different parent, sort by that
- res = p;
- }
- } else {
- res = Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); // use date if there is a flag
- if (sortType == 1) res = -res; // flip date for newest first instead of oldest first
- }
- return res;
- }
- });
-
- List schematics = listFiles(files, worldEdit.getConfiguration().saveDir, Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS ? actor.getUniqueId() : null);
- int offset = (page - 1) * SCHEMATICS_PER_PAGE;
-
- BBC.SCHEMATIC_LIST.send(actor, page, pageCount);
- StringBuilder build = new StringBuilder();
- int limit = Math.min(offset + SCHEMATICS_PER_PAGE, schematics.size());
- for (int i = offset; i < limit;) {
- build.append(schematics.get(i));
- if (++i != limit) {
- build.append("\n");
- }
- }
-
- actor.print(BBC.getPrefix() + build.toString());
- }
-
-
- private List allFiles(File root, boolean recursive) {
- File[] files = root.listFiles();
- if (files == null) return new ArrayList<>();
- List fileList = new ArrayList();
- for (File f : files) {
- if (recursive && f.isDirectory()) {
- List subFiles = allFiles(f, recursive);
- if (subFiles == null || subFiles.isEmpty()) continue; // empty subdir
- fileList.addAll(subFiles);
- } else {
- fileList.add(f);
- }
- }
- return fileList;
- }
-
- private List listFiles(File[] files, String prefix, UUID uuid) {
- if (prefix == null) prefix = "";
- File root = worldEdit.getWorkingDirectoryFile(prefix);
- File dir;
- if (uuid != null) {
- dir = new File(root, uuid.toString());
- } else {
- dir = root;
- }
- List result = new ArrayList();
- for (File file : files) {
- StringBuilder build = new StringBuilder();
-
- build.append("\u00a72");
- ClipboardFormat format = ClipboardFormat.findByFile(file);
-// boolean inRoot = file.getParentFile().getName().equals(prefix);
-// if (inRoot) {
-// build.append(file.getName());
-// } else {
-// String relative = dir.toURI().relativize(file.toURI()).getPath();
-// build.append(relative);
-// }
- URI relative = dir.toURI().relativize(file.toURI());
- String name = "";
- if (relative.isAbsolute()) {
- relative = root.toURI().relativize(file.toURI());
- name += "../";
- }
- name += relative.getPath();
- build.append(name);
- build.append(": ").append(format == null ? "Unknown" : format.name());
- result.add(build.toString());
- }
- return result;
+ UtilityCommands.list(dir, actor, args, page, formatName, Settings.IMP.PATHS.PER_PLAYER_SCHEMATICS);
}
public static Class> inject() {
diff --git a/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java b/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java
index b62775ed..4f579398 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/SelectionCommands.java
@@ -266,7 +266,7 @@ public class SelectionCommands {
}
@Command(
- aliases = { "/wand" },
+ aliases = { "/wand", "/w" },
usage = "",
desc = "Get the wand object",
min = 0,
diff --git a/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java b/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java
index 349c82f3..4db08400 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/ToolCommands.java
@@ -44,7 +44,7 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.util.TreeGenerator;
import com.sk89q.worldedit.util.command.parametric.Optional;
-@Command(aliases = {"tool"}, desc = "Bind functions to held items: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Tools)")
+@Command(aliases = {"brush", "br", "/b", "tool"}, desc = "Bind functions to held items: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Tools)")
public class ToolCommands {
private final WorldEdit we;
@@ -52,6 +52,19 @@ public class ToolCommands {
this.we = we;
}
+ @Command(
+ aliases = { "info", "/info" },
+ usage = "",
+ desc = "Block information tool",
+ min = 0,
+ max = 0
+ )
+ @CommandPermissions("worldedit.tool.info")
+ public void info(Player player, LocalSession session, CommandContext args) throws WorldEditException {
+ session.setTool(new QueryTool(), player);
+ BBC.TOOL_INFO.send(player, ItemType.toHeldName(player.getItemInHand()));
+ }
+
@Command(
aliases = { "inspect" },
usage = "",
@@ -67,31 +80,6 @@ public class ToolCommands {
BBC.TOOL_INSPECT.send(player, ItemType.toHeldName(player.getItemInHand()));
}
- @Command(
- aliases = { "none" },
- usage = "",
- desc = "Unbind a bound tool from your current item",
- min = 0,
- max = 0
- )
- public void none(Player player, LocalSession session, CommandContext args) throws WorldEditException {
- session.setTool(null, player);
- BBC.TOOL_NONE.send(player);
- }
-
- @Command(
- aliases = { "info" },
- usage = "",
- desc = "Block information tool",
- min = 0,
- max = 0
- )
- @CommandPermissions("worldedit.tool.info")
- public void info(Player player, LocalSession session, CommandContext args) throws WorldEditException {
- session.setTool(new QueryTool(), player);
- BBC.TOOL_INFO.send(player, ItemType.toHeldName(player.getItemInHand()));
- }
-
@Command(
aliases = { "tree" },
usage = "[type]",
diff --git a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java
index d339c7f8..c1987472 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/UtilityCommands.java
@@ -22,6 +22,7 @@ package com.sk89q.worldedit.command;
import com.boydti.fawe.config.BBC;
import com.boydti.fawe.object.FaweLimit;
import com.boydti.fawe.object.FawePlayer;
+import com.boydti.fawe.util.MathMan;
import com.boydti.fawe.util.StringMan;
import com.google.common.base.Joiner;
import com.google.common.util.concurrent.AtomicDouble;
@@ -46,6 +47,7 @@ import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Capability;
import com.sk89q.worldedit.extension.platform.CommandManager;
import com.sk89q.worldedit.extension.platform.Platform;
+import com.sk89q.worldedit.extent.clipboard.io.ClipboardFormat;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.operation.Operations;
@@ -60,6 +62,7 @@ import com.sk89q.worldedit.regions.CylinderRegion;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.CommandMapping;
+import com.sk89q.worldedit.util.command.DelegateCallable;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.PrimaryAliasComparator;
import com.sk89q.worldedit.util.command.binding.Text;
@@ -68,18 +71,24 @@ import com.sk89q.worldedit.util.command.parametric.ParametricCallable;
import com.sk89q.worldedit.util.formatting.ColorCodeBuilder;
import com.sk89q.worldedit.util.formatting.component.CommandUsageBox;
import com.sk89q.worldedit.world.World;
+import java.io.File;
+import java.net.URI;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
+import java.util.Comparator;
import java.util.HashSet;
+import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
+import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
@@ -89,7 +98,6 @@ import static com.sk89q.minecraft.util.commands.Logging.LogMode.PLACEMENT;
*/
@Command(aliases = {}, desc = "Various utility commands: [More Info](http://wiki.sk89q.com/wiki/WorldEdit/Utilities)")
public class UtilityCommands extends MethodCommands {
-
public UtilityCommands(WorldEdit we) {
super(we);
}
@@ -548,196 +556,363 @@ public class UtilityCommands extends MethodCommands {
return null;
}
+ public static void list(File dir, Actor actor, CommandContext args, int page, String formatName, boolean playerFolder) {
+ List fileList = new ArrayList<>();
+ int len = args.argsLength();
+ List filters = new ArrayList<>();
+ boolean mine = false;
+ if (len > 0) {
+ int max = len;
+ if (MathMan.isInteger(args.getString(len - 1))) {
+ page = args.getInteger(--len);
+ }
+ for (int i = 0; i < len; i++) {
+ switch (args.getString(i).toLowerCase()) {
+ case "me":
+ case "mine":
+ mine = true;
+ break;
+ default:
+ filters.add(args.getString(i));
+ break;
+ }
+ }
+ }
+ if (playerFolder) {
+ File playerDir = new File(dir, actor.getUniqueId().toString());
+ if (playerDir.exists()) {
+ fileList.addAll(allFiles(playerDir, true));
+ }
+ if (!mine) {
+ fileList.addAll(allFiles(dir, false));
+ }
+ } else {
+ fileList.addAll(allFiles(dir, true));
+ }
+ if (!filters.isEmpty()) {
+ for (String filter : filters) {
+ fileList.removeIf(file -> !file.getPath().contains(filter));
+ }
+ }
+ if (fileList.isEmpty()) {
+ BBC.SCHEMATIC_NONE.send(actor);
+ return;
+ }
+ if (formatName != null) {
+ final ClipboardFormat cf = ClipboardFormat.findByAlias(formatName);
+ fileList = fileList.stream()
+ .filter(file -> cf.isFormat(file))
+ .collect(Collectors.toList());
+
+ }
+ File[] files = new File[fileList.size()];
+ fileList.toArray(files);
+ final int perPage = actor instanceof Player ? 8 : 20; // More pages for console
+ int pageCount = (files.length + perPage - 1) / perPage;
+ if (page < 1) {
+ BBC.SCHEMATIC_PAGE.send(actor, ">0");
+ return;
+ }
+ if (page > pageCount) {
+ BBC.SCHEMATIC_PAGE.send(actor, "<" + (pageCount + 1));
+ return;
+ }
+
+ final int sortType = args.hasFlag('d') ? -1 : args.hasFlag('n') ? 1 : 0;
+ // cleanup file list
+ Arrays.sort(files, new Comparator(){
+ @Override
+ public int compare(File f1, File f2) {
+ int res;
+ if (sortType == 0) { // use name by default
+ int p = f1.getParent().compareTo(f2.getParent());
+ if (p == 0) { // same parent, compare names
+ res = f1.getName().compareTo(f2.getName());
+ } else { // different parent, sort by that
+ res = p;
+ }
+ } else {
+ res = Long.valueOf(f1.lastModified()).compareTo(f2.lastModified()); // use date if there is a flag
+ if (sortType == 1) res = -res; // flip date for newest first instead of oldest first
+ }
+ return res;
+ }
+ });
+
+ List schematics = listFiles(dir, files, playerFolder ? actor.getUniqueId() : null);
+ int offset = (page - 1) * perPage;
+
+ StringBuilder build = new StringBuilder();
+ int limit = Math.min(offset + perPage, schematics.size());
+ for (int i = offset; i < limit;) {
+ build.append(schematics.get(i));
+ if (++i != limit) {
+ build.append("\n");
+ }
+ }
+ String heading = BBC.SCHEMATIC_LIST.f(page, pageCount);
+ actor.print(BBC.getPrefix() + heading + "\n" + build.toString());
+ }
+
+
+ private static List allFiles(File root, boolean recursive) {
+ File[] files = root.listFiles();
+ if (files == null) return new ArrayList<>();
+ List fileList = new ArrayList();
+ for (File f : files) {
+ if (f.isDirectory()) {
+ if (recursive) {
+ List subFiles = allFiles(f, recursive);
+ if (subFiles == null || subFiles.isEmpty()) continue; // empty subdir
+ fileList.addAll(subFiles);
+ }
+ } else {
+ fileList.add(f);
+ }
+ }
+ return fileList;
+ }
+
+ private static List listFiles(File root, File[] files, UUID uuid) {
+ File dir;
+ if (uuid != null) {
+ dir = new File(root, uuid.toString());
+ } else {
+ dir = root;
+ }
+ List result = new ArrayList();
+ for (File file : files) {
+ ClipboardFormat format = ClipboardFormat.findByFile(file);
+ URI relative = dir.toURI().relativize(file.toURI());
+ String name = "";
+ if (relative.isAbsolute()) {
+ relative = root.toURI().relativize(file.toURI());
+ name += "../";
+ }
+ name += relative.getPath();
+ String formatName;
+ if (format == null) {
+ String[] split = file.getName().split("\\.");
+ formatName = split.length > 1 ? split[split.length - 1].toUpperCase() : "Unknown";
+ } else {
+ formatName = format.toString();
+ }
+ result.add(BBC.SCHEMATIC_LIST_ELEM.f(name, formatName));
+ }
+ return result;
+ }
+
public static void help(CommandContext args, WorldEdit we, Actor actor) {
help(args, we, actor, "/", null);
}
public static void help(CommandContext args, WorldEdit we, Actor actor, String prefix, CommandCallable callable) {
- if (callable == null) {
- callable = we.getPlatformManager().getCommandManager().getDispatcher();
- }
- CommandLocals locals = args.getLocals();
-
- int page = -1;
- String category = null;
- final int perPage = actor instanceof Player ? 8 : 20; // More pages for console
- int effectiveLength = args.argsLength();
-
- // Detect page from args
try {
- if (effectiveLength > 0) {
- page = args.getInteger(args.argsLength() - 1);
- if (page <= 0) {
- page = 1;
- } else {
- page--;
- }
- effectiveLength--;
+ if (callable == null) {
+ callable = we.getPlatformManager().getCommandManager().getDispatcher();
}
- } catch (NumberFormatException ignored) {
- }
+ CommandLocals locals = args.getLocals();
- boolean isRootLevel = true;
- List visited = new ArrayList();
+ int page = -1;
+ String category = null;
+ final int perPage = actor instanceof Player ? 8 : 20; // More pages for console
+ int effectiveLength = args.argsLength();
- // Create the message
- if (callable instanceof Dispatcher) {
- Dispatcher dispatcher = (Dispatcher) callable;
-
- // Get a list of aliases
- List aliases = new ArrayList(dispatcher.getCommands());
- // Group by callable
-
- if (page == -1 || effectiveLength > 0) {
- Map> grouped = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
- for (CommandMapping mapping : aliases) {
- CommandCallable c = mapping.getCallable();
- String group;
- if (c instanceof ParametricCallable) {
- group = ((ParametricCallable) c).getObject().getClass().getSimpleName().replaceAll("Commands", "");
- } else {
- group = "Miscellaneous";
- }
- ArrayList queue = grouped.get(group);
- if (queue == null) {
- queue = new ArrayList<>();
- grouped.put(group, queue);
- }
- queue.add(mapping);
- }
+ // Detect page from args
+ try {
if (effectiveLength > 0) {
- String cat = args.getString(0);
- ArrayList mappings = effectiveLength == 1 ? grouped.get(cat) : null;
- if (mappings == null) {
- // Drill down to the command
- for (int i = 0; i < effectiveLength; i++) {
- String command = args.getString(i);
+ page = args.getInteger(args.argsLength() - 1);
+ if (page <= 0) {
+ page = 1;
+ } else {
+ page--;
+ }
+ effectiveLength--;
+ }
+ } catch (NumberFormatException ignored) {
+ }
- if (callable instanceof Dispatcher) {
- // Chop off the beginning / if we're are the root level
- if (isRootLevel && command.length() > 1 && command.charAt(0) == '/') {
- command = command.substring(1);
- }
+ boolean isRootLevel = true;
+ List visited = new ArrayList();
- CommandMapping mapping = detectCommand((Dispatcher) callable, command, isRootLevel);
- if (mapping != null) {
- callable = mapping.getCallable();
- } else {
- if (isRootLevel) {
- Set found = new HashSet<>();
- String arg = args.getString(i).toLowerCase();
- String closest = null;
- int distance = Integer.MAX_VALUE;
- for (CommandMapping map : aliases) {
- String desc = map.getDescription().getDescription();
- if (desc == null) desc = map.getDescription().getHelp();
- if (desc == null) desc = "";
- String[] descSplit = desc.replaceAll("[^A-Za-z0-9]", "").toLowerCase().split(" ");
- for (String alias : map.getAllAliases()) {
- if (alias.equals(arg)) {
- closest = map.getPrimaryAlias();
- distance = 0;
- found.add(map.getPrimaryAlias());
- } else if (alias.contains(arg)) {
- closest = map.getPrimaryAlias();
- distance = 1;
- found.add(map.getPrimaryAlias());
- } else if (StringMan.isEqualIgnoreCaseToAny(arg, descSplit)) {
- closest = map.getPrimaryAlias();
- distance = 1;
- found.add(map.getPrimaryAlias());
- } else {
- int currentDist = StringMan.getLevenshteinDistance(alias, arg);
- if (currentDist < distance) {
- distance = currentDist;
+ // Create the message
+ if (callable instanceof Dispatcher) {
+ Dispatcher dispatcher = (Dispatcher) callable;
+
+ // Get a list of aliases
+ List aliases = new ArrayList(dispatcher.getCommands());
+ // Group by callable
+
+ if (page == -1 || effectiveLength > 0) {
+ Map> grouped = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
+ for (CommandMapping mapping : aliases) {
+ CommandCallable c = mapping.getCallable();
+ String group;
+ if (c instanceof DelegateCallable) {
+ c = ((DelegateCallable) c).getParent();
+ }
+ if (c instanceof ParametricCallable) {
+ Object obj = ((ParametricCallable) c).getObject();
+ Command command = obj.getClass().getAnnotation(Command.class);
+ if (command != null && command.aliases().length != 0) {
+ group = command.aliases()[0];
+ } else {
+ group = obj.getClass().getSimpleName().replaceAll("Commands", "").replaceAll("Util$", "");
+ }
+ } else if (c instanceof Dispatcher) {
+ group = mapping.getPrimaryAlias();
+ } else {
+ group = "Unsorted";
+ }
+ group = StringMan.toProperCase(group);
+ Set queue = grouped.get(group);
+ if (queue == null) {
+ queue = new LinkedHashSet<>();
+ grouped.put(group, queue);
+ }
+ if (c instanceof Dispatcher) {
+ queue.addAll(((Dispatcher) c).getCommands());
+ } else {
+ queue.add(mapping);
+ }
+ }
+ if (effectiveLength > 0) {
+ String cat = args.getString(0);
+ Set mappings = effectiveLength == 1 ? grouped.get(cat) : null;
+ if (mappings == null) {
+ // Drill down to the command
+ for (int i = 0; i < effectiveLength; i++) {
+ String command = args.getString(i);
+
+ if (callable instanceof Dispatcher) {
+ // Chop off the beginning / if we're are the root level
+ if (isRootLevel && command.length() > 1 && command.charAt(0) == '/') {
+ command = command.substring(1);
+ }
+
+ CommandMapping mapping = detectCommand((Dispatcher) callable, command, isRootLevel);
+ if (mapping != null) {
+ callable = mapping.getCallable();
+ } else {
+ if (isRootLevel) {
+ Set found = new HashSet<>();
+ String arg = args.getString(i).toLowerCase();
+ String closest = null;
+ int distance = Integer.MAX_VALUE;
+ for (CommandMapping map : aliases) {
+ String desc = map.getDescription().getDescription();
+ if (desc == null) desc = map.getDescription().getHelp();
+ if (desc == null) desc = "";
+ String[] descSplit = desc.replaceAll("[^A-Za-z0-9]", "").toLowerCase().split(" ");
+ for (String alias : map.getAllAliases()) {
+ if (alias.equals(arg)) {
closest = map.getPrimaryAlias();
+ distance = 0;
+ found.add(map.getPrimaryAlias());
+ } else if (alias.contains(arg)) {
+ closest = map.getPrimaryAlias();
+ distance = 1;
+ found.add(map.getPrimaryAlias());
+ } else if (StringMan.isEqualIgnoreCaseToAny(arg, descSplit)) {
+ closest = map.getPrimaryAlias();
+ distance = 1;
+ found.add(map.getPrimaryAlias());
+ } else {
+ int currentDist = StringMan.getLevenshteinDistance(alias, arg);
+ if (currentDist < distance) {
+ distance = currentDist;
+ closest = map.getPrimaryAlias();
+ }
}
}
}
+ found.add(closest);
+ BBC.HELP_SUGGEST.send(actor, arg, StringMan.join(found, ", "));
+ return;
+ } else {
+ actor.printError(String.format("The sub-command '%s' under '%s' could not be found.",
+ command, Joiner.on(" ").join(visited)));
+ return;
}
- found.add(closest);
- BBC.HELP_SUGGEST.send(actor, arg, StringMan.join(found, ", "));
- return;
- } else {
- actor.printError(String.format("The sub-command '%s' under '%s' could not be found.",
- command, Joiner.on(" ").join(visited)));
- return;
}
+ visited.add(args.getString(i));
+ isRootLevel = false;
+ } else {
+ actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)",
+ Joiner.on(" ").join(visited), command));
+ return;
}
- visited.add(args.getString(i));
- isRootLevel = false;
- } else {
- actor.printError(String.format("'%s' has no sub-commands. (Maybe '%s' is for a parameter?)",
- Joiner.on(" ").join(visited), command));
+ }
+ if (!(callable instanceof Dispatcher)) {
+ actor.printRaw(BBC.getPrefix() + ColorCodeBuilder.asColorCodes(new CommandUsageBox(callable, Joiner.on(" ").join(visited))));
return;
}
- }
- if (!(callable instanceof Dispatcher)) {
- actor.printRaw(BBC.getPrefix() + ColorCodeBuilder.asColorCodes(new CommandUsageBox(callable, Joiner.on(" ").join(visited))));
- return;
- }
- dispatcher = (Dispatcher) callable;
- aliases = new ArrayList(dispatcher.getCommands());
- } else {
- aliases = mappings;
- }
- page = Math.max(0, page);
- } else if (grouped.size() > 1) {
- StringBuilder message = new StringBuilder();
- message.append(BBC.getPrefix() + BBC.HELP_HEADER_CATEGORIES.s() + "\n");
- StringBuilder builder = new StringBuilder();
- boolean first = true;
- for (Map.Entry> entry : grouped.entrySet()) {
- String s1 = "&a//help " + entry.getKey();
- String s2 = entry.getValue().size() + "";
- message.append(BBC.HELP_ITEM_ALLOWED.format(s1, s2) + "\n");
- }
- message.append(BBC.HELP_HEADER_FOOTER.s());
- actor.print(BBC.color(message.toString()));
- return;
- }
- }
-// else
- {
- Collections.sort(aliases, new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN));
-
- // Calculate pagination
- int offset = perPage * Math.max(0, page);
- int pageTotal = (int) Math.ceil(aliases.size() / (double) perPage);
-
- // Box
- StringBuilder message = new StringBuilder();
-
- if (offset >= aliases.size()) {
- message.append("&c").append(String.format("There is no page %d (total number of pages is %d).", page + 1, pageTotal));
- } else {
- message.append(BBC.getPrefix() + BBC.HELP_HEADER.format(page + 1, pageTotal) + "\n");
- List list = aliases.subList(offset, Math.min(offset + perPage, aliases.size() - 1));
-
- boolean first = true;
- // Add each command
- for (CommandMapping mapping : list) {
- CommandCallable c = mapping.getCallable();
- StringBuilder s1 = new StringBuilder();
- s1.append(prefix);
- if (!visited.isEmpty()) {
- s1.append(Joiner.on(" ").join(visited));
- s1.append(" ");
- }
- s1.append(mapping.getPrimaryAlias());
- String s2 = mapping.getDescription().getDescription();
- if (c.testPermission(locals)) {
- message.append(BBC.HELP_ITEM_ALLOWED.format(s1, s2) + "\n");
+ dispatcher = (Dispatcher) callable;
+ aliases = new ArrayList(dispatcher.getCommands());
} else {
- message.append(BBC.HELP_ITEM_DENIED.format(s1, s2) + "\n");
+ aliases = new ArrayList<>(mappings);
}
+ page = Math.max(0, page);
+ } else if (grouped.size() > 1) {
+ StringBuilder message = new StringBuilder();
+ message.append(BBC.getPrefix() + BBC.HELP_HEADER_CATEGORIES.s() + "\n");
+ StringBuilder builder = new StringBuilder();
+ boolean first = true;
+ for (Map.Entry> entry : grouped.entrySet()) {
+ String s1 = "&a//help " + entry.getKey();
+ String s2 = entry.getValue().size() + "";
+ message.append(BBC.HELP_ITEM_ALLOWED.format(s1, s2) + "\n");
+ }
+ message.append(BBC.HELP_HEADER_FOOTER.s());
+ actor.print(BBC.color(message.toString()));
+ return;
}
- message.append(BBC.HELP_HEADER_FOOTER.f());
}
- actor.print(BBC.color(message.toString()));
+// else
+ {
+ Collections.sort(aliases, new PrimaryAliasComparator(CommandManager.COMMAND_CLEAN_PATTERN));
+
+ // Calculate pagination
+ int offset = perPage * Math.max(0, page);
+ int pageTotal = (int) Math.ceil(aliases.size() / (double) perPage);
+
+ // Box
+ StringBuilder message = new StringBuilder();
+
+ if (offset >= aliases.size()) {
+ message.append("&c").append(String.format("There is no page %d (total number of pages is %d).", page + 1, pageTotal));
+ } else {
+ message.append(BBC.getPrefix() + BBC.HELP_HEADER.format(page + 1, pageTotal) + "\n");
+ List list = aliases.subList(offset, Math.min(offset + perPage, aliases.size()));
+
+ boolean first = true;
+ // Add each command
+ for (CommandMapping mapping : list) {
+ CommandCallable c = mapping.getCallable();
+ StringBuilder s1 = new StringBuilder();
+ s1.append(prefix);
+ if (!visited.isEmpty()) {
+ s1.append(Joiner.on(" ").join(visited));
+ s1.append(" ");
+ }
+ s1.append(mapping.getPrimaryAlias());
+ String s2 = mapping.getDescription().getDescription();
+ if (c.testPermission(locals)) {
+ message.append(BBC.HELP_ITEM_ALLOWED.format(s1, s2) + "\n");
+ } else {
+ message.append(BBC.HELP_ITEM_DENIED.format(s1, s2) + "\n");
+ }
+ }
+ message.append(BBC.HELP_HEADER_FOOTER.f());
+ }
+ actor.print(BBC.color(message.toString()));
+ }
+ } else {
+ actor.printRaw(BBC.getPrefix() + ColorCodeBuilder.asColorCodes(new CommandUsageBox(callable, Joiner.on(" ").join(visited))));
}
- } else {
- actor.printRaw(BBC.getPrefix() + ColorCodeBuilder.asColorCodes(new CommandUsageBox(callable, Joiner.on(" ").join(visited))));
+ } catch (Throwable e) {
+ e.printStackTrace();
+ throw new RuntimeException(e);
}
}
diff --git a/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java b/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java
index 90c5b77e..00983528 100644
--- a/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java
+++ b/core/src/main/java/com/sk89q/worldedit/command/tool/BrushTool.java
@@ -18,6 +18,9 @@ import com.boydti.fawe.object.extent.ResettableExtent;
import com.boydti.fawe.object.pattern.PatternTraverser;
import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.TaskManager;
+import com.google.gson.Gson;
+import com.google.gson.reflect.TypeToken;
+import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.worldedit.BlockWorldVector;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.LocalConfiguration;
@@ -29,6 +32,7 @@ import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.command.tool.brush.Brush;
import com.sk89q.worldedit.entity.Player;
+import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.Platform;
import com.sk89q.worldedit.extent.inventory.BlockBag;
@@ -38,6 +42,11 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.util.TargetBlock;
+import java.io.IOException;
+import java.io.Serializable;
+import java.lang.reflect.Type;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import javax.annotation.Nullable;
@@ -45,7 +54,11 @@ import javax.annotation.Nullable;
import static com.google.common.base.Preconditions.checkNotNull;
-public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool, ResettableTool {
+public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool, ResettableTool, Serializable {
+// TODO:
+ // Serialize methods
+ // serialize BrushSettings (primary and secondary only if different)
+ // set transient values e.g. context
public enum BrushAction {
PRIMARY,
@@ -58,20 +71,83 @@ public class BrushTool implements DoubleActionTraceTool, ScrollTool, MovableTool
private TargetMode targetMode = TargetMode.TARGET_BLOCK_RANGE;
private transient BrushSettings context = new BrushSettings();
- private BrushSettings primary = context;
- private BrushSettings secondary = context;
+ private transient BrushSettings primary = context;
+ private transient BrushSettings secondary = context;
private transient VisualExtent visualExtent;
private transient Lock lock = new ReentrantLock();
- /**
- * Construct the tool.
- *
- * @param permission the permission to check before use is allowed
- */
public BrushTool(String permission) {
- checkNotNull(permission);
- this.getContext().permission = permission;
+ getContext().addPermission(permission);
+ }
+
+ public BrushTool() {
+ }
+
+ public static BrushTool fromString(Player player, LocalSession session, String json) throws CommandException, InputParseException {
+ Gson gson = new Gson();
+ Type type = new TypeToken