Optimize for 1.12
Refactor commands / style / cleanup
Brush saving/loading
Tweak / improve ChunkListener
This commit is contained in:
Jesse Boyd 2017-05-15 21:33:03 +10:00
parent de26c22f05
commit b9c056c879
No known key found for this signature in database
GPG Key ID: 59F1DE6293AF6E1F
135 changed files with 3965 additions and 2214 deletions

View File

@ -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'

View File

@ -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);

View File

@ -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<Boolean> 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<Long> badChunks = new HashSet<>();
private Long2ObjectOpenHashMap<Boolean> badChunks = new Long2ObjectOpenHashMap<>();
private Long2ObjectOpenHashMap<int[]> 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;

View File

@ -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;

View File

@ -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<Long> 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));
}
}

View File

@ -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<Chunk, BukkitQueue_1_12> {
public DataPaletteBlock[] sectionPalettes;
public static Map<String, Class<? extends Entity>> 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<String, Tag> 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<DataPaletteBlock> 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<Entity>[] entities = (Collection<Entity>[]) getParent().getEntitySlices.invoke(nmsChunk);
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
// Set heightmap
getParent().setHeightMap(this, heightMap);
// Remove entities
HashSet<UUID> entsToRemove = this.getEntityRemoves();
if (!entsToRemove.isEmpty()) {
for (int i = 0; i < entities.length; i++) {
Collection<Entity> ents = entities[i];
if (!ents.isEmpty()) {
Iterator<Entity> 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<Entity> ents = entities[i];
if (!ents.isEmpty()) {
if (copy != null) {
for (Entity entity : ents) {
copy.storeEntity(entity);
}
}
synchronized (BukkitQueue_0.class) {
ents.clear();
}
}
} else {
Collection<Entity> ents = entities[i];
if (!ents.isEmpty()) {
char[] array = this.getIdArray(i);
if (array == null) continue;
Iterator<Entity> 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<CompoundTag> entitiesToSpawn = this.getEntities();
Set<UUID> createdEntities = new HashSet<>();
if (!entitiesToSpawn.isEmpty()) {
synchronized (BukkitQueue_0.class) {
for (CompoundTag nativeTag : entitiesToSpawn) {
Map<String, Tag> 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<Map.Entry<BlockPosition, TileEntity>> iterator = tiles.entrySet().iterator();
HashMap<BlockPosition, TileEntity> toRemove = null;
while (iterator.hasNext()) {
Map.Entry<BlockPosition, TileEntity> 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<BlockPosition, TileEntity> 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<Short, CompoundTag> tilesToSpawn = this.getTiles();
for (Map.Entry<Short, CompoundTag> 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;
}
}

View File

@ -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");
}
}

View File

@ -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<net.minecraft.server.v1_12_R1.Chunk, ChunkSection[], ChunkSection> {
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<Object>() {
@Override
public void run(Object value) {
try {
synchronized (RegionFileCache.class) {
ArrayDeque<net.minecraft.server.v1_12_R1.Chunk> chunks = new ArrayDeque<>();
World world = getWorld();
world.setKeepSpawnInMemory(false);
ChunkProviderServer provider = nmsWorld.getChunkProviderServer();
if (unload) { // Unload chunks
int bcx = (allowed.minX >> 9) << 5;
int bcz = (allowed.minZ >> 9) << 5;
int tcx = 31 + (allowed.maxX >> 9) << 5;
int tcz = 31 + (allowed.maxZ >> 9) << 5;
Iterator<net.minecraft.server.v1_12_R1.Chunk> iter = provider.a().iterator();
while (iter.hasNext()) {
net.minecraft.server.v1_12_R1.Chunk chunk = iter.next();
int cx = chunk.locX;
int cz = chunk.locZ;
if (cx >= bcx && cx <= tcx && cz >= bcz && cz <= tcz) {
chunks.add(chunk);
}
}
for (net.minecraft.server.v1_12_R1.Chunk chunk : chunks) {
provider.unloadChunk(chunk, true);
}
}
provider.c();
if (unload) { // Unload regions
Map<File, RegionFile> map = RegionFileCache.a;
Iterator<Map.Entry<File, RegionFile>> iter = map.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry<File, RegionFile> entry = iter.next();
RegionFile regionFile = entry.getValue();
regionFile.c();
iter.remove();
}
}
whileLocked.run();
// Load the chunks again
if (unload) {
for (net.minecraft.server.v1_12_R1.Chunk chunk : chunks) {
chunk = provider.loadChunk(chunk.locX, chunk.locZ);
if (chunk != null) {
sendChunk(chunk, 0);
}
}
}
}
} catch (Throwable e) {
e.printStackTrace();
}
}
});
return true;
} catch (Throwable e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
@Override
public void setHeightMap(FaweChunk chunk, byte[] heightMap) {
CraftChunk craftChunk = (CraftChunk) chunk.getChunk();
if (craftChunk != null) {
int[] otherMap = craftChunk.getHandle().heightMap;
for (int i = 0; i < heightMap.length; i++) {
int newHeight = heightMap[i] & 0xFF;
int currentHeight = otherMap[i];
if (newHeight > currentHeight) {
otherMap[i] = newHeight;
}
}
}
}
@Override
public boolean next(int amount, long time) {
return super.next(amount, time);
}
@Override
public void setSkyLight(ChunkSection section, int x, int y, int z, int value) {
section.getSkyLightArray().a(x & 15, y & 15, z & 15, value);
}
@Override
public void setBlockLight(ChunkSection section, int x, int y, int z, int value) {
section.getEmittedLightArray().a(x & 15, y & 15, z & 15, value);
}
@Override
public World createWorld(final WorldCreator creator) {
final String name = creator.name();
ChunkGenerator generator = creator.generator();
final CraftServer server = (CraftServer) Bukkit.getServer();
final MinecraftServer console = server.getServer();
final File folder = new File(server.getWorldContainer(), name);
final World world = server.getWorld(name);
final WorldType type = WorldType.getType(creator.type().getName());
final boolean generateStructures = creator.generateStructures();
if (world != null) {
return world;
}
if (folder.exists() && !folder.isDirectory()) {
throw new IllegalArgumentException("File exists with the name '" + name + "' and isn't a folder");
}
TaskManager.IMP.sync(new RunnableVal<Object>() {
@Override
public void run(Object value) {
try {
Field field = CraftServer.class.getDeclaredField("worlds");
field.setAccessible(true);
Map<Object, Object> existing = (Map<Object, Object>) field.get(server);
if (!existing.getClass().getName().contains("SynchronizedMap")) {
field.set(server, Collections.synchronizedMap(existing));
}
} catch (Throwable e) {
e.printStackTrace();
}
}
});
if (generator == null) {
generator = server.getGenerator(name);
}
int dimension = 10 + console.worlds.size();
boolean used = false;
do {
for (final WorldServer ws : console.worlds) {
used = (ws.dimension == dimension);
if (used) {
++dimension;
break;
}
}
} while (used);
final boolean hardcore = false;
final IDataManager sdm = new ServerNBTManager(server.getWorldContainer(), name, true, server.getHandle().getServer().dataConverterManager);
WorldData worlddata = sdm.getWorldData();
final WorldSettings worldSettings;
if (worlddata == null) {
worldSettings = new WorldSettings(creator.seed(), EnumGamemode.getById(server.getDefaultGameMode().getValue()), generateStructures, hardcore, type);
worldSettings.setGeneratorSettings(creator.generatorSettings());
worlddata = new WorldData(worldSettings, name);
} else {
worldSettings = null;
}
worlddata.checkName(name);
final WorldServer internal = (WorldServer)new WorldServer(console, sdm, worlddata, dimension, console.methodProfiler, creator.environment(), generator).b();
startSet(true); // Temporarily allow async chunk load since the world isn't added yet
if (worldSettings != null) {
internal.a(worldSettings);
}
endSet(true);
internal.scoreboard = server.getScoreboardManager().getMainScoreboard().getHandle();
internal.tracker = new EntityTracker(internal);
internal.addIWorldAccess(new WorldManager(console, internal));
internal.worldData.setDifficulty(EnumDifficulty.EASY);
internal.setSpawnFlags(true, true);
if (generator != null) {
internal.getWorld().getPopulators().addAll(generator.getDefaultPopulators(internal.getWorld()));
}
// Add the world
return TaskManager.IMP.sync(new RunnableVal<World>() {
@Override
public void run(World value) {
console.worlds.add(internal);
server.getPluginManager().callEvent(new WorldInitEvent(internal.getWorld()));
server.getPluginManager().callEvent(new WorldLoadEvent(internal.getWorld()));
this.value = internal.getWorld();
}
});
}
@Override
public int getCombinedId4Data(ChunkSection lastSection, int x, int y, int z) {
DataPaletteBlock dataPalette = lastSection.getBlocks();
IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15);
Block block = ibd.getBlock();
int id = Block.getId(block);
if (FaweCache.hasData(id)) {
return (id << 4) + block.toLegacyData(ibd);
} else {
return id << 4;
}
}
@Override
public int getBiome(net.minecraft.server.v1_12_R1.Chunk chunk, int x, int z) {
return chunk.getBiomeIndex()[((z & 15) << 4) + (x & 15)];
}
@Override
public int getOpacity(ChunkSection section, int x, int y, int z) {
DataPaletteBlock dataPalette = section.getBlocks();
IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15);
return ibd.c();
}
@Override
public int getBrightness(ChunkSection section, int x, int y, int z) {
DataPaletteBlock dataPalette = section.getBlocks();
IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15);
return ibd.d();
}
@Override
public int getOpacityBrightnessPair(ChunkSection section, int x, int y, int z) {
DataPaletteBlock dataPalette = section.getBlocks();
IBlockData ibd = dataPalette.a(x & 15, y & 15, z & 15);
return MathMan.pair16(ibd.c(), ibd.d());
}
@Override
public void sendChunk(int x, int z, int bitMask) {
net.minecraft.server.v1_12_R1.Chunk chunk = getCachedChunk(getWorld(), x, z);
if (chunk != null) {
sendChunk(chunk, bitMask);
}
}
@Override
public void sendBlockUpdate(FaweChunk chunk, FawePlayer... players) {
try {
PlayerChunkMap playerManager = ((CraftWorld) getWorld()).getHandle().getPlayerChunkMap();
boolean watching = false;
boolean[] watchingArr = new boolean[players.length];
for (int i = 0; i < players.length; i++) {
EntityPlayer player = ((CraftPlayer) ((BukkitPlayer) players[i]).parent).getHandle();
if (playerManager.a(player, chunk.getX(), chunk.getZ())) {
watchingArr[i] = true;
watching = true;
}
}
if (!watching) return;
final LongAdder size = new LongAdder();
if (chunk instanceof VisualChunk) {
size.add(((VisualChunk) chunk).size());
} else if (chunk instanceof CharFaweChunk) {
size.add(((CharFaweChunk) chunk).getTotalCount());
} else {
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
@Override
public void run(int localX, int y, int localZ, int combined) {
size.add(1);
}
});
}
if (size.intValue() == 0) return;
PacketPlayOutMultiBlockChange packet = new PacketPlayOutMultiBlockChange();
ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer();
final PacketDataSerializer buffer = new PacketDataSerializer(byteBuf);
buffer.writeInt(chunk.getX());
buffer.writeInt(chunk.getZ());
buffer.d(size.intValue());
chunk.forEachQueuedBlock(new FaweChunkVisitor() {
@Override
public void run(int localX, int y, int localZ, int combined) {
short index = (short) (localX << 12 | localZ << 8 | y);
if (combined < 16) combined = 0;
buffer.writeShort(index);
buffer.d(combined);
}
});
packet.a(buffer);
for (int i = 0; i < players.length; i++) {
if (watchingArr[i]) ((CraftPlayer) ((BukkitPlayer) players[i]).parent).getHandle().playerConnection.sendPacket(packet);
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void refreshChunk(FaweChunk fc) {
net.minecraft.server.v1_12_R1.Chunk chunk = getCachedChunk(getWorld(), fc.getX(), fc.getZ());
if (chunk != null) {
sendChunk(chunk, fc.getBitMask());
}
}
public void sendChunk(net.minecraft.server.v1_12_R1.Chunk nmsChunk, int mask) {
WorldServer w = (WorldServer) nmsChunk.getWorld();
PlayerChunkMap chunkMap = w.getPlayerChunkMap();
PlayerChunk playerChunk = chunkMap.getChunk(nmsChunk.locX, nmsChunk.locZ);
if (playerChunk == null) {
return;
}
if (playerChunk.c.isEmpty()) {
return;
}
if (mask == 0) {
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65535);
for (EntityPlayer player : playerChunk.c) {
player.playerConnection.sendPacket(packet);
}
return;
}
// Send chunks
boolean empty = false;
ChunkSection[] sections = nmsChunk.getSections();
for (int i = 0; i < sections.length; i++) {
if (sections[i] == null) {
sections[i] = emptySection;
empty = true;
}
}
if (mask == 0 || mask == 65535 && hasEntities(nmsChunk)) {
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, 65280);
for (EntityPlayer player : playerChunk.c) {
player.playerConnection.sendPacket(packet);
}
mask = 255;
}
PacketPlayOutMapChunk packet = new PacketPlayOutMapChunk(nmsChunk, mask);
for (EntityPlayer player : playerChunk.c) {
player.playerConnection.sendPacket(packet);
}
if (empty) {
for (int i = 0; i < sections.length; i++) {
if (sections[i] == emptySection) {
sections[i] = null;
}
}
}
}
public boolean hasEntities(net.minecraft.server.v1_12_R1.Chunk nmsChunk) {
try {
final Collection<Entity>[] entities = (Collection<Entity>[]) getEntitySlices.invoke(nmsChunk);
for (int i = 0; i < entities.length; i++) {
Collection<Entity> slice = entities[i];
if (slice != null && !slice.isEmpty()) {
return true;
}
}
} catch (Throwable ignore) {}
return false;
}
@Override
public boolean removeLighting(ChunkSection[] sections, RelightMode mode, boolean sky) {
if (mode != RelightMode.NONE) {
for (int i = 0; i < sections.length; i++) {
ChunkSection section = sections[i];
if (section != null) {
section.a(new NibbleArray()); // Emitted
if (sky) {
section.b(new NibbleArray()); // Skylight
}
}
}
}
return true;
}
@Override
public void setFullbright(ChunkSection[] sections) {
for (int i = 0; i < sections.length; i++) {
ChunkSection section = sections[i];
if (section != null) {
byte[] bytes = section.getSkyLightArray().asBytes();
Arrays.fill(bytes, (byte) 255);
}
}
}
@Override
public int getSkyLight(ChunkSection section, int x, int y, int z) {
return section.b(x & 15, y & 15, z & 15);
}
@Override
public int getEmmittedLight(ChunkSection section, int x, int y, int z) {
return section.c(x & 15, y & 15, z & 15);
}
@Override
public void relightBlock(int x, int y, int z) {
pos.c(x, y, z);
nmsWorld.c(EnumSkyBlock.BLOCK, pos);
}
@Override
public void relightSky(int x, int y, int z) {
pos.c(x, y, z);
nmsWorld.c(EnumSkyBlock.SKY, pos);
}
@Override
public void relight(int x, int y, int z) {
pos.c(x, y, z);
nmsWorld.w(pos);
}
protected WorldServer nmsWorld;
@Override
public World getImpWorld() {
World world = super.getImpWorld();
if (world != null) {
this.nmsWorld = ((CraftWorld) world).getHandle();
return super.getImpWorld();
} else {
return null;
}
}
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
fieldTickingBlockCount.set(section, tickingBlockCount);
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
}
public int getNonEmptyBlockCount(ChunkSection section) throws IllegalAccessException {
return (int) fieldNonEmptyBlockCount.get(section);
}
public void setPalette(ChunkSection section, DataPaletteBlock palette) throws NoSuchFieldException, IllegalAccessException {
fieldSection.set(section, palette);
Arrays.fill(section.getEmittedLightArray().asBytes(), (byte) 0);
}
public ChunkSection newChunkSection(int y2, boolean flag, char[] array) {
try {
if (array == null) {
return new ChunkSection(y2, flag);
} else {
return new ChunkSection(y2, flag, array);
}
} catch (Throwable e) {
try {
if (array == null) {
Constructor<ChunkSection> constructor = ChunkSection.class.getDeclaredConstructor(int.class, boolean.class, IBlockData[].class);
return constructor.newInstance(y2, flag, (IBlockData[]) null);
} else {
Constructor<ChunkSection> constructor = ChunkSection.class.getDeclaredConstructor(int.class, boolean.class, char[].class, IBlockData[].class);
return constructor.newInstance(y2, flag, array, (IBlockData[]) null);
}
} catch (Throwable e2) {
throw new RuntimeException(e2);
}
}
}
@Override
public BukkitChunk_1_12 getPrevious(CharFaweChunk fs, ChunkSection[] sections, Map<?, ?> tilesGeneric, Collection<?>[] entitiesGeneric, Set<UUID> createdEntities, boolean all) throws Exception {
Map<BlockPosition, TileEntity> tiles = (Map<BlockPosition, TileEntity>) tilesGeneric;
Collection<Entity>[] entities = (Collection<Entity>[]) entitiesGeneric;
// Copy blocks
BukkitChunk_1_12_Copy previous = new BukkitChunk_1_12_Copy(this, fs.getX(), fs.getZ());
for (int layer = 0; layer < sections.length; layer++) {
if (fs.getCount(layer) != 0 || all) {
ChunkSection section = sections[layer];
if (section != null) {
DataPaletteBlock blocks = section.getBlocks();
byte[] ids = new byte[4096];
NibbleArray data = new NibbleArray();
blocks.exportData(ids, data);
previous.set(layer, ids, data.asBytes());
short solid = (short) fieldNonEmptyBlockCount.getInt(section);
previous.count[layer] = solid;
previous.air[layer] = (short) (4096 - solid);
}
}
}
// Copy tiles
if (tiles != null) {
for (Map.Entry<BlockPosition, TileEntity> entry : tiles.entrySet()) {
TileEntity tile = entry.getValue();
NBTTagCompound tag = new NBTTagCompound();
BlockPosition pos = entry.getKey();
CompoundTag nativeTag = getTag(tile);
previous.setTile(pos.getX() & 15, pos.getY(), pos.getZ() & 15, nativeTag);
}
}
// Copy entities
if (entities != null) {
for (Collection<Entity> entityList : entities) {
for (Entity ent : entityList) {
if (ent instanceof EntityPlayer || (!createdEntities.isEmpty() && createdEntities.contains(ent.getUniqueID()))) {
continue;
}
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];
char[] array = fs.getIdArray(i);
if (array == null) {
continue;
}
int j = FaweCache.CACHE_J[y][z][x];
if (array[j] != 0) {
String id = EntityTypes.b(ent);
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
ent.save(tag); // readEntityIntoTag
CompoundTag nativeTag = (CompoundTag) methodToNative.invoke(adapter, tag);
Map<String, Tag> map = ReflectionUtils.getMap(nativeTag.getValue());
map.put("Id", new StringTag(id));
previous.setEntity(nativeTag);
}
}
}
}
}
return previous;
}
protected BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
@Override
public CompoundTag getTileEntity(net.minecraft.server.v1_12_R1.Chunk chunk, int x, int y, int z) {
Map<BlockPosition, TileEntity> tiles = chunk.getTileEntities();
pos.c(x, y, z);
TileEntity tile = tiles.get(pos);
return tile != null ? getTag(tile) : null;
}
public CompoundTag getTag(TileEntity tile) {
try {
NBTTagCompound tag = new NBTTagCompound();
tile.save(tag); // readTagIntoEntity
return (CompoundTag) methodToNative.invoke(adapter, tag);
} catch (Exception e) {
MainUtil.handleError(e);
return null;
}
}
@Deprecated
public boolean unloadChunk(final String world, final Chunk chunk) {
net.minecraft.server.v1_12_R1.Chunk c = ((CraftChunk) chunk).getHandle();
c.mustSave = false;
if (chunk.isLoaded()) {
chunk.unload(false, false);
}
return true;
}
@Override
public BukkitChunk_1_12 getFaweChunk(int x, int z) {
return new BukkitChunk_1_12(this, x, z);
}
}

View File

@ -0,0 +1,333 @@
package com.boydti.fawe.bukkit.v1_12;
import com.google.common.base.Preconditions;
import com.sk89q.jnbt.ByteArrayTag;
import com.sk89q.jnbt.ByteTag;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.DoubleTag;
import com.sk89q.jnbt.EndTag;
import com.sk89q.jnbt.FloatTag;
import com.sk89q.jnbt.IntArrayTag;
import com.sk89q.jnbt.IntTag;
import com.sk89q.jnbt.ListTag;
import com.sk89q.jnbt.LongTag;
import com.sk89q.jnbt.NBTConstants;
import com.sk89q.jnbt.ShortTag;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.bukkit.adapter.BukkitImplAdapter;
import com.sk89q.worldedit.entity.BaseEntity;
import com.sk89q.worldedit.internal.Constants;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import net.minecraft.server.v1_12_R1.BiomeBase;
import net.minecraft.server.v1_12_R1.BlockPosition;
import net.minecraft.server.v1_12_R1.Entity;
import net.minecraft.server.v1_12_R1.EntityTypes;
import net.minecraft.server.v1_12_R1.MinecraftKey;
import net.minecraft.server.v1_12_R1.NBTBase;
import net.minecraft.server.v1_12_R1.NBTTagByte;
import net.minecraft.server.v1_12_R1.NBTTagByteArray;
import net.minecraft.server.v1_12_R1.NBTTagCompound;
import net.minecraft.server.v1_12_R1.NBTTagDouble;
import net.minecraft.server.v1_12_R1.NBTTagEnd;
import net.minecraft.server.v1_12_R1.NBTTagFloat;
import net.minecraft.server.v1_12_R1.NBTTagInt;
import net.minecraft.server.v1_12_R1.NBTTagIntArray;
import net.minecraft.server.v1_12_R1.NBTTagList;
import net.minecraft.server.v1_12_R1.NBTTagLong;
import net.minecraft.server.v1_12_R1.NBTTagShort;
import net.minecraft.server.v1_12_R1.NBTTagString;
import net.minecraft.server.v1_12_R1.TileEntity;
import net.minecraft.server.v1_12_R1.World;
import net.minecraft.server.v1_12_R1.WorldServer;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.block.Biome;
import org.bukkit.block.Block;
import org.bukkit.craftbukkit.v1_12_R1.CraftWorld;
import org.bukkit.craftbukkit.v1_12_R1.block.CraftBlock;
import org.bukkit.craftbukkit.v1_12_R1.entity.CraftEntity;
import org.bukkit.event.entity.CreatureSpawnEvent;
public final class FaweAdapter_1_12 implements BukkitImplAdapter
{
private final Logger logger = Logger.getLogger(getClass().getCanonicalName());
private final Field nbtListTagListField;
private final Method nbtCreateTagMethod;
public FaweAdapter_1_12() throws NoSuchFieldException, NoSuchMethodException {
this.nbtListTagListField = NBTTagList.class.getDeclaredField("list");
this.nbtListTagListField.setAccessible(true);
this.nbtCreateTagMethod = NBTBase.class.getDeclaredMethod("createTag", new Class[] { Byte.TYPE });
this.nbtCreateTagMethod.setAccessible(true);
}
private static void readTagIntoTileEntity(NBTTagCompound tag, TileEntity tileEntity)
{
tileEntity.a(tag);
}
private static void readTileEntityIntoTag(TileEntity tileEntity, NBTTagCompound tag)
{
tileEntity.save(tag);
}
@Nullable
private static String getEntityId(Entity entity)
{
return EntityTypes.b(entity);
}
@Nullable
private static Entity createEntityFromId(String id, World world)
{
return EntityTypes.a(new MinecraftKey(id), world);
}
private static void readTagIntoEntity(NBTTagCompound tag, Entity entity)
{
entity.f(tag);
}
private static void readEntityIntoTag(Entity entity, NBTTagCompound tag)
{
entity.save(tag);
}
public int getBlockId(Material material)
{
return material.getId();
}
public Material getMaterial(int id)
{
return Material.getMaterial(id);
}
public int getBiomeId(Biome biome)
{
BiomeBase mcBiome = CraftBlock.biomeToBiomeBase(biome);
return mcBiome != null ? BiomeBase.a(mcBiome) : 0;
}
public Biome getBiome(int id)
{
BiomeBase mcBiome = BiomeBase.getBiome(id);
return CraftBlock.biomeBaseToBiome(mcBiome);
}
public BaseBlock getBlock(Location location)
{
Preconditions.checkNotNull(location);
CraftWorld craftWorld = (CraftWorld)location.getWorld();
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
Block bukkitBlock = location.getBlock();
BaseBlock block = new BaseBlock(bukkitBlock.getTypeId(), bukkitBlock.getData());
TileEntity te = craftWorld.getHandle().getTileEntity(new BlockPosition(x, y, z));
if (te != null)
{
NBTTagCompound tag = new NBTTagCompound();
readTileEntityIntoTag(te, tag);
block.setNbtData((CompoundTag)toNative(tag));
}
return block;
}
public boolean setBlock(Location location, BaseBlock block, boolean notifyAndLight)
{
Preconditions.checkNotNull(location);
Preconditions.checkNotNull(block);
CraftWorld craftWorld = (CraftWorld)location.getWorld();
int x = location.getBlockX();
int y = location.getBlockY();
int z = location.getBlockZ();
boolean changed = location.getBlock().setTypeIdAndData(block.getId(), (byte)block.getData(), notifyAndLight);
CompoundTag nativeTag = block.getNbtData();
if (nativeTag != null)
{
TileEntity tileEntity = craftWorld.getHandle().getTileEntity(new BlockPosition(x, y, z));
if (tileEntity != null)
{
NBTTagCompound tag = (NBTTagCompound)fromNative(nativeTag);
tag.set("x", new NBTTagInt(x));
tag.set("y", new NBTTagInt(y));
tag.set("z", new NBTTagInt(z));
readTagIntoTileEntity(tag, tileEntity);
}
}
return changed;
}
public BaseEntity getEntity(org.bukkit.entity.Entity entity)
{
Preconditions.checkNotNull(entity);
CraftEntity craftEntity = (CraftEntity)entity;
Entity mcEntity = craftEntity.getHandle();
String id = getEntityId(mcEntity);
if (id != null) {
NBTTagCompound tag = new NBTTagCompound();
readEntityIntoTag(mcEntity, tag);
CompoundTag weTag = (CompoundTag) toNative(tag);
return new BaseEntity(id, weTag);
}
return null;
}
@Nullable
public org.bukkit.entity.Entity createEntity(Location location, BaseEntity state)
{
Preconditions.checkNotNull(location);
Preconditions.checkNotNull(state);
CraftWorld craftWorld = (CraftWorld)location.getWorld();
WorldServer worldServer = craftWorld.getHandle();
Entity createdEntity = createEntityFromId(state.getTypeId(), craftWorld.getHandle());
if (createdEntity != null)
{
CompoundTag nativeTag = state.getNbtData();
if (nativeTag != null)
{
NBTTagCompound tag = (NBTTagCompound)fromNative(nativeTag);
for (String name : Constants.NO_COPY_ENTITY_NBT_FIELDS) {
tag.remove(name);
}
readTagIntoEntity(tag, createdEntity);
}
createdEntity.setLocation(location.getX(), location.getY(), location.getZ(), location.getYaw(), location.getPitch());
worldServer.addEntity(createdEntity, CreatureSpawnEvent.SpawnReason.CUSTOM);
return createdEntity.getBukkitEntity();
}
return null;
}
public Tag toNative(NBTBase foreign) {
if (foreign == null) {
return null;
}
if (foreign instanceof NBTTagCompound) {
Map<String, Tag> values = new HashMap<String, Tag>();
Set<String> foreignKeys = ((NBTTagCompound) foreign).c(); // map.keySet
for (String str : foreignKeys) {
NBTBase base = ((NBTTagCompound) foreign).get(str);
values.put(str, toNative(base));
}
return new CompoundTag(values);
} else if (foreign instanceof NBTTagByte) {
return new ByteTag(((NBTTagByte) foreign).g()); // getByte
} else if (foreign instanceof NBTTagByteArray) {
return new ByteArrayTag(((NBTTagByteArray) foreign).c()); // data
} else if (foreign instanceof NBTTagDouble) {
return new DoubleTag(((NBTTagDouble) foreign).asDouble()); // getDouble
} else if (foreign instanceof NBTTagFloat) {
return new FloatTag(((NBTTagFloat) foreign).i()); // getFloat
} else if (foreign instanceof NBTTagInt) {
return new IntTag(((NBTTagInt) foreign).e()); // getInt
} else if (foreign instanceof NBTTagIntArray) {
return new IntArrayTag(((NBTTagIntArray) foreign).d()); // data
} else if (foreign instanceof NBTTagList) {
try {
return toNativeList((NBTTagList) foreign);
} catch (Throwable e) {
logger.log(Level.WARNING, "Failed to convert NBTTagList", e);
return new ListTag(ByteTag.class, new ArrayList<ByteTag>());
}
} else if (foreign instanceof NBTTagLong) {
return new LongTag(((NBTTagLong) foreign).d()); // getLong
} else if (foreign instanceof NBTTagShort) {
return new ShortTag(((NBTTagShort) foreign).f()); // getShort
} else if (foreign instanceof NBTTagString) {
return new StringTag(((NBTTagString) foreign).c_()); // data
} else if (foreign instanceof NBTTagEnd) {
return new EndTag();
} else {
throw new IllegalArgumentException("Don't know how to make native " + foreign.getClass().getCanonicalName());
}
}
public ListTag toNativeList(NBTTagList foreign) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
List<Tag> values = new ArrayList<Tag>();
int type = foreign.g();
List foreignList;
foreignList = (List) nbtListTagListField.get(foreign);
for (int i = 0; i < foreign.size(); i++) {
NBTBase element = (NBTBase) foreignList.get(i);
values.add(toNative(element)); // List elements shouldn't have names
}
Class<? extends Tag> cls = NBTConstants.getClassFromType(type);
return new ListTag(cls, values);
}
public NBTBase fromNative(Tag foreign) {
if (foreign == null) {
return null;
}
if (foreign instanceof CompoundTag) {
NBTTagCompound tag = new NBTTagCompound();
for (Map.Entry<String, Tag> entry : ((CompoundTag) foreign)
.getValue().entrySet()) {
tag.set(entry.getKey(), fromNative(entry.getValue()));
}
return tag;
} else if (foreign instanceof ByteTag) {
return new NBTTagByte(((ByteTag) foreign).getValue());
} else if (foreign instanceof ByteArrayTag) {
return new NBTTagByteArray(((ByteArrayTag) foreign).getValue());
} else if (foreign instanceof DoubleTag) {
return new NBTTagDouble(((DoubleTag) foreign).getValue());
} else if (foreign instanceof FloatTag) {
return new NBTTagFloat(((FloatTag) foreign).getValue());
} else if (foreign instanceof IntTag) {
return new NBTTagInt(((IntTag) foreign).getValue());
} else if (foreign instanceof IntArrayTag) {
return new NBTTagIntArray(((IntArrayTag) foreign).getValue());
} else if (foreign instanceof ListTag) {
NBTTagList tag = new NBTTagList();
ListTag foreignList = (ListTag) foreign;
for (Tag t : foreignList.getValue()) {
tag.add(fromNative(t));
}
return tag;
} else if (foreign instanceof LongTag) {
return new NBTTagLong(((LongTag) foreign).getValue());
} else if (foreign instanceof ShortTag) {
return new NBTTagShort(((ShortTag) foreign).getValue());
} else if (foreign instanceof StringTag) {
return new NBTTagString(((StringTag) foreign).getValue());
} else if (foreign instanceof EndTag) {
try {
return (NBTBase) nbtCreateTagMethod.invoke(null, (byte) 0);
} catch (Exception e) {
return null;
}
} else {
throw new IllegalArgumentException("Don't know how to make NMS " + foreign.getClass().getCanonicalName());
}
}
}

View File

@ -0,0 +1,26 @@
package com.boydti.fawe.bukkit.v1_12;
import java.util.Arrays;
import net.minecraft.server.v1_12_R1.GenLayer;
import net.minecraft.server.v1_12_R1.IntCache;
public class MutableGenLayer extends GenLayer {
private int biome;
public MutableGenLayer(long seed) {
super(seed);
}
public MutableGenLayer set(int biome) {
this.biome = biome;
return this;
}
@Override
public int[] a(int areaX, int areaY, int areaWidth, int areaHeight) {
int[] biomes = IntCache.a(areaWidth * areaHeight);
Arrays.fill(biomes, biome);
return biomes;
}
}

View File

@ -10,7 +10,7 @@ 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 java.util.concurrent.atomic.LongAdder;
import com.boydti.fawe.object.visitor.FaweChunkVisitor;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.MathMan;

View File

@ -35,7 +35,7 @@ import com.sk89q.worldedit.command.BrushCommands;
import com.sk89q.worldedit.command.ChunkCommands;
import com.sk89q.worldedit.command.ClipboardCommands;
import com.sk89q.worldedit.command.FlattenedClipboardTransform;
import com.sk89q.worldedit.command.GeneralCommands;
import com.sk89q.worldedit.command.OptionsCommands;
import com.sk89q.worldedit.command.GenerationCommands;
import com.sk89q.worldedit.command.HistoryCommands;
import com.sk89q.worldedit.command.NavigationCommands;
@ -46,7 +46,7 @@ import com.sk89q.worldedit.command.SnapshotCommands;
import com.sk89q.worldedit.command.SnapshotUtilCommands;
import com.sk89q.worldedit.command.SuperPickaxeCommands;
import com.sk89q.worldedit.command.ToolCommands;
import com.sk89q.worldedit.command.ToolUtilCommands;
import com.sk89q.worldedit.command.BrushOptionsCommands;
import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.command.WorldEditCommands;
import com.sk89q.worldedit.command.composition.SelectionCommand;
@ -77,6 +77,8 @@ import com.sk89q.worldedit.extent.transform.BlockTransformExtent;
import com.sk89q.worldedit.function.block.BlockReplace;
import com.sk89q.worldedit.function.block.ExtentBlockCopy;
import com.sk89q.worldedit.function.entity.ExtentEntityCopy;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.BlockMask;
import com.sk89q.worldedit.function.mask.FuzzyBlockMask;
import com.sk89q.worldedit.function.mask.Mask;
@ -87,6 +89,7 @@ import com.sk89q.worldedit.function.mask.SolidBlockMask;
import com.sk89q.worldedit.function.operation.ChangeSetExecutor;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.BlockPattern;
import com.sk89q.worldedit.function.pattern.ClipboardPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
@ -115,6 +118,7 @@ import com.sk89q.worldedit.session.PasteBuilder;
import com.sk89q.worldedit.session.SessionManager;
import com.sk89q.worldedit.session.request.Request;
import com.sk89q.worldedit.util.command.SimpleDispatcher;
import com.sk89q.worldedit.util.command.fluent.DispatcherNode;
import com.sk89q.worldedit.util.command.parametric.ParameterData;
import com.sk89q.worldedit.util.command.parametric.ParametricBuilder;
import com.sk89q.worldedit.util.command.parametric.ParametricCallable;
@ -133,6 +137,7 @@ import java.lang.management.MemoryUsage;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
@ -423,8 +428,6 @@ public class Fawe {
*/
try {
// Setting up commands.yml
Commands.load(new File(INSTANCE.IMP.getDirectory(), "commands.yml"));
Commands.inject(); // Translations
EditSession.inject(); // Custom block placer + optimizations
EditSessionEvent.inject(); // Add EditSession to event (API)
LocalSession.inject(); // Add remember order / queue flushing / Optimizations for disk / brush visualization
@ -433,6 +436,8 @@ public class Fawe {
AbstractPlayerActor.inject(); // Don't use exception for getBlockInHand control flow
Request.inject(); // Custom pattern extent
// Commands
Commands.load(new File(INSTANCE.IMP.getDirectory(), "commands.yml"));
Commands.inject(); // Translations
BiomeCommands.inject(); // Translations + Optimizations
ChunkCommands.inject(); // Translations + Optimizations
GenerationCommands.inject(); // Translations + Optimizations
@ -453,8 +458,9 @@ public class Fawe {
ParametricBuilder.inject(); // Translations
ParametricCallable.inject(); // Translations
ParameterData.inject(); // Translations
ToolUtilCommands.inject(); // Fixes + Translations
GeneralCommands.inject(); // Translations + gmask args
BrushOptionsCommands.inject(); // Fixes + Translations
OptionsCommands.inject(); // Translations + gmask args
DispatcherNode.inject(); // Method command delegate
// Formatting
MessageBox.inject();
Fragment.inject();
@ -521,6 +527,7 @@ public class Fawe {
HashTagPatternParser.inject(); // Add new patterns
DefaultBlockParser.inject(); // Fix block lookups
BlockPattern.inject(); // Optimization
AbstractPattern.inject();
// Mask
Mask.inject(); // Extend deprecated mask
BlockMask.inject(); // Optimizations
@ -530,6 +537,8 @@ public class Fawe {
DefaultMaskParser.inject(); // Add new masks
Masks.inject(); // Optimizations
MaskUnion.inject(); // Optimizations
AbstractMask.inject(); // Serializing
AbstractExtentMask.inject(); // Serializing
// Operations
Operations.inject(); // Optimizations
ExtentBlockCopy.inject(); // Optimizations
@ -688,19 +697,26 @@ public class Fawe {
}
private ConcurrentHashMap<String, FawePlayer> players = new ConcurrentHashMap<>(8, 0.9f, 1);
private ConcurrentHashMap<UUID, FawePlayer> playersUUID = new ConcurrentHashMap<>(8, 0.9f, 1);
public <T> void register(FawePlayer<T> player) {
players.put(player.getName(), player);
playersUUID.put(player.getUUID(), player);
}
public <T> void unregister(String name) {
players.remove(name);
FawePlayer player = players.remove(name);
if (player != null) playersUUID.remove(player.getUUID());
}
public FawePlayer getCachedPlayer(String name) {
return players.get(name);
}
public FawePlayer getCachedPlayer(UUID uuid) {
return playersUUID.get(uuid);
}
public Collection<FawePlayer> getCachedPlayers() {
return players.values();
}

View File

@ -54,7 +54,7 @@ import java.util.concurrent.TimeUnit;
import static com.google.common.base.Preconditions.checkNotNull;
@Command(aliases = "/anvil", desc = "Manipulate billions of blocks: [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/Anvil-API)")
@Command(aliases = {"anvil", "/anvil"}, desc = "Manipulate billions of blocks: [More Info](https://github.com/boy0001/FastAsyncWorldedit/wiki/Anvil-API)")
public class AnvilCommands {
private final WorldEdit worldEdit;

View File

@ -109,35 +109,18 @@ public enum BBC {
BRUSH_RESET("Reset your brush.", "WorldEdit.Brush"),
BRUSH_NONE("You aren't holding a brush!", "WorldEdit.Brush"),
BRUSH_SCROLL_ACTION_SET("Set scroll action to %s0", "WorldEdit.Brush"),
BRUSH_SCROLL_ACTION_UNSET("Removed scrol action", "WorldEdit.Brush"),
BRUSH_VISUAL_MODE_SET("Set visual mode to %s0", "WorldEdit.Brush"),
BRUSH_TARGET_MODE_SET("Set target mode to %s0", "WorldEdit.Brush"),
BRUSH_BUTCHER("Butcher brush equiped (%s0)", "WorldEdit.Brush"),
BRUSH_CLIPBOARD("Clipboard brush shape equipped", "WorldEdit.Brush"),
BRUSH_CYLINDER("Cylinder brush shape equipped (%s0 by %s1).", "WorldEdit.Brush"),
BRUSH_EXTINGUISHER("Extinguisher equipped (%s0).", "WorldEdit.Brush"),
BRUSH_GRAVITY("Gravity brush equipped (%s0)", "WorldEdit.Brush"),
BRUSH_HEIGHT("Height brush equipped (%s0)", "WorldEdit.Brush"),
BRUSH_EQUIPPED("Equipped brush %s0", "WorldEdit.Brush"),
BRUSH_TRY_OTHER("&cThere are other more suitable brushes e.g.\n&8 - &7//br height [radius=5] [#clipboard|file=null] [rotation=0] [yscale=1.00]", "WorldEdit.Brush"),
BRUSH_COPY("Copy brush equipped (%s0). Left click the base of an object to copy, right click to paste. Increase the brush radius if necessary.", "WorldEdit.Brush"),
BRUSH_COMMAND("Command brush equipped (%s0)", "WorldEdit.Brush"),
BRUSH_COPY("Left click the base of an object to copy, right click to paste. Increase the brush radius if necessary.", "WorldEdit.Brush"),
BRUSH_HEIGHT_INVALID("Invalid height map file (%s0)", "WorldEdit.Brush"),
BRUSH_SMOOTH("Smooth brush equipped (%s0 x %s1 using %s2. Note: Use the blend brush if you want to smooth overhangs or caves.).", "WorldEdit.Brush"),
BRUSH_SPHERE("Sphere brush shape equipped (%s0).", "WorldEdit.Brush"),
BRUSH_SCATTER("Scatter brush shape equipped (%s0, %s1).", "WorldEdit.Brush"),
BRUSH_SHATTER("Shatter brush shape equipped (%s0, %s1).", "WorldEdit.Brush"),
BRUSH_POPULATE("Populate brush shape equipped (%s0, %s1).", "WorldEdit.Brush"),
BRUSH_LAYER("Layer brush shape equipped (%s0, %s1).", "WorldEdit.Brush"),
BRUSH_STENCIL("Stencil brush equipped (%s0).", "WorldEdit.Brush"),
BRUSH_SURFACE("Surface brush equipped (%s0).", "WorldEdit.Brush"),
BRUSH_LINE("Line brush shape equipped (%s0).", "WorldEdit.Brush"),
BRUSH_SPLINE("Spline brush shape equipped (%s0). Right click an end to add a shape", "WorldEdit.Brush"),
BRUSH_SMOOTH("Note: Use the blend brush if you want to smooth overhangs or caves.", "WorldEdit.Brush"),
BRUSH_SPLINE("Click to add a point, click the same spot to finish", "WorldEdit.Brush"),
BRUSH_SPLINE_PRIMARY_2("Added position, Click the same spot to join!", "WorldEdit.Brush"),
BRUSH_SPLINE_SECONDARY_ERROR("Not enough positions set!", "WorldEdit.Brush"),
BRUSH_SPLINE_SECONDARY("Created spline", "WorldEdit.Brush"),
BRUSH_BLEND_BALL("Blend ball brush equipped (%s0).", "WorldEdit.Brush"),
BRUSH_ERODE("Erode brush equipped (%s0). Right click to erode, left click to pull.", "WorldEdit.Brush"),
BRUSH_CIRCLE("Circle brush equipped (%s0). Right click to create a circle.", "WorldEdit.Brush"),
BRUSH_RECURSIVE("Recursive brush equipped (%s0).", "WorldEdit.Brush"),
BRUSH_SIZE("Brush size set", "WorldEdit.Brush"),
BRUSH_RANGE("Brush size set", "WorldEdit.Brush"),
BRUSH_MASK_DISABLED("Brush mask disabled", "WorldEdit.Brush"),
@ -190,12 +173,13 @@ public enum BBC {
SCHEMATIC_DELETE("%s0 has been deleted.", "Worldedit.Schematic"),
SCHEMATIC_FORMAT("Available clipboard formats (Name: Lookup names)", "Worldedit.Schematic"),
SCHEMATIC_FORMAT("Available formats (Name: Lookup names)", "Worldedit.Schematic"),
SCHEMATIC_LOADED("%s0 loaded. Paste it with //paste", "Worldedit.Schematic"),
SCHEMATIC_SAVED("%s0 saved.", "Worldedit.Schematic"),
SCHEMATIC_PAGE("Page must be %s", "WorldEdit.Schematic"),
SCHEMATIC_NONE("No schematics found.", "WorldEdit.Schematic"),
SCHEMATIC_LIST("Available schematics (Filename: Format) [%s0/%s1]:", "Worldedit.Schematic"),
SCHEMATIC_NONE("No files found.", "WorldEdit.Schematic"),
SCHEMATIC_LIST("Available files (Filename: Format) [%s0/%s1]:", "Worldedit.Schematic"),
SCHEMATIC_LIST_ELEM("&8 - &a%s0 &8- &7%s1", "Worldedit.Schematic"),
CLIPBOARD_CLEARED("Clipboard cleared", "WorldEdit.Clipboard"),
CLIPBOARD_INVALID_FORMAT("Unknown clipboard format: %s0", "WorldEdit.Clipboard"),
@ -232,6 +216,8 @@ public enum BBC {
COMMAND_SYNTAX("&cUsage: &7%s0", "Error"),
NO_PERM("&cYou are lacking the permission node: %s0", "Error"),
SETTING_DISABLE("&cLacking setting: %s0","Error"),
BRUSH_NOT_FOUND("&cAvailable brushes: %s0", "Error"),
BRUSH_INCOMPATIBLE("&cBrush not compatible with this version", "Error"),
SCHEMATIC_NOT_FOUND("&cSchematic not found: &7%s0", "Error"),
NO_REGION("&cYou have no current allowed region", "Error"),
NO_MASK("&cYou have no current mask set", "Error"),
@ -316,16 +302,6 @@ public enum BBC {
TIP_ROTATE("Tip: Orientate with &c//rotate", "Tips"),
TIP_COPY_PATTERN("Tip: To use as a pattern try &c#copy", "Tips"),
// brush
TIP_BRUSH_SPLINE("&7Tip The spline &c//brush &7connects multiple shapes together", "Tips"),
TIP_BRUSH_HEIGHT("&7Tip: The height &c//brush &7smoothly raises or lowers terrain", "Tips"),
TIP_BRUSH_COPY("&7Tip: The copypaste &c//brush &7allows you to easily copy and paste objects", "Tips"),
TIP_BRUSH_MASK("&7Tip: Set a brush destination mask with &c/mask", "Tips"),
TIP_BRUSH_MASK_SOURCE("&7Tip: Set a brush source mask with &c/smask", "Tips"),
TIP_BRUSH_TRANSFORM("&7Tip: Set a brush transform with &c/transform", "Tips"),
TIP_BRUSH_RELATIVE("&7Tip: Use a relative clipboard pattern with //br sphere #~[#copy]", "Tips"),
TIP_BRUSH_COMMAND("&7Tip: Try the command brush &c//br cmd <radius> <cmd1;cmd2>", "Tips"),
// regen
TIP_REGEN_0("Tip: Use a biome with /regen [biome]", "Tips"),
TIP_REGEN_1("Tip: Use a seed with /regen [biome] [seed]", "Tips"),

View File

@ -323,13 +323,13 @@ public class Settings extends Config {
@Comment("Enable the limiter")
public boolean ENABLED = true;
@Comment("The interval in ticks")
public int INTERVAL = 1;
public int INTERVAL = 20;
@Comment("Max falling blocks per interval (per chunk)")
public int FALLING = 512;
public int FALLING = 64;
@Comment("Max physics per interval (per chunk)")
public int PHYSICS = 512;
public int PHYSICS = 8192;
@Comment("Max item spawns per interval (per chunk)")
public int ITEMS = 128;
public int ITEMS = 64;
}
public static class CLIPBOARD {

View File

@ -1,18 +1,238 @@
package com.boydti.fawe.object.brush;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.brush.scroll.ScrollAction;
import com.boydti.fawe.object.extent.ResettableExtent;
import com.sk89q.minecraft.util.commands.CommandException;
import com.sk89q.minecraft.util.commands.CommandLocals;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.tool.BrushTool;
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.input.ParserContext;
import com.sk89q.worldedit.extension.platform.Actor;
import com.sk89q.worldedit.extension.platform.CommandManager;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.util.command.CommandCallable;
import com.sk89q.worldedit.util.command.Dispatcher;
import com.sk89q.worldedit.util.command.ProcessedCallable;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
public class BrushSettings {
public Brush brush = null;
public Mask mask = null;
public Mask sourceMask = null;
public ResettableExtent transform = null;
public Pattern material;
public double size = 1;
public String permission;
public ScrollAction scrollAction;
public enum SettingType {
BRUSH,
SIZE,
MASK,
SOURCE_MASK,
TRANSFORM,
FILL,
PERMISSIONS,
SCROLL_ACTION,
}
private Map<SettingType, Object> constructor = new ConcurrentHashMap<>();
private Brush brush = null;
private Mask mask = null;
private Mask sourceMask = null;
private ResettableExtent transform = null;
private Pattern material;
private double size = 1;
private Set<String> permissions;
private ScrollAction scrollAction;
public BrushSettings() {
this.permissions = new HashSet<>();
this.constructor.put(SettingType.PERMISSIONS, permissions);
}
public static BrushSettings get(BrushTool tool, Player player, LocalSession session, Map<String, Object> settings) throws CommandException, InputParseException {
Dispatcher dispatcher = CommandManager.getInstance().getDispatcher();
Dispatcher brushDispatcher = (Dispatcher) (dispatcher.get("brush").getCallable());
if (brushDispatcher == null) {
return null;
}
String constructor = (String) settings.get(SettingType.BRUSH.name());
if (constructor == null) {
return new BrushSettings();
}
String[] split = constructor.split(" ");
CommandCallable sphereCommand = ((ProcessedCallable) brushDispatcher.get(split[0]).getCallable()).getParent();
CommandLocals locals = new CommandLocals();
locals.put(Actor.class, player);
String args = constructor.substring(constructor.indexOf(' ') + 1);
String[] parentArgs = new String[]{"brush", split[0]};
BrushSettings bs = (BrushSettings) sphereCommand.call(args, locals, parentArgs);
if (settings.containsKey(SettingType.PERMISSIONS.name())) {
bs.permissions.addAll((Collection<? extends String>) settings.get(SettingType.PERMISSIONS.name()));
}
if (settings.containsKey(SettingType.SIZE.name())) {
bs.size = (double) settings.get(SettingType.SIZE.name());
}
ParserContext parserContext = new ParserContext();
parserContext.setActor(player);
parserContext.setWorld(player.getWorld());
parserContext.setSession(session);
if (settings.containsKey(SettingType.MASK.name())) {
String maskArgs = (String) settings.get(SettingType.MASK.name());
Mask mask = WorldEdit.getInstance().getMaskFactory().parseFromInput(maskArgs, parserContext);
bs.setMask(mask);
bs.constructor.put(SettingType.MASK, maskArgs);
}
if (settings.containsKey(SettingType.SOURCE_MASK.name())) {
String maskArgs = (String) settings.get(SettingType.SOURCE_MASK.name());
Mask mask = WorldEdit.getInstance().getMaskFactory().parseFromInput(maskArgs, parserContext);
bs.setSourceMask(mask);
bs.constructor.put(SettingType.SOURCE_MASK, maskArgs);
}
if (settings.containsKey(SettingType.TRANSFORM.name())) {
String transformArgs = (String) settings.get(SettingType.TRANSFORM.name());
ResettableExtent extent = Fawe.get().getTransformParser().parseFromInput(transformArgs, parserContext);
bs.setTransform(extent);
bs.constructor.put(SettingType.TRANSFORM, transformArgs);
}
if (settings.containsKey(SettingType.FILL.name())) {
String fillArgs = (String) settings.get(SettingType.FILL.name());
Pattern pattern = WorldEdit.getInstance().getPatternFactory().parseFromInput(fillArgs, parserContext);
bs.setFill(pattern);
bs.constructor.put(SettingType.FILL, fillArgs);
}
if (settings.containsKey(SettingType.SCROLL_ACTION.name())) {
String actionArgs = (String) settings.get(SettingType.SCROLL_ACTION.name());
ScrollAction action = ScrollAction.fromArguments(tool, player, session, actionArgs, false);
if (action != null) {
bs.setScrollAction(action);
bs.constructor.put(SettingType.SCROLL_ACTION, actionArgs);
}
}
return bs;
}
public BrushSettings setBrush(Brush brush) {
this.brush = brush;
return this;
}
public BrushSettings clear() {
brush = null;
mask = null;
sourceMask = null;
transform = null;
material = null;
scrollAction = null;
size = 1;
permissions.clear();
constructor.clear();
return this;
}
public BrushSettings addSetting(SettingType type, String args) {
constructor.put(type, args);
return this;
}
public Map<SettingType, Object> getSettings() {
return Collections.unmodifiableMap(constructor);
}
public BrushSettings setMask(Mask mask) {
if (mask == null) constructor.remove(SettingType.MASK);
this.mask = mask;
return this;
}
public BrushSettings setSourceMask(Mask mask) {
if (mask == null) constructor.remove(SettingType.SOURCE_MASK);
this.sourceMask = mask;
return this;
}
public BrushSettings setTransform(ResettableExtent transform) {
if (transform == null) constructor.remove(SettingType.TRANSFORM);
this.transform = transform;
return this;
}
public BrushSettings setFill(Pattern pattern) {
if (pattern == null) constructor.remove(SettingType.FILL);
this.material = pattern;
return this;
}
public BrushSettings setSize(double size) {
this.size = size;
if (size == -1) {
constructor.remove(SettingType.SIZE);
} else {
constructor.put(SettingType.SIZE, size);
}
return this;
}
public BrushSettings setScrollAction(ScrollAction scrollAction) {
if (scrollAction == null) constructor.remove(SettingType.SCROLL_ACTION);
this.scrollAction = scrollAction;
return this;
}
public BrushSettings addPermission(String permission) {
this.permissions.add(permission);
return this;
}
public BrushSettings addPermissions(String... perms) {
for (String perm : perms) permissions.add(perm);
return this;
}
public Brush getBrush() {
return brush;
}
public Mask getMask() {
return mask;
}
public Mask getSourceMask() {
return sourceMask;
}
public ResettableExtent getTransform() {
return transform;
}
public Pattern getMaterial() {
return material;
}
public double getSize() {
return size;
}
public Set<String> getPermissions() {
return Collections.unmodifiableSet(permissions);
}
public ScrollAction getScrollAction() {
return scrollAction;
}
public boolean canUse(Actor actor) {
for (String perm : getPermissions()) {
if (actor.hasPermission(perm)) return true;
}
return false;
}
}

View File

@ -1,10 +1,81 @@
package com.boydti.fawe.object.brush.scroll;
import com.boydti.fawe.config.BBC;
import com.sk89q.worldedit.LocalConfiguration;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.command.tool.BrushTool;
import com.sk89q.worldedit.entity.Player;
import com.sk89q.worldedit.extension.input.InputParseException;
import com.sk89q.worldedit.extension.input.ParserContext;
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 java.io.IOException;
public abstract class ScrollAction implements ScrollTool {
private BrushTool tool;
public static ScrollAction fromArguments(BrushTool tool, Player player, LocalSession session, String arguments, boolean message) throws InputParseException {
ParserContext parserContext = new ParserContext();
parserContext.setActor(player);
parserContext.setWorld(player.getWorld());
parserContext.setSession(session);
final LocalConfiguration config = WorldEdit.getInstance().getConfiguration();
String[] split = arguments.split(" ");
switch (split[0].toLowerCase()) {
case "none":
return null;
case "clipboard":
if (split.length != 2) {
if (message) BBC.COMMAND_SYNTAX.send(player, "clipboard [file]");
return null;
}
String filename = split[1];
try {
ClipboardHolder[] clipboards = ClipboardFormat.SCHEMATIC.loadAllFromInput(player, player.getWorld().getWorldData(), filename, message);
if (clipboards == null) {
return null;
}
return (new ScrollClipboard(tool, session, clipboards));
} catch (IOException e) {
throw new RuntimeException(e);
}
case "mask":
if (split.length < 2) {
if (message) BBC.COMMAND_SYNTAX.send(player, "mask [mask 1] [mask 2] [mask 3]...");
return null;
}
Mask[] masks = new Mask[split.length - 1];
for (int i = 1; i < split.length; i++) {
String arg = split[i];
masks[i - 1] = WorldEdit.getInstance().getMaskFactory().parseFromInput(arg, parserContext);
}
return (new ScrollMask(tool, masks));
case "pattern":
if (split.length < 2) {
if (message) BBC.COMMAND_SYNTAX.send(player, "pattern [pattern 1] [pattern 2] [pattern 3]...");
return null;
}
Pattern[] patterns = new Pattern[split.length - 1];
for (int i = 1; i < split.length; i++) {
String arg = split[i];
patterns[i - 1] = WorldEdit.getInstance().getPatternFactory().parseFromInput(arg, parserContext);
}
return (new ScrollPattern(tool, patterns));
case "range":
return (new ScrollRange(tool));
case "size":
return (new ScrollSize(tool));
case "target":
return (new ScrollTarget(tool));
default:
return null;
}
}
public ScrollAction(BrushTool tool) {
this.tool = tool;
}

View File

@ -11,7 +11,6 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
public class BlockTranslateExtent extends AbstractDelegateExtent {
private final int dx,dy,dz;
private final Extent extent;
private MutableBlockVector mutable = new MutableBlockVector();
public BlockTranslateExtent(Extent extent, int dx, int dy, int dz) {
@ -19,7 +18,6 @@ public class BlockTranslateExtent extends AbstractDelegateExtent {
this.dx = dx;
this.dy = dy;
this.dz = dz;
this.extent = extent;
}
@Override
@ -27,7 +25,7 @@ public class BlockTranslateExtent extends AbstractDelegateExtent {
mutable.mutX((location.getX() + dx));
mutable.mutY((location.getY() + dy));
mutable.mutZ((location.getZ() + dz));
return extent.setBlock(mutable, block);
return getExtent().setBlock(mutable, block);
}
@Override
@ -35,7 +33,7 @@ public class BlockTranslateExtent extends AbstractDelegateExtent {
mutable.mutX(x + dx);
mutable.mutY(y + dy);
mutable.mutZ(z + dz);
return extent.setBlock(mutable, block);
return getExtent().setBlock(mutable, block);
}
@Override

View File

@ -2,17 +2,13 @@ package com.boydti.fawe.object.extent;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import java.util.Arrays;
import java.util.Collection;
public class Linear3DTransform extends SelectTransform {
private final Collection<ResettableExtent> extents;
private final ResettableExtent[] extentsArray;
public Linear3DTransform(ResettableExtent[] extents) {
this.extentsArray = extents;
this.extents = Arrays.asList(extents);
}
@Override

View File

@ -2,18 +2,14 @@ package com.boydti.fawe.object.extent;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import java.util.Arrays;
import java.util.Collection;
public class LinearTransform extends SelectTransform {
private final Collection<ResettableExtent> extents;
private final ResettableExtent[] extentsArray;
private int index;
public LinearTransform(ResettableExtent[] extents) {
this.extentsArray = extents;
this.extents = Arrays.asList(extents);
}
@Override

View File

@ -13,20 +13,20 @@ import java.util.Collection;
import javax.annotation.Nullable;
public class MultiTransform extends RandomTransform {
private AbstractDelegateExtent[] extents;
private ResettableExtent[] extents;
public MultiTransform(Collection<ResettableExtent> extents) {
for (ResettableExtent extent : extents) add(extent, 1);
}
public MultiTransform() {
this.extents = new AbstractDelegateExtent[0];
this.extents = new ResettableExtent[0];
}
@Override
public void add(ResettableExtent extent, double chance) {
super.add(extent, chance);
this.extents = getExtents().toArray(new AbstractDelegateExtent[getExtents().size()]);
this.extents = getExtents().toArray(new ResettableExtent[getExtents().size()]);
}
@Override
public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {

View File

@ -10,7 +10,7 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
public class OffsetExtent extends ResettableExtent {
private final int dx, dy, dz;
private MutableBlockVector2D mutable = new MutableBlockVector2D();
private transient MutableBlockVector2D mutable = new MutableBlockVector2D();
public OffsetExtent(Extent parent, int dx, int dy, int dz) {
super(parent);
@ -33,4 +33,10 @@ public class OffsetExtent extends ResettableExtent {
public boolean setBlock(int x, int y, int z, BaseBlock block) throws WorldEditException {
return getExtent().setBlock(x + dx, y + dy, z + dz, block);
}
@Override
public ResettableExtent setExtent(Extent extent) {
mutable = new MutableBlockVector2D();
return super.setExtent(extent);
}
}

View File

@ -11,9 +11,9 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
public class PositionTransformExtent extends ResettableExtent {
private final MutableBlockVector mutable = new MutableBlockVector();
private transient MutableBlockVector mutable = new MutableBlockVector();
private transient Vector min;
private Transform transform;
private Vector min;
public PositionTransformExtent(Extent parent, Transform transform) {
super(parent);
@ -22,6 +22,7 @@ public class PositionTransformExtent extends ResettableExtent {
@Override
public ResettableExtent setExtent(Extent extent) {
mutable = new MutableBlockVector();
min = null;
return super.setExtent(extent);
}

View File

@ -10,9 +10,10 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
import java.util.SplittableRandom;
public class RandomOffsetTransform extends ResettableExtent {
private transient SplittableRandom random;
private transient MutableBlockVector2D mutable = new MutableBlockVector2D();
private final int dx, dy, dz;
private final SplittableRandom random;
private MutableBlockVector2D mutable = new MutableBlockVector2D();
public RandomOffsetTransform(Extent parent, int dx, int dy, int dz) {
super(parent);
@ -47,6 +48,8 @@ public class RandomOffsetTransform extends ResettableExtent {
@Override
public ResettableExtent setExtent(Extent extent) {
random = new SplittableRandom();
mutable = new MutableBlockVector2D();
return super.setExtent(extent);
}
}

View File

@ -19,10 +19,11 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public class RandomTransform extends SelectTransform {
private final SimpleRandom random;
private SimpleRandom random;
private Map<ResettableExtent, Double> weights = new HashMap<>();
private RandomCollection<ResettableExtent> collection;
private LinkedHashSet<ResettableExtent> extents = new LinkedHashSet<>();
private transient RandomCollection<ResettableExtent> collection;
private transient LinkedHashSet<ResettableExtent> extents = new LinkedHashSet<>();
public RandomTransform() {
this(new TrueRandom());
@ -44,6 +45,10 @@ public class RandomTransform extends SelectTransform {
@Override
public ResettableExtent setExtent(Extent extent) {
if (collection == null) {
collection = RandomCollection.of(weights, random);
extents = new LinkedHashSet<>(weights.keySet());
}
for (AbstractDelegateExtent current : extents) {
if (current instanceof ResettableExtent) {
((ResettableExtent) current).setExtent(extent);

View File

@ -1,14 +1,18 @@
package com.boydti.fawe.object.extent;
import com.boydti.fawe.util.ExtentTraverser;
import com.boydti.fawe.util.ReflectionUtils;
import com.sk89q.worldedit.extent.AbstractDelegateExtent;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.World;
import java.io.IOException;
import java.io.Serializable;
import java.lang.reflect.Field;
import static com.google.common.base.Preconditions.checkNotNull;
public class ResettableExtent extends AbstractDelegateExtent {
public class ResettableExtent extends AbstractDelegateExtent implements Serializable {
public ResettableExtent(Extent parent) {
super(parent);
}
@ -23,4 +27,26 @@ public class ResettableExtent extends AbstractDelegateExtent {
}
return this;
}
private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
Extent extent = getExtent();
boolean next = extent instanceof ResettableExtent;
stream.writeBoolean(next);
if (next) {
stream.writeObject(extent);
}
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
if (stream.readBoolean()) {
try {
Field field = AbstractDelegateExtent.class.getDeclaredField("extent");
ReflectionUtils.setFailsafeFieldValue(field, this, stream.readObject());
} catch (Throwable e) {
e.printStackTrace();
}
}
}
}

View File

@ -13,11 +13,12 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
import javax.annotation.Nullable;
public class ScaleTransform extends ResettableExtent {
private final MutableBlockVector mutable = new MutableBlockVector();
private final double dx,dy,dz;
private int maxy;
private transient MutableBlockVector mutable = new MutableBlockVector();
private transient int maxy;
private transient Vector min;
private final double dx,dy,dz;
private Vector min;
public ScaleTransform(Extent parent, double dx, double dy, double dz) {
super(parent);
@ -31,6 +32,7 @@ public class ScaleTransform extends ResettableExtent {
public ResettableExtent setExtent(Extent extent) {
min = null;
maxy = extent.getMaximumPoint().getBlockY();
mutable = new MutableBlockVector();
return super.setExtent(extent);
}
@ -111,8 +113,6 @@ public class ScaleTransform extends ResettableExtent {
return result;
}
@Nullable
@Override
public Entity createEntity(Location location, BaseEntity entity) {

View File

@ -1,29 +0,0 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.boydti.fawe.object.function.block;
import com.google.common.base.Preconditions;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.RegionFunction;
import com.sk89q.worldedit.patterns.Pattern;
public class LegacyBlockReplace implements RegionFunction {
private final Extent extent;
private Pattern pattern;
public LegacyBlockReplace(Extent extent, Pattern pattern) {
Preconditions.checkNotNull(extent);
Preconditions.checkNotNull(pattern);
this.extent = extent;
this.pattern = pattern;
}
public boolean apply(Vector position) throws WorldEditException {
return this.extent.setBlock(position, this.pattern.next(position));
}
}

View File

@ -1,11 +1,12 @@
package com.boydti.fawe.object.function.mask;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
public class AbstractDelegateMask implements Mask {
public class AbstractDelegateMask extends AbstractMask {
private final Mask mask;

View File

@ -2,15 +2,16 @@ package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask;
/**
* Just an optimized version of the Adjacent Mask for single adjacency
*/
public class AdjacentAnyMask implements Mask {
public class AdjacentAnyMask extends AbstractMask implements ResettableMask {
private final Mask mask;
private MutableBlockVector mutable = new MutableBlockVector();
private transient MutableBlockVector mutable = new MutableBlockVector();
public AdjacentAnyMask(Mask mask) {
this.mask = mask;
@ -20,6 +21,11 @@ public class AdjacentAnyMask implements Mask {
return mask;
}
@Override
public void reset() {
mutable = new MutableBlockVector();
}
@Override
public boolean test(Vector v) {
int x = v.getBlockX();

View File

@ -1,9 +1,10 @@
package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask;
public class AdjacentMask implements Mask {
public class AdjacentMask extends AbstractMask {
private final int min, max;
private final Mask mask;

View File

@ -8,48 +8,52 @@ import com.sk89q.worldedit.function.mask.Mask2D;
import com.sk89q.worldedit.function.mask.SolidBlockMask;
import javax.annotation.Nullable;
public class AngleMask extends SolidBlockMask {
public class AngleMask extends SolidBlockMask implements ResettableMask {
public static double ADJACENT_MOD = 0.5;
public static double DIAGONAL_MOD = 1 / Math.sqrt(8);
private final double max;
private final double min;
private final Extent extent;
private final boolean overlay;
private MutableBlockVector mutable = new MutableBlockVector();
private int maxY;
private transient MutableBlockVector mutable = new MutableBlockVector();
public AngleMask(Extent extent, double min, double max, boolean overlay) {
super(extent);
this.extent = extent;
this.min = min;
this.max = max;
this.maxY = extent.getMaximumPoint().getBlockY();
this.overlay = overlay;
}
@Override
public void reset() {
mutable = new MutableBlockVector();
}
@Override
public boolean test(Vector vector) {
int x = vector.getBlockX();
int y = vector.getBlockY();
int z = vector.getBlockZ();
BaseBlock block = extent.getLazyBlock(x, y, z);
BaseBlock block = getExtent().getLazyBlock(x, y, z);
if (!test(block.getId(), block.getData())) {
return false;
}
block = extent.getLazyBlock(x, y + 1, z);
block = getExtent().getLazyBlock(x, y + 1, z);
if (overlay && test(block.getId(), block.getData())) {
return false;
}
double slope;
boolean aboveMin;
slope = Math.abs(extent.getNearestSurfaceTerrainBlock(x + 1, z, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x - 1, z, y, 0, maxY)) * ADJACENT_MOD;
slope = Math.abs(getExtent().getNearestSurfaceTerrainBlock(x + 1, z, y, 0, maxY) - getExtent().getNearestSurfaceTerrainBlock(x - 1, z, y, 0, maxY)) * ADJACENT_MOD;
if (slope >= min && max >= Math.max(maxY - y, y)) {
return true;
}
slope = Math.max(slope, Math.abs(extent.getNearestSurfaceTerrainBlock(x, z + 1, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x, z - 1, y, 0, maxY)) * ADJACENT_MOD);
slope = Math.max(slope, Math.abs(extent.getNearestSurfaceTerrainBlock(x + 1, z + 1, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x - 1, z - 1, y, 0, maxY)) * DIAGONAL_MOD);
slope = Math.max(slope, Math.abs(extent.getNearestSurfaceTerrainBlock(x - 1, z + 1, y, 0, maxY) - extent.getNearestSurfaceTerrainBlock(x + 1, z - 1, y, 0, maxY)) * DIAGONAL_MOD);
slope = Math.max(slope, Math.abs(getExtent().getNearestSurfaceTerrainBlock(x, z + 1, y, 0, maxY) - getExtent().getNearestSurfaceTerrainBlock(x, z - 1, y, 0, maxY)) * ADJACENT_MOD);
slope = Math.max(slope, Math.abs(getExtent().getNearestSurfaceTerrainBlock(x + 1, z + 1, y, 0, maxY) - getExtent().getNearestSurfaceTerrainBlock(x - 1, z - 1, y, 0, maxY)) * DIAGONAL_MOD);
slope = Math.max(slope, Math.abs(getExtent().getNearestSurfaceTerrainBlock(x - 1, z + 1, y, 0, maxY) - getExtent().getNearestSurfaceTerrainBlock(x + 1, z - 1, y, 0, maxY)) * DIAGONAL_MOD);
return (slope >= min && slope <= max);
}

View File

@ -7,15 +7,20 @@ import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.world.biome.BaseBiome;
public class BiomeMask extends AbstractExtentMask {
public class BiomeMask extends AbstractExtentMask implements ResettableMask {
private final BaseBiome biome;
private MutableBlockVector2D mutable = new MutableBlockVector2D();
private transient MutableBlockVector2D mutable = new MutableBlockVector2D();
public BiomeMask(Extent extent, BaseBiome biome) {
super(extent);
this.biome = biome;
}
@Override
public void reset() {
mutable = new MutableBlockVector2D();
}
@Override
public boolean test(Vector vector) {
Vector2D pos = mutable.setComponents(vector.getBlockX(), vector.getBlockZ());

View File

@ -3,23 +3,23 @@ package com.boydti.fawe.object.mask;
import com.boydti.fawe.object.extent.LightingExtent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
public class BlockLightMask implements Mask {
public class BlockLightMask extends AbstractExtentMask {
private final Extent extent;
private final int min,max;
public BlockLightMask(Extent extent, int min, int max) {
this.extent = extent;
super(extent);
this.min = min;
this.max = max;
}
@Override
public boolean test(Vector vector) {
Extent extent = getExtent();
if (extent instanceof LightingExtent) {
int light = ((LightingExtent) extent).getBlockLight(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
return light >= min && light <= max;

View File

@ -3,23 +3,23 @@ package com.boydti.fawe.object.mask;
import com.boydti.fawe.object.extent.LightingExtent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
public class BrightnessMask implements Mask {
public class BrightnessMask extends AbstractExtentMask {
private final Extent extent;
private final int min,max;
public BrightnessMask(Extent extent, int min, int max) {
this.extent = extent;
super(extent);
this.min = min;
this.max = max;
}
@Override
public boolean test(Vector vector) {
Extent extent = getExtent();
if (extent instanceof LightingExtent) {
int light = ((LightingExtent) extent).getBrightness(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
return light >= min && light <= max;

View File

@ -2,22 +2,21 @@ package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
public class DataMask implements Mask, ResettableMask {
private final Extent extent;
public class DataMask extends AbstractExtentMask implements ResettableMask {
public DataMask(Extent extent) {
this.extent = extent;
super(extent);
}
int data = -1;
private transient int data = -1;
@Override
public boolean test(Vector vector) {
Extent extent = getExtent();
if (data != -1) {
return extent.getLazyBlock(vector).getData() == data;
} else {

View File

@ -3,22 +3,20 @@ package com.boydti.fawe.object.mask;
import com.boydti.fawe.FaweCache;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
public class IdDataMask implements Mask, ResettableMask {
private final Extent extent;
public class IdDataMask extends AbstractExtentMask implements ResettableMask {
private transient int combined = -1;
public IdDataMask(Extent extent) {
this.extent = extent;
super(extent);
}
int combined = -1;
@Override
public boolean test(Vector vector) {
Extent extent = getExtent();
if (combined != -1) {
return FaweCache.getCombined(extent.getLazyBlock(vector)) == combined;
} else {

View File

@ -2,22 +2,21 @@ package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
public class IdMask implements Mask, ResettableMask {
public class IdMask extends AbstractExtentMask implements ResettableMask {
private Extent extent;
private transient int id = -1;
public IdMask(Extent extent) {
this.extent = extent;
super(extent);
}
int id = -1;
@Override
public boolean test(Vector vector) {
Extent extent = getExtent();
if (id != -1) {
return extent.getLazyBlock(vector).getId() == id;
} else {

View File

@ -3,25 +3,24 @@ package com.boydti.fawe.object.mask;
import com.boydti.fawe.object.extent.LightingExtent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
public class LightMask implements Mask {
public class LightMask extends AbstractExtentMask {
private final Extent extent;
private final int min,max;
public LightMask(Extent extent, int min, int max) {
this.extent = extent;
super(extent);
this.min = min;
this.max = max;
}
@Override
public boolean test(Vector vector) {
if (extent instanceof LightingExtent) {
int light = ((LightingExtent) extent).getLight(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
if (getExtent() instanceof LightingExtent) {
int light = ((LightingExtent) getExtent()).getLight(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
return light >= min && light <= max;
}
return false;

View File

@ -3,25 +3,24 @@ package com.boydti.fawe.object.mask;
import com.boydti.fawe.object.extent.LightingExtent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
public class OpacityMask implements Mask {
public class OpacityMask extends AbstractExtentMask {
private final Extent extent;
private final int min,max;
public OpacityMask(Extent extent, int min, int max) {
this.extent = extent;
super(extent);
this.min = min;
this.max = max;
}
@Override
public boolean test(Vector vector) {
if (extent instanceof LightingExtent) {
int light = ((LightingExtent) extent).getOpacity(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
if (getExtent() instanceof LightingExtent) {
int light = ((LightingExtent) getExtent()).getOpacity(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
return light >= min && light <= max;
}
return false;

View File

@ -1,18 +1,17 @@
package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
/**
* Restricts the
*/
public class PlaneMask implements Mask, ResettableMask {
public class PlaneMask extends AbstractMask implements ResettableMask {
private int mode = -1;
private int originX = Integer.MAX_VALUE,originY = Integer.MAX_VALUE,originZ = Integer.MAX_VALUE;
private transient int mode = -1;
private transient int originX = Integer.MAX_VALUE, originY = Integer.MAX_VALUE,originZ = Integer.MAX_VALUE;
@Override
public boolean test(Vector vector) {

View File

@ -2,12 +2,13 @@ package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
public class RadiusMask implements Mask, ResettableMask{
public class RadiusMask extends AbstractMask implements ResettableMask{
private transient Vector pos;
private final int minSqr, maxSqr;
public RadiusMask(int min, int max) {
@ -20,8 +21,6 @@ public class RadiusMask implements Mask, ResettableMask{
pos = null;
}
private Vector pos;
@Override
public boolean test(Vector to) {
if (pos == null) {

View File

@ -4,8 +4,8 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.function.mask.AbstractMask;
import java.util.SplittableRandom;
public class RandomMask extends AbstractMask {
private final SplittableRandom random;
public class RandomMask extends AbstractMask implements ResettableMask {
private transient SplittableRandom random;
private final double threshold;
public RandomMask(double threshold) {
@ -17,4 +17,9 @@ public class RandomMask extends AbstractMask {
public boolean test(Vector vector) {
return random.nextInt() <= threshold;
}
@Override
public void reset() {
random = new SplittableRandom();
}
}

View File

@ -3,25 +3,24 @@ package com.boydti.fawe.object.mask;
import com.boydti.fawe.object.extent.LightingExtent;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractExtentMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
public class SkyLightMask implements Mask {
public class SkyLightMask extends AbstractExtentMask {
private final Extent extent;
private final int min,max;
public SkyLightMask(Extent extent, int min, int max) {
this.extent = extent;
super(extent);
this.min = min;
this.max = max;
}
@Override
public boolean test(Vector vector) {
if (extent instanceof LightingExtent) {
int light = ((LightingExtent) extent).getSkyLight(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
if (getExtent() instanceof LightingExtent) {
int light = ((LightingExtent) getExtent()).getSkyLight(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ());
return light >= min && light <= max;
}
return false;

View File

@ -12,8 +12,8 @@ import javax.annotation.Nullable;
*/
public class SolidPlaneMask extends SolidBlockMask implements ResettableMask {
private int mode = -1;
private MutableBlockVector mutable = new MutableBlockVector();
private transient int mode = -1;
private transient MutableBlockVector mutable = new MutableBlockVector();
private int originX = Integer.MAX_VALUE,originY = Integer.MAX_VALUE,originZ = Integer.MAX_VALUE;
@ -84,6 +84,7 @@ public class SolidPlaneMask extends SolidBlockMask implements ResettableMask {
@Override
public void reset() {
mode = -1;
mutable = new MutableBlockVector();
}
@Nullable

View File

@ -7,7 +7,7 @@ import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.BlockMask;
public class SurfaceMask extends AdjacentAnyMask {
private final Extent extent;
private final transient Extent extent;
public SurfaceMask(Extent extent) {
super(new BlockMask(extent, new BaseBlock(0)));

View File

@ -1,9 +1,10 @@
package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask;
public class WallMask implements Mask {
public class WallMask extends AbstractMask {
private final int min, max;
private final Mask mask;

View File

@ -1,16 +1,16 @@
package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
/**
* Restricts the
*/
public class XAxisMask implements Mask, ResettableMask {
public class XAxisMask extends AbstractMask implements ResettableMask {
private int layer = -1;
private transient int layer = -1;
@Override
public boolean test(Vector vector) {

View File

@ -1,16 +1,16 @@
package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
/**
* Restricts the
*/
public class YAxisMask implements Mask, ResettableMask {
public class YAxisMask extends AbstractMask implements ResettableMask {
private int layer = -1;
private transient int layer = -1;
@Override
public boolean test(Vector vector) {

View File

@ -1,16 +1,16 @@
package com.boydti.fawe.object.mask;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.mask.AbstractMask;
import com.sk89q.worldedit.function.mask.Mask2D;
import javax.annotation.Nullable;
/**
* Restricts the
*/
public class ZAxisMask implements Mask, ResettableMask {
public class ZAxisMask extends AbstractMask implements ResettableMask {
private int layer = -1;
private transient int layer = -1;
@Override
public boolean test(Vector vector) {

View File

@ -1,179 +0,0 @@
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/*
* Source:
* http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/LongAdder.java?revision=1.17
*/
package com.boydti.fawe.object.number;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
public final class LongAdder extends Striped64 implements Serializable {
private static final long serialVersionUID = 7249069246863182397L;
/**
* Version of plus for use in retryUpdate
*/
final long fn(long v, long x) { return v + x; }
/**
* Creates a new adder with initial sum of zero.
*/
public LongAdder() {
}
/**
* Adds the given value.
*
* @param x the value to add
*/
public void add(long x) {
Cell[] as; long b, v; int[] hc; Cell a; int n;
if ((as = cells) != null || !casBase(b = base, b + x)) {
boolean uncontended = true;
if ((hc = threadHashCode.get()) == null ||
as == null || (n = as.length) < 1 ||
(a = as[(n - 1) & hc[0]]) == null ||
!(uncontended = a.cas(v = a.value, v + x)))
retryUpdate(x, hc, uncontended);
}
}
/**
* Equivalent to {@code add(1)}.
*/
public void increment() {
add(1L);
}
/**
* Equivalent to {@code add(-1)}.
*/
public void decrement() {
add(-1L);
}
/**
* Returns the current sum. The returned value is <em>NOT</em> an
* atomic snapshot; invocation in the absence of concurrent
* updates returns an accurate result, but concurrent updates that
* occur while the sum is being calculated might not be
* incorporated.
*
* @return the sum
*/
public long sum() {
long sum = base;
Cell[] as = cells;
if (as != null) {
int n = as.length;
for (int i = 0; i < n; ++i) {
Cell a = as[i];
if (a != null)
sum += a.value;
}
}
return sum;
}
/**
* Resets variables maintaining the sum to zero. This method may
* be a useful alternative to creating a new adder, but is only
* effective if there are no concurrent updates. Because this
* method is intrinsically racy, it should only be used when it is
* known that no threads are concurrently updating.
*/
public void reset() {
internalReset(0L);
}
/**
* Equivalent in effect to {@link #sum} followed by {@link
* #reset}. This method may apply for example during quiescent
* points between multithreaded computations. If there are
* updates concurrent with this method, the returned value is
* <em>not</em> guaranteed to be the final value occurring before
* the reset.
*
* @return the sum
*/
public long sumThenReset() {
long sum = base;
Cell[] as = cells;
base = 0L;
if (as != null) {
int n = as.length;
for (int i = 0; i < n; ++i) {
Cell a = as[i];
if (a != null) {
sum += a.value;
a.value = 0L;
}
}
}
return sum;
}
/**
* Returns the String representation of the {@link #sum}.
* @return the String representation of the {@link #sum}
*/
public String toString() {
return Long.toString(sum());
}
/**
* Equivalent to {@link #sum}.
*
* @return the sum
*/
public long longValue() {
return sum();
}
/**
* Returns the {@link #sum} as an {@code int} after a narrowing
* primitive conversion.
*/
public int intValue() {
return (int)sum();
}
/**
* Returns the {@link #sum} as a {@code float}
* after a widening primitive conversion.
*/
public float floatValue() {
return (float)sum();
}
/**
* Returns the {@link #sum} as a {@code double} after a widening
* primitive conversion.
*/
public double doubleValue() {
return (double)sum();
}
private void writeObject(ObjectOutputStream s) throws IOException {
s.defaultWriteObject();
s.writeLong(sum());
}
private void readObject(ObjectInputStream s)
throws IOException, ClassNotFoundException {
s.defaultReadObject();
busy = 0;
cells = null;
base = s.readLong();
}
}

View File

@ -1,341 +0,0 @@
package com.boydti.fawe.object.number;
/*
* Written by Doug Lea with assistance from members of JCP JSR-166
* Expert Group and released to the public domain, as explained at
* http://creativecommons.org/publicdomain/zero/1.0/
*/
/*
* Source:
* http://gee.cs.oswego.edu/cgi-bin/viewcvs.cgi/jsr166/src/jsr166e/Striped64.java?revision=1.9
*/
import com.boydti.fawe.object.PseudoRandom;
import java.util.Random;
/**
* A package-local class holding common representation and mechanics
* for classes supporting dynamic striping on 64bit values. The class
* extends Number so that concrete subclasses must publicly do so.
*/
abstract class Striped64 extends Number {
/*
* This class maintains a lazily-initialized table of atomically
* updated variables, plus an extra "base" field. The table size
* is a power of two. Indexing uses masked per-thread hash codes.
* Nearly all declarations in this class are package-private,
* accessed directly by subclasses.
*
* Table entries are of class Cell; a variant of AtomicLong padded
* to reduce cache contention on most processors. Padding is
* overkill for most Atomics because they are usually irregularly
* scattered in memory and thus don't interfere much with each
* other. But Atomic objects residing in arrays will tend to be
* placed adjacent to each other, and so will most often share
* cache lines (with a huge negative performance impact) without
* this precaution.
*
* In part because Cells are relatively large, we avoid creating
* them until they are needed. When there is no contention, all
* updates are made to the base field. Upon first contention (a
* failed CAS on base update), the table is initialized to size 2.
* The table size is doubled upon further contention until
* reaching the nearest power of two greater than or equal to the
* number of CPUS. Table slots remain empty (null) until they are
* needed.
*
* A single spinlock ("busy") is used for initializing and
* resizing the table, as well as populating slots with new Cells.
* There is no need for a blocking lock; when the lock is not
* available, threads try other slots (or the base). During these
* retries, there is increased contention and reduced locality,
* which is still better than alternatives.
*
* Per-thread hash codes are initialized to random values.
* Contention and/or table collisions are indicated by failed
* CASes when performing an update operation (see method
* retryUpdate). Upon a collision, if the table size is less than
* the capacity, it is doubled in size unless some other thread
* holds the lock. If a hashed slot is empty, and lock is
* available, a new Cell is created. Otherwise, if the slot
* exists, a CAS is tried. Retries proceed by "double hashing",
* using a secondary hash (Marsaglia XorShift) to try to find a
* free slot.
*
* The table size is capped because, when there are more threads
* than CPUs, supposing that each thread were bound to a CPU,
* there would exist a perfect hash function mapping threads to
* slots that eliminates collisions. When we reach capacity, we
* search for this mapping by randomly varying the hash codes of
* colliding threads. Because search is random, and collisions
* only become known via CAS failures, convergence can be slow,
* and because threads are typically not bound to CPUS forever,
* may not occur at all. However, despite these limitations,
* observed contention rates are typically low in these cases.
*
* It is possible for a Cell to become unused when threads that
* once hashed to it terminate, as well as in the case where
* doubling the table causes no thread to hash to it under
* expanded mask. We do not try to detect or remove such cells,
* under the assumption that for long-running instances, observed
* contention levels will recur, so the cells will eventually be
* needed again; and for short-lived ones, it does not matter.
*/
/**
* Padded variant of AtomicLong supporting only raw accesses plus CAS.
* The value field is placed between pads, hoping that the JVM doesn't
* reorder them.
*
* JVM intrinsics note: It would be possible to use a release-only
* form of CAS here, if it were provided.
*/
static final class Cell {
volatile long p0, p1, p2, p3, p4, p5, p6;
volatile long value;
volatile long q0, q1, q2, q3, q4, q5, q6;
Cell(long x) { value = x; }
final boolean cas(long cmp, long val) {
return UNSAFE.compareAndSwapLong(this, valueOffset, cmp, val);
}
// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE;
private static final long valueOffset;
static {
try {
UNSAFE = getUnsafe();
Class<?> ak = Cell.class;
valueOffset = UNSAFE.objectFieldOffset
(ak.getDeclaredField("value"));
} catch (Exception e) {
throw new Error(e);
}
}
}
/**
* ThreadLocal holding a single-slot int array holding hash code.
* Unlike the JDK8 version of this class, we use a suboptimal
* int[] representation to avoid introducing a new type that can
* impede class-unloading when ThreadLocals are not removed.
*/
static final ThreadLocal<int[]> threadHashCode = new ThreadLocal<int[]>();
/**
* Generator of new random hash codes
*/
static final PseudoRandom prng = new PseudoRandom(System.nanoTime());
static final Random rng = new Random();
/** Number of CPUS, to place bound on table size */
static final int NCPU = Runtime.getRuntime().availableProcessors();
/**
* Table of cells. When non-null, size is a power of 2.
*/
transient volatile Cell[] cells;
/**
* Base value, used mainly when there is no contention, but also as
* a fallback during table initialization races. Updated via CAS.
*/
transient volatile long base;
/**
* Spinlock (locked via CAS) used when resizing and/or creating Cells.
*/
transient volatile int busy;
/**
* Package-private default constructor
*/
Striped64() {
}
/**
* CASes the base field.
*/
final boolean casBase(long cmp, long val) {
return UNSAFE.compareAndSwapLong(this, baseOffset, cmp, val);
}
/**
* CASes the busy field from 0 to 1 to acquire lock.
*/
final boolean casBusy() {
return UNSAFE.compareAndSwapInt(this, busyOffset, 0, 1);
}
/**
* Computes the function of current and new value. Subclasses
* should open-code this update function for most uses, but the
* virtualized form is needed within retryUpdate.
*
* @param currentValue the current value (of either base or a cell)
* @param newValue the argument from a user update call
* @return result of the update function
*/
abstract long fn(long currentValue, long newValue);
/**
* Handles cases of updates involving initialization, resizing,
* creating new Cells, and/or contention. See above for
* explanation. This method suffers the usual non-modularity
* problems of optimistic retry code, relying on rechecked sets of
* reads.
*
* @param x the value
* @param hc the hash code holder
* @param wasUncontended false if CAS failed before call
*/
final void retryUpdate(long x, int[] hc, boolean wasUncontended) {
int h;
if (hc == null) {
threadHashCode.set(hc = new int[1]); // Initialize randomly
int r = prng.random(Integer.MAX_VALUE); // Avoid zero to allow xorShift rehash
h = hc[0] = (r == 0) ? 1 : r;
}
else
h = hc[0];
boolean collide = false; // True if last slot nonempty
for (;;) {
Cell[] as; Cell a; int n; long v;
if ((as = cells) != null && (n = as.length) > 0) {
if ((a = as[(n - 1) & h]) == null) {
if (busy == 0) { // Try to attach new Cell
Cell r = new Cell(x); // Optimistically create
if (busy == 0 && casBusy()) {
boolean created = false;
try { // Recheck under lock
Cell[] rs; int m, j;
if ((rs = cells) != null &&
(m = rs.length) > 0 &&
rs[j = (m - 1) & h] == null) {
rs[j] = r;
created = true;
}
} finally {
busy = 0;
}
if (created)
break;
continue; // Slot is now non-empty
}
}
collide = false;
}
else if (!wasUncontended) // CAS already known to fail
wasUncontended = true; // Continue after rehash
else if (a.cas(v = a.value, fn(v, x)))
break;
else if (n >= NCPU || cells != as)
collide = false; // At max size or stale
else if (!collide)
collide = true;
else if (busy == 0 && casBusy()) {
try {
if (cells == as) { // Expand table unless stale
Cell[] rs = new Cell[n << 1];
for (int i = 0; i < n; ++i)
rs[i] = as[i];
cells = rs;
}
} finally {
busy = 0;
}
collide = false;
continue; // Retry with expanded table
}
h ^= h << 13; // Rehash
h ^= h >>> 17;
h ^= h << 5;
hc[0] = h; // Record index for next time
}
else if (busy == 0 && cells == as && casBusy()) {
boolean init = false;
try { // Initialize table
if (cells == as) {
Cell[] rs = new Cell[2];
rs[h & 1] = new Cell(x);
cells = rs;
init = true;
}
} finally {
busy = 0;
}
if (init)
break;
}
else if (casBase(v = base, fn(v, x)))
break; // Fall back on using base
}
}
/**
* Sets base and all cells to the given value.
*/
final void internalReset(long initialValue) {
Cell[] as = cells;
base = initialValue;
if (as != null) {
int n = as.length;
for (int i = 0; i < n; ++i) {
Cell a = as[i];
if (a != null)
a.value = initialValue;
}
}
}
// Unsafe mechanics
private static final sun.misc.Unsafe UNSAFE;
private static final long baseOffset;
private static final long busyOffset;
static {
try {
UNSAFE = getUnsafe();
Class<?> sk = Striped64.class;
baseOffset = UNSAFE.objectFieldOffset
(sk.getDeclaredField("base"));
busyOffset = UNSAFE.objectFieldOffset
(sk.getDeclaredField("busy"));
} catch (Exception e) {
throw new Error(e);
}
}
/**
* Returns a sun.misc.Unsafe. Suitable for use in a 3rd party package.
* Replace with a simple call to Unsafe.getUnsafe when integrating
* into a jdk.
*
* @return a sun.misc.Unsafe
*/
private static sun.misc.Unsafe getUnsafe() {
try {
return sun.misc.Unsafe.getUnsafe();
} catch (SecurityException tryReflectionInstead) {}
try {
return java.security.AccessController.doPrivileged
(new java.security.PrivilegedExceptionAction<sun.misc.Unsafe>() {
public sun.misc.Unsafe run() throws Exception {
Class<sun.misc.Unsafe> k = sun.misc.Unsafe.class;
for (java.lang.reflect.Field f : k.getDeclaredFields()) {
f.setAccessible(true);
Object x = f.get(null);
if (k.isInstance(x))
return k.cast(x);
}
throw new NoSuchFieldError("the Unsafe");
}});
} catch (java.security.PrivilegedActionException e) {
throw new RuntimeException("Could not initialize intrinsics",
e.getCause());
}
}
}

View File

@ -0,0 +1,20 @@
package com.boydti.fawe.object.pattern;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import static com.google.common.base.Preconditions.checkNotNull;
public abstract class AbstractExtentPattern extends AbstractPattern {
private transient final Extent extent;
public AbstractExtentPattern(Extent extent) {
checkNotNull(extent);
this.extent = extent;
}
public final Extent getExtent() {
return extent;
}
}

View File

@ -1,26 +1,31 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.DataAngleMask;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import java.io.IOException;
public class AngleColorPattern extends DataAngleMask {
private final TextureUtil util;
private final int maxY;
private final double factor = 1d/196;
private static final double FACTOR = 1d/196;
private transient TextureUtil util;
public AngleColorPattern(TextureUtil util, Extent extent) {
private final boolean randomize;
private final int complexity;
public AngleColorPattern(Extent extent, int complexity, boolean randomize) {
super(extent);
this.util = util;
this.maxY = extent.getMaximumPoint().getBlockY();
this.complexity = complexity;
this.randomize = randomize;
this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
}
public int getColor(int color, int slope) {
if (slope == 0) return color;
double newFactor = (196 - Math.min(196, slope)) * factor;
double newFactor = (196 - Math.min(196, slope)) * FACTOR;
int newRed = (int) (((color >> 16) & 0xFF) * newFactor);
int newGreen = (int) (((color >> 8) & 0xFF) * newFactor);
int newBlue = (int) (((color >> 0) & 0xFF) * newFactor);
@ -50,4 +55,9 @@ public class AngleColorPattern extends DataAngleMask {
if (newBlock == null) return false;
return extent.setBlock(setPosition, newBlock);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
}
}

View File

@ -1,27 +1,31 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import java.awt.Color;
import java.io.IOException;
public class AverageColorPattern extends AbstractPattern {
public class AverageColorPattern extends AbstractExtentPattern {
private transient TextureUtil util;
private final boolean randomize;
private final int complexity;
private final int color;
private final Extent extent;
private final TextureUtil util;
public AverageColorPattern(Extent extent, TextureUtil util, int color) {
this.extent = extent;
this.util = util;
public AverageColorPattern(Extent extent, int color, int complexity, boolean randomize) {
super(extent);
this.complexity = complexity;
this.randomize = randomize;
this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
this.color = new Color(color).getRGB();
}
@Override
public BaseBlock apply(Vector position) {
BaseBlock block = extent.getBlock(position);
BaseBlock block = getExtent().getBlock(position);
int currentColor = util.getColor(block);
int newColor = util.averageColor(currentColor, color);
return util.getNearestBlock(newColor);
@ -37,4 +41,9 @@ public class AverageColorPattern extends AbstractPattern {
if (newBlock.equals(block)) return false;
return extent.setBlock(setPosition, newBlock);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
}
}

View File

@ -6,21 +6,20 @@ import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.IOException;
public class BiomePattern extends ExistingPattern {
private transient MutableBlockVector2D mutable = new MutableBlockVector2D();
private final BaseBiome biome;
private BiomePatternException exception;
private MutableBlockVector2D mutable = new MutableBlockVector2D();
public BiomePattern(Extent extent, BaseBiome biome) {
super(extent);
this.biome = biome;
this.exception = new BiomePatternException();
}
@Override
public BaseBlock apply(Vector position) {
throw exception;
throw new BiomePatternException();
}
@Override
@ -29,10 +28,7 @@ public class BiomePattern extends ExistingPattern {
}
public class BiomePatternException extends RuntimeException {
public BiomePatternException() {
super("Haha, you failed Empire92! Should've done things properly instead of some hacky AF biome pattern.\nHey, you! The one reading this stacktrace, can you do me a favor and report this on GitHub so I can get around to fixing it?");
}
private BiomePatternException() {}
public BiomePattern getPattern() {
return BiomePattern.this;
@ -47,4 +43,9 @@ public class BiomePattern extends ExistingPattern {
return this;
}
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
mutable = new MutableBlockVector2D();
}
}

View File

@ -10,17 +10,21 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.io.IOException;
import java.util.UUID;
public class BufferedPattern extends AbstractPattern implements ResettablePattern {
private final Pattern pattern;
private final LocalBlockVectorSet set = new LocalBlockVectorSet();
private final FaweTimer timer;
private final long[] actionTime;
protected transient LocalBlockVectorSet set = new LocalBlockVectorSet();
protected transient FaweTimer timer;
protected transient long[] actionTime;
protected final Pattern pattern;
protected final UUID uuid;
public BufferedPattern(FawePlayer fp, Pattern parent) {
long[] actionTime = fp.getMeta("lastActionTime");
this.uuid = fp.getUUID();
this.actionTime = fp.getMeta("lastActionTime");
if (actionTime == null) fp.setMeta("lastActionTime", actionTime = new long[2]);
this.actionTime = actionTime;
this.pattern = parent;
this.timer = Fawe.get().getTimer();
}
@ -34,7 +38,7 @@ public class BufferedPattern extends AbstractPattern implements ResettablePatter
public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException {
long now = timer.getTick();
try {
if (!set.add(setPosition)) {
if (!set(setPosition)) {
return false;
}
return pattern.apply(extent, setPosition, getPosition);
@ -42,6 +46,10 @@ public class BufferedPattern extends AbstractPattern implements ResettablePatter
return false;
}
public boolean set(Vector pos) {
return set.add(pos);
}
@Override
public void reset() {
long now = timer.getTick();
@ -51,4 +59,17 @@ public class BufferedPattern extends AbstractPattern implements ResettablePatter
actionTime[1] = actionTime[0];
actionTime[0] = now;
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
set = new LocalBlockVectorSet();
timer = Fawe.get().getTimer();
FawePlayer fp = Fawe.get().getCachedPlayer(uuid);
if (fp != null) {
this.actionTime = fp.getMeta("lastActionTime");
if (actionTime == null) fp.setMeta("lastActionTime", actionTime = new long[2]);
} else {
actionTime = new long[2];
}
}
}

View File

@ -1,54 +1,17 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.collection.LocalBlockVectorSet;
import com.boydti.fawe.util.FaweTimer;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
public class BufferedPattern2D extends AbstractPattern implements ResettablePattern {
private final Pattern pattern;
private final LocalBlockVectorSet set = new LocalBlockVectorSet();
private final FaweTimer timer;
private final long[] actionTime;
public class BufferedPattern2D extends BufferedPattern {
public BufferedPattern2D(FawePlayer fp, Pattern parent) {
long[] actionTime = fp.getMeta("lastActionTime");
if (actionTime == null) fp.setMeta("lastActionTime", actionTime = new long[2]);
this.actionTime = actionTime;
this.pattern = parent;
this.timer = Fawe.get().getTimer();
super(fp, parent);
}
@Override
public BaseBlock apply(Vector position) {
return pattern.apply(position);
}
@Override
public boolean apply(Extent extent, Vector setPosition, Vector getPosition) throws WorldEditException {
long now = timer.getTick();
try {
if (!set.add(setPosition.getBlockX(), 0, setPosition.getBlockZ())) {
return false;
}
return pattern.apply(extent, setPosition, getPosition);
} catch (UnsupportedOperationException ignore) {}
return false;
}
@Override
public void reset() {
long now = timer.getTick();
if (now - actionTime[1] > 5) {
set.clear();
}
actionTime[1] = actionTime[0];
actionTime[0] = now;
public boolean set(Vector pos) {
return set.add(pos.getBlockX(), 0, pos.getBlockY());
}
}

View File

@ -4,26 +4,23 @@ import com.boydti.fawe.FaweCache;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import static com.google.common.base.Preconditions.checkNotNull;
public class DataPattern extends AbstractPattern {
private final Extent extent;
public class DataPattern extends AbstractExtentPattern {
private final Pattern pattern;
public DataPattern(Extent extent, Pattern parent) {
checkNotNull(extent);
super(extent);
checkNotNull(parent);
this.extent = extent;
this.pattern = parent;
}
@Override
public BaseBlock apply(Vector position) {
BaseBlock oldBlock = extent.getBlock(position);
BaseBlock oldBlock = getExtent().getBlock(position);
BaseBlock newBlock = pattern.apply(position);
return FaweCache.getBlock(oldBlock.getId(), newBlock.getData());
}

View File

@ -1,20 +1,26 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import java.io.IOException;
public class DesaturatePattern extends AbstractPattern{
private final TextureUtil util;
private transient TextureUtil util;
private final boolean randomize;
private final int complexity;
private final Extent extent;
private final double value;
public DesaturatePattern(Extent extent, TextureUtil util, double value) {
public DesaturatePattern(Extent extent, double value, int complexity, boolean randomize) {
this.extent = extent;
this.util = util;
this.complexity = complexity;
this.randomize = randomize;
this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
this.value = Math.max(0, Math.min(1, value));
}
@Override
@ -55,4 +61,9 @@ public class DesaturatePattern extends AbstractPattern{
}
return extent.setBlock(setPosition, newBlock);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
}
}

View File

@ -4,18 +4,15 @@ import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
public class ExistingPattern extends AbstractPattern {
private final Extent extent;
public class ExistingPattern extends AbstractExtentPattern {
public ExistingPattern(Extent extent) {
this.extent = extent;
super(extent);
}
@Override
public BaseBlock apply(Vector position) {
return extent.getBlock(position);
return getExtent().getBlock(position);
}
@Override

View File

@ -9,6 +9,7 @@ import com.sk89q.worldedit.internal.expression.Expression;
import com.sk89q.worldedit.internal.expression.ExpressionException;
import com.sk89q.worldedit.internal.expression.runtime.EvaluationException;
import com.sk89q.worldedit.regions.shape.WorldEditExpressionEnvironment;
import java.io.IOException;
import static com.google.common.base.Preconditions.checkNotNull;
@ -21,7 +22,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
*/
public class ExpressionPattern extends AbstractPattern {
private final Expression expression;
public String input;
private transient Expression expression;
/**
* Create a new instance.
@ -29,9 +31,10 @@ public class ExpressionPattern extends AbstractPattern {
* @param expression the expression
* @throws ExpressionException thrown if there is an error with the expression
*/
public ExpressionPattern(String expression) throws ExpressionException {
checkNotNull(expression);
this.expression = Expression.compile(expression, "x", "y", "z");
public ExpressionPattern(String input) throws ExpressionException {
checkNotNull(input);
this.input = input;
this.expression = Expression.compile(input, "x", "y", "z");
}
/**
@ -56,4 +59,13 @@ public class ExpressionPattern extends AbstractPattern {
return EditSession.nullBlock;
}
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
try {
this.expression = Expression.compile(input, "x", "y", "z");
} catch (ExpressionException e) {
e.printStackTrace();
}
}
}

View File

@ -9,8 +9,9 @@ import com.sk89q.worldedit.extent.clipboard.Clipboard;
import com.sk89q.worldedit.function.mask.ExistingBlockMask;
import com.sk89q.worldedit.function.operation.ForwardExtentCopy;
import com.sk89q.worldedit.function.operation.Operations;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.regions.Region;
import java.io.IOException;
import java.io.NotSerializableException;
import static com.google.common.base.Preconditions.checkNotNull;
@ -18,8 +19,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* A pattern that reads from {@link Clipboard}.
*/
public class FullClipboardPattern extends AbstractPattern {
private final Extent extent;
public class FullClipboardPattern extends AbstractExtentPattern {
private final Clipboard clipboard;
private final MutableBlockVector mutable = new MutableBlockVector();
@ -29,9 +29,9 @@ public class FullClipboardPattern extends AbstractPattern {
* @param clipboard the clipboard
*/
public FullClipboardPattern(Extent extent, Clipboard clipboard) {
super(extent);
checkNotNull(clipboard);
this.clipboard = clipboard;
this.extent = extent;
}
@Override
@ -47,4 +47,8 @@ public class FullClipboardPattern extends AbstractPattern {
public BaseBlock apply(Vector position) {
throw new IllegalStateException("Incorrect use. This pattern can only be applied to an extent!");
}
private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
throw new NotSerializableException("Clipboard cannot be serialized!");
}
}

View File

@ -4,26 +4,24 @@ import com.boydti.fawe.FaweCache;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
public class IdDataMaskPattern extends AbstractPattern {
private final Extent extent;
public class IdDataMaskPattern extends AbstractExtentPattern {
private final Pattern pattern;
private final int mask;
private final int bitMask;
public IdDataMaskPattern(Extent extent, Pattern parent, int mask) {
this.extent = extent;
public IdDataMaskPattern(Extent extent, Pattern parent, int bitMask) {
super(extent);
this.pattern = parent;
this.mask = mask;
this.bitMask = bitMask;
}
@Override
public BaseBlock apply(Vector position) {
BaseBlock oldBlock = extent.getBlock(position);
BaseBlock oldBlock = getExtent().getBlock(position);
BaseBlock newBlock = pattern.apply(position);
int oldData = oldBlock.getData();
int newData = newBlock.getData() + oldData - (oldData & mask);
int newData = newBlock.getData() + oldData - (oldData & bitMask);
return FaweCache.getBlock(newBlock.getId(), newData);
}
}

View File

@ -4,26 +4,23 @@ import com.boydti.fawe.FaweCache;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import static com.google.common.base.Preconditions.checkNotNull;
public class IdPattern extends AbstractPattern {
private final Extent extent;
public class IdPattern extends AbstractExtentPattern {
private final Pattern pattern;
public IdPattern(Extent extent, Pattern parent) {
checkNotNull(extent);
super(extent);
checkNotNull(parent);
this.extent = extent;
this.pattern = parent;
}
@Override
public BaseBlock apply(Vector position) {
BaseBlock oldBlock = extent.getBlock(position);
BaseBlock oldBlock = getExtent().getBlock(position);
BaseBlock newBlock = pattern.apply(position);
return FaweCache.getBlock(newBlock.getId(), oldBlock.getData());
}

View File

@ -6,17 +6,13 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.util.Arrays;
import java.util.Collection;
public class Linear3DBlockPattern extends AbstractPattern {
private final Collection<Pattern> patterns;
private final Pattern[] patternsArray;
public Linear3DBlockPattern(Pattern[] patterns) {
this.patternsArray = patterns;
this.patterns = Arrays.asList(patterns);
}
@Override

View File

@ -6,18 +6,14 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.util.Arrays;
import java.util.Collection;
public class LinearBlockPattern extends AbstractPattern implements ResettablePattern {
private final Collection<Pattern> patterns;
private final Pattern[] patternsArray;
private int index;
private transient int index;
public LinearBlockPattern(Pattern[] patterns) {
this.patternsArray = patterns;
this.patterns = Arrays.asList(patterns);
}
@Override

View File

@ -7,21 +7,17 @@ import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.util.Arrays;
import java.util.List;
public class MaskedPattern extends AbstractPattern {
private final PatternExtent patternExtent;
private final Pattern secondaryPattern;
private final List<Pattern> patterns;
private Mask mask;
public MaskedPattern(Mask mask, PatternExtent primary, Pattern secondary) {
this.mask = mask;
this.patternExtent = primary;
this.secondaryPattern = secondary;
this.patterns = Arrays.asList(primary, secondary);
}

View File

@ -7,17 +7,17 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.io.IOException;
public class NoXPattern extends AbstractPattern {
private final Pattern pattern;
private transient MutableBlockVector mutable = new MutableBlockVector();
public NoXPattern(Pattern pattern) {
this.pattern = pattern;
}
private MutableBlockVector mutable = new MutableBlockVector();
@Override
public BaseBlock apply(Vector pos) {
mutable.mutY((pos.getY()));
@ -31,4 +31,9 @@ public class NoXPattern extends AbstractPattern {
mutable.mutZ((get.getZ()));
return pattern.apply(extent, set, mutable);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
mutable = new MutableBlockVector();
}
}

View File

@ -7,6 +7,7 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.io.IOException;
public class NoYPattern extends AbstractPattern {
@ -16,7 +17,7 @@ public class NoYPattern extends AbstractPattern {
this.pattern = pattern;
}
private MutableBlockVector mutable = new MutableBlockVector();
private transient MutableBlockVector mutable = new MutableBlockVector();
@Override
public BaseBlock apply(Vector pos) {
@ -31,4 +32,9 @@ public class NoYPattern extends AbstractPattern {
mutable.mutZ((get.getZ()));
return pattern.apply(extent, set, mutable);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
mutable = new MutableBlockVector();
}
}

View File

@ -7,6 +7,7 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.io.IOException;
public class NoZPattern extends AbstractPattern {
@ -16,7 +17,7 @@ public class NoZPattern extends AbstractPattern {
this.pattern = pattern;
}
private MutableBlockVector mutable = new MutableBlockVector();
private transient MutableBlockVector mutable = new MutableBlockVector();
@Override
public BaseBlock apply(Vector pos) {
@ -31,4 +32,9 @@ public class NoZPattern extends AbstractPattern {
mutable.mutY((get.getY()));
return pattern.apply(extent, set, mutable);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
mutable = new MutableBlockVector();
}
}

View File

@ -7,11 +7,12 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.io.IOException;
public class OffsetPattern extends AbstractPattern {
private final int dx,dy,dz;
private final MutableBlockVector mutable = new MutableBlockVector();
private transient MutableBlockVector mutable = new MutableBlockVector();
private final Pattern pattern;
public OffsetPattern(Pattern pattern, int dx, int dy, int dz) {
@ -36,4 +37,9 @@ public class OffsetPattern extends AbstractPattern {
mutable.mutZ((get.getZ() + dz));
return pattern.apply(extent, set, mutable);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
mutable = new MutableBlockVector();
}
}

View File

@ -13,19 +13,25 @@ import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.regions.Region;
import com.sk89q.worldedit.util.Location;
import com.sk89q.worldedit.world.biome.BaseBiome;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.Nullable;
public class PatternExtent extends AbstractPattern implements Extent {
private final Pattern pattern;
private BaseBlock block;
private Vector target = new Vector();
private transient BaseBlock block;
private transient Vector target = new Vector();
public PatternExtent(Pattern pattern) {
this.pattern = pattern;
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
target = new Vector();
}
@Override
public Vector getMinimumPoint() {
return new Vector(Integer.MIN_VALUE,0,Integer.MIN_VALUE);

View File

@ -13,6 +13,8 @@ import com.sk89q.worldedit.math.transform.AffineTransform;
import com.sk89q.worldedit.math.transform.Transform;
import com.sk89q.worldedit.session.ClipboardHolder;
import com.sk89q.worldedit.world.registry.WorldData;
import java.io.IOException;
import java.io.NotSerializableException;
import static com.google.common.base.Preconditions.checkNotNull;
@ -62,4 +64,8 @@ public class RandomFullClipboardPattern extends AbstractPattern {
public BaseBlock apply(Vector position) {
throw new IllegalStateException("Incorrect use. This pattern can only be applied to an extent!");
}
private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
throw new NotSerializableException("Clipboard cannot be serialized!");
}
}

View File

@ -1,6 +1,5 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.object.PseudoRandom;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@ -8,12 +7,16 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.io.IOException;
import java.util.SplittableRandom;
public class RandomOffsetPattern extends AbstractPattern {
private final PseudoRandom r = new PseudoRandom();
private final int dx, dy, dz, dx2, dy2, dz2;
private final int dx, dy, dz;
private final Pattern pattern;
private final MutableBlockVector mutable = new MutableBlockVector();
private transient int dx2, dy2, dz2;
private transient MutableBlockVector mutable = new MutableBlockVector();
private transient SplittableRandom r;
public RandomOffsetPattern(Pattern pattern, int dx, int dy, int dz) {
this.pattern = pattern;
@ -23,6 +26,7 @@ public class RandomOffsetPattern extends AbstractPattern {
this.dx2 = dx * 2 + 1;
this.dy2 = dy * 2 + 1;
this.dz2 = dz * 2 + 1;
this.r = new SplittableRandom();
}
@ -41,4 +45,13 @@ public class RandomOffsetPattern extends AbstractPattern {
mutable.mutZ((get.getZ() + r.nextInt(dz2) - dz));
return pattern.apply(extent, set, mutable);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
this.dx2 = dx * 2 + 1;
this.dy2 = dy * 2 + 1;
this.dz2 = dz * 2 + 1;
this.r = new SplittableRandom();
this.mutable = new MutableBlockVector();
}
}

View File

@ -7,18 +7,18 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.io.IOException;
public class RelativePattern extends AbstractPattern implements ResettablePattern {
private final Pattern pattern;
private transient Vector origin;
private transient MutableBlockVector mutable = new MutableBlockVector();
public RelativePattern(Pattern pattern) {
this.pattern = pattern;
}
private Vector origin;
private MutableBlockVector mutable = new MutableBlockVector();
@Override
public BaseBlock apply(Vector pos) {
if (origin == null) {
@ -41,6 +41,11 @@ public class RelativePattern extends AbstractPattern implements ResettablePatter
return pattern.apply(extent, set, mutable);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
mutable = new MutableBlockVector();
}
@Override
public void reset() {
origin = null;

View File

@ -1,5 +1,6 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@ -7,15 +8,21 @@ import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import java.awt.Color;
import java.io.IOException;
public class SaturatePattern extends AbstractPattern {
private transient TextureUtil util;
private final boolean randomize;
private final int complexity;
private final int color;
private final Extent extent;
private final TextureUtil util;
public SaturatePattern(Extent extent, TextureUtil util, int color) {
public SaturatePattern(Extent extent, int color, int complexity, boolean randomize) {
this.extent = extent;
this.util = util;
this.complexity = complexity;
this.randomize = randomize;
this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
this.color = new Color(color).getRGB();
}
@ -37,4 +44,9 @@ public class SaturatePattern extends AbstractPattern {
if (newBlock.equals(block)) return false;
return extent.setBlock(setPosition, newBlock);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
}
}

View File

@ -1,24 +1,29 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.util.TextureUtil;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import java.io.IOException;
import static com.google.common.base.Preconditions.checkNotNull;
public class ShadePattern extends AbstractPattern{
private final TextureUtil util;
private transient TextureUtil util;
private final boolean randomize;
private final int complexity;
private final Extent extent;
private final boolean darken;
public ShadePattern(Extent extent, TextureUtil util, boolean darken) {
public ShadePattern(Extent extent, boolean darken, int complexity, boolean randomize) {
checkNotNull(extent);
checkNotNull(util);
this.extent = extent;
this.util = util;
this.complexity = complexity;
this.randomize = randomize;
this.util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
this.darken = darken;
}
@Override
@ -26,4 +31,9 @@ public class ShadePattern extends AbstractPattern{
BaseBlock block = extent.getBlock(position);
return darken ? util.getDarkerBlock(block) : util.getLighterBlock(block);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
util = Fawe.get().getCachedTextureUtil(randomize, 0, complexity);
}
}

View File

@ -1,7 +1,6 @@
package com.boydti.fawe.object.pattern;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.PseudoRandom;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.WorldEditException;
@ -10,19 +9,28 @@ import com.sk89q.worldedit.blocks.BlockType;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import java.io.IOException;
import java.util.SplittableRandom;
public class SolidRandomOffsetPattern extends AbstractPattern {
private final PseudoRandom r = new PseudoRandom();
private final int dx, dy, dz, dx2, dy2, dz2;
private final int dx, dy, dz;
private final Pattern pattern;
private final MutableBlockVector mutable = new MutableBlockVector();
boolean[] solid;
private transient int dx2, dy2, dz2;
private transient MutableBlockVector mutable;
private transient boolean[] solid;
private SplittableRandom r;
public SolidRandomOffsetPattern(Pattern pattern, int dx, int dy, int dz) {
this.pattern = pattern;
this.dx = dx;
this.dy = dy;
this.dz = dz;
init();
}
private void init() {
this.dx2 = dx * 2 + 1;
this.dy2 = dy * 2 + 1;
this.dz2 = dz * 2 + 1;
@ -34,6 +42,8 @@ public class SolidRandomOffsetPattern extends AbstractPattern {
}
}
}
this.r = new SplittableRandom();
this.mutable = new MutableBlockVector();
}
@Override
@ -61,4 +71,9 @@ public class SolidRandomOffsetPattern extends AbstractPattern {
return pattern.apply(extent, set, get);
}
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
init();
}
}

View File

@ -5,26 +5,28 @@ import com.boydti.fawe.object.PseudoRandom;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import com.sk89q.worldedit.blocks.BaseBlock;
import com.sk89q.worldedit.extent.Extent;
import com.sk89q.worldedit.function.pattern.AbstractPattern;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.function.visitor.BreadthFirstSearch;
import java.io.IOException;
public class SurfaceRandomOffsetPattern extends AbstractPattern {
private final Pattern pattern;
private final Extent extent;
private int moves;
private final MutableBlockVector cur = new MutableBlockVector();
private final MutableBlockVector[] buffer;
private final MutableBlockVector[] allowed;
private MutableBlockVector next;
private transient MutableBlockVector cur;
private transient MutableBlockVector[] buffer;
private transient MutableBlockVector[] allowed;
private transient MutableBlockVector next;
public SurfaceRandomOffsetPattern(Extent extent, Pattern pattern, int distance) {
public SurfaceRandomOffsetPattern(Pattern pattern, int distance) {
this.pattern = pattern;
this.extent = extent;
this.moves = Math.min(255, distance);
init();
}
private void init() {
cur = new MutableBlockVector();
this.buffer = new MutableBlockVector[BreadthFirstSearch.DIAGONAL_DIRECTIONS.length];
for (int i = 0; i < buffer.length; i++) {
buffer[i] = new MutableBlockVector();
@ -88,40 +90,9 @@ public class SurfaceRandomOffsetPattern extends AbstractPattern {
BaseBlock block = pattern.apply(v);
return FaweCache.canPassThrough(block.getId(), block.getData());
}
//
// @Override
// public BaseBlock apply(Vector position) {
// mutable.mutX((position.getX() + r.nextInt(dx2) - dx));
// mutable.mutY((position.getY() + r.nextInt(dy2) - dy));
// mutable.mutZ((position.getZ() + r.nextInt(dz2) - dz));
// BaseBlock block = pattern.apply(mutable);
// if (solid[FaweCache.getCombined(block)]) {
// if (solid[FaweCache.getCombined(mutable)])
// mutable.mutY(mutable.getY() + 1);
// if (!solid[FaweCache.getCombined(pattern.apply(mutable))]) {
// return block;
// }
// }
// return pattern.apply(position);
// }
//
// private Vector get(Vector input) {
// for (dir :
// BreadthFirstSearch.DIAGONAL_DIRECTIONS)
// }
//
// @Override
// public boolean apply(Extent extent, Vector set, Vector get) throws WorldEditException {
// mutable.mutX((get.getX() + r.nextInt(dx2) - dx));
// mutable.mutY((get.getY() + r.nextInt(dy2) - dy));
// mutable.mutZ((get.getZ() + r.nextInt(dz2) - dz));
// BaseBlock block = pattern.apply(mutable);
// if (solid[FaweCache.getCombined(block)]) {
// mutable.mutY(mutable.getY() + 1);
// if (!solid[FaweCache.getCombined(pattern.apply(mutable))]) {
// return pattern.apply(extent, set, mutable);
// }
// }
// return pattern.apply(extent, set, get);
// }
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
stream.defaultReadObject();
init();
}
}

View File

@ -1,30 +0,0 @@
package com.boydti.fawe.object.serializer;
import com.boydti.fawe.FaweCache;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.sk89q.worldedit.blocks.BaseBlock;
import java.lang.reflect.Type;
public class BaseBlockSerializer extends JsonSerializable<BaseBlock> {
@Override
public BaseBlock deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonArray jsonArray = json.getAsJsonArray();
if (jsonArray.size() != 2) {
throw new JsonParseException("Expected array of 3 length for Vector");
}
return FaweCache.getBlock(jsonArray.get(0).getAsInt(), jsonArray.get(1).getAsInt());
}
@Override
public JsonElement serialize(BaseBlock src, Type typeOfSrc, JsonSerializationContext context) {
JsonArray array = new JsonArray();
array.add(new JsonPrimitive(src.getId()));
array.add(new JsonPrimitive(src.getData()));
return array;
}
}

View File

@ -1,36 +0,0 @@
package com.boydti.fawe.object.serializer;
import com.google.gson.JsonArray;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.sk89q.worldedit.MutableBlockVector;
import com.sk89q.worldedit.Vector;
import java.lang.reflect.Type;
public class BlockVectorSerializer extends JsonSerializable<Vector> {
@Override
public JsonElement serialize(Vector src, Type typeOfSrc, JsonSerializationContext context) {
JsonArray array = new JsonArray();
array.add(new JsonPrimitive(src.getBlockX()));
array.add(new JsonPrimitive(src.getBlockY()));
array.add(new JsonPrimitive(src.getBlockZ()));
return array;
}
@Override
public Vector deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonArray jsonArray = json.getAsJsonArray();
if (jsonArray.size() != 3) {
throw new JsonParseException("Expected array of 3 length for Vector");
}
int x = jsonArray.get(0).getAsInt();
int y = jsonArray.get(1).getAsInt();
int z = jsonArray.get(2).getAsInt();
return new MutableBlockVector(x, y, z);
}
}

View File

@ -1,30 +0,0 @@
package com.boydti.fawe.object.serializer;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.util.EditSessionBuilder;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.entity.Player;
import java.lang.reflect.Type;
public class EditSessionSerializer extends JsonSerializable<EditSession> {
private final Player player;
public EditSessionSerializer(Player player) {
this.player = player;
}
@Override
public EditSession deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return new EditSessionBuilder(player.getWorld()).player(FawePlayer.wrap(player)).build();
}
@Override
public JsonElement serialize(EditSession src, Type typeOfSrc, JsonSerializationContext context) {
return null;
}
}

View File

@ -1,50 +0,0 @@
package com.boydti.fawe.object.serializer;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import java.lang.reflect.Field;
public class InheritedExclusion implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> arg0)
{
return false;
}
public boolean shouldSkipField(FieldAttributes fieldAttributes)
{
String fieldName = fieldAttributes.getName();
Class<?> theClass = fieldAttributes.getDeclaringClass();
return isFieldInSuperclass(theClass, fieldName);
}
private boolean isFieldInSuperclass(Class<?> subclass, String fieldName)
{
Class<?> superclass = subclass.getSuperclass();
Field field;
while(superclass != null)
{
field = getField(superclass, fieldName);
if(field != null)
return true;
superclass = superclass.getSuperclass();
}
return false;
}
private Field getField(Class<?> theClass, String fieldName)
{
try
{
return theClass.getDeclaredField(fieldName);
}
catch(Exception e)
{
return null;
}
}
}

View File

@ -1,10 +0,0 @@
package com.boydti.fawe.object.serializer;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonSerializer;
public abstract class JsonSerializable<T> implements JsonSerializer<T>, JsonDeserializer<T> {
public JsonSerializable() {
}
}

View File

@ -1,28 +0,0 @@
package com.boydti.fawe.object.serializer;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.sk89q.worldedit.LocalSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.entity.Player;
import java.lang.reflect.Type;
public class LocalSessionSerializer extends JsonSerializable<LocalSession> {
private final Player player;
public LocalSessionSerializer(Player player) {
this.player = player;
}
@Override
public LocalSession deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return WorldEdit.getInstance().getSessionManager().get(player);
}
@Override
public JsonElement serialize(LocalSession src, Type typeOfSrc, JsonSerializationContext context) {
return null;
}
}

View File

@ -1,25 +0,0 @@
package com.boydti.fawe.object.serializer;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonSerializationContext;
import com.sk89q.worldedit.entity.Player;
import java.lang.reflect.Type;
public class PlayerSerializer extends JsonSerializable<Player> {
private final Player player;
public PlayerSerializer(Player player) {
this.player = player;
}
@Override
public Player deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
return player;
}
@Override
public JsonElement serialize(Player src, Type typeOfSrc, JsonSerializationContext context) {
return null;
}
}

View File

@ -6,9 +6,9 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
public class CachedTextureUtil extends DelegateTextureUtil {
private final TextureUtil parent;
private Int2ObjectOpenHashMap<Integer> colorBlockMap;
private Int2ObjectOpenHashMap<Integer> colorBiomeMap;
private Int2ObjectOpenHashMap<char[]> colorLayerMap;
private transient Int2ObjectOpenHashMap<Integer> colorBlockMap;
private transient Int2ObjectOpenHashMap<Integer> colorBiomeMap;
private transient Int2ObjectOpenHashMap<char[]> colorLayerMap;
public CachedTextureUtil(TextureUtil parent) {
super(parent);

View File

@ -10,7 +10,7 @@ public class CleanTextureUtil extends TextureUtil {
long min = parent.distances[minIndex];
long max = parent.distances[maxIndex];
for (; minIndex > 0 && parent.distances[minIndex - 1] == min; minIndex--);
for (; maxIndex < parent.distances.length - 2 && parent.distances[maxIndex + 1] == max; maxIndex++);
for (; maxIndex < parent.distances.length - 1 && parent.distances[maxIndex + 1] == max; maxIndex++);
int num = maxIndex - minIndex + 1;
this.validBiomes = parent.validBiomes;
this.blockColors = parent.blockColors;

View File

@ -25,13 +25,14 @@ import com.sk89q.minecraft.util.commands.CommandPermissions;
import com.sk89q.minecraft.util.commands.NestedCommand;
import com.sk89q.worldedit.command.BiomeCommands;
import com.sk89q.worldedit.command.BrushCommands;
import com.sk89q.worldedit.command.BrushOptionsCommands;
import com.sk89q.worldedit.command.ChunkCommands;
import com.sk89q.worldedit.command.ClipboardCommands;
import com.sk89q.worldedit.command.GeneralCommands;
import com.sk89q.worldedit.command.GenerationCommands;
import com.sk89q.worldedit.command.HistoryCommands;
import com.sk89q.worldedit.command.MaskCommands;
import com.sk89q.worldedit.command.NavigationCommands;
import com.sk89q.worldedit.command.OptionsCommands;
import com.sk89q.worldedit.command.PatternCommands;
import com.sk89q.worldedit.command.RegionCommands;
import com.sk89q.worldedit.command.SchematicCommands;
@ -41,7 +42,6 @@ import com.sk89q.worldedit.command.SnapshotCommands;
import com.sk89q.worldedit.command.SnapshotUtilCommands;
import com.sk89q.worldedit.command.SuperPickaxeCommands;
import com.sk89q.worldedit.command.ToolCommands;
import com.sk89q.worldedit.command.ToolUtilCommands;
import com.sk89q.worldedit.command.TransformCommands;
import com.sk89q.worldedit.command.UtilityCommands;
import com.sk89q.worldedit.command.WorldEditCommands;
@ -97,7 +97,6 @@ public final class DocumentationPrinter {
stream.println();
StringBuilder builder = new StringBuilder();
writePermissionsWikiTable(stream, builder, "/we ", WorldEditCommands.class);
writePermissionsWikiTable(stream, builder, "/", GeneralCommands.class);
writePermissionsWikiTable(stream, builder, "/", UtilityCommands.class);
writePermissionsWikiTable(stream, builder, "/", RegionCommands.class);
writePermissionsWikiTable(stream, builder, "/", SelectionCommands.class);
@ -106,16 +105,17 @@ public final class DocumentationPrinter {
writePermissionsWikiTable(stream, builder, "/", ClipboardCommands.class);
writePermissionsWikiTable(stream, builder, "/", GenerationCommands.class);
writePermissionsWikiTable(stream, builder, "/", BiomeCommands.class);
writePermissionsWikiTable(stream, builder, "/tool ", ToolCommands.class);
writePermissionsWikiTable(stream, builder, "/", ToolUtilCommands.class);
writePermissionsWikiTable(stream, builder, "/brush ", BrushCommands.class);
writePermissionsWikiTable(stream, builder, "/anvil ", AnvilCommands.class);
writePermissionsWikiTable(stream, builder, "/sp ", SuperPickaxeCommands.class);
writePermissionsWikiTable(stream, builder, "/", NavigationCommands.class);
writePermissionsWikiTable(stream, builder, "/", SnapshotCommands.class);
writePermissionsWikiTable(stream, builder, "/snapshot", SnapshotCommands.class);
writePermissionsWikiTable(stream, builder, "/", SnapshotUtilCommands.class);
writePermissionsWikiTable(stream, builder, "/", ScriptingCommands.class);
writePermissionsWikiTable(stream, builder, "/", ChunkCommands.class);
writePermissionsWikiTable(stream, builder, "/", OptionsCommands.class);
writePermissionsWikiTable(stream, builder, "/", BrushOptionsCommands.class);
writePermissionsWikiTable(stream, builder, "/tool ", ToolCommands.class);
writePermissionsWikiTable(stream, builder, "/brush ", BrushCommands.class);
writePermissionsWikiTable(stream, builder, "/masks ", MaskCommands.class);
writePermissionsWikiTable(stream, builder, "/patterns ", PatternCommands.class);
writePermissionsWikiTable(stream, builder, "/transforms ", TransformCommands.class);

View File

@ -41,6 +41,11 @@ public class StringMan {
return -1;
}
public static String toProperCase(String s) {
return s.substring(0, 1).toUpperCase() +
s.substring(1);
}
public static List<String> split(String input, char delim) {
List<String> result = new ArrayList<String>();
int start = 0;

View File

@ -1,8 +1,3 @@
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//
package com.sk89q.worldedit;
/** @deprecated */

View File

@ -31,7 +31,6 @@ import com.boydti.fawe.object.changeset.FaweChangeSet;
import com.boydti.fawe.object.extent.ResettableExtent;
import com.boydti.fawe.util.EditSessionBuilder;
import com.boydti.fawe.util.MainUtil;
import com.boydti.fawe.util.TaskManager;
import com.boydti.fawe.wrappers.WorldWrapper;
import com.sk89q.jchronic.Chronic;
import com.sk89q.jchronic.Options;
@ -984,10 +983,12 @@ public class LocalSession {
return getBrushTool(item, 0, null, true);
}
@Deprecated
public BrushTool getBrushTool(Player player) throws InvalidToolBindException {
return getBrushTool(player, true);
}
@Deprecated
public BrushTool getBrushTool(Player player, boolean create) throws InvalidToolBindException {
BaseBlock block;
try {
@ -1000,12 +1001,13 @@ public class LocalSession {
}
@Deprecated
public BrushTool getBrushTool(int id, int data, Player player, boolean create) throws InvalidToolBindException {
Tool tool = getTool(id, data);
if ((tool == null || !(tool instanceof BrushTool))) {
if (create) {
tool = new BrushTool("worldedit.brush.sphere");
tool = new BrushTool();
setTool(id, data, tool, player);
} else {
return null;

View File

@ -1,6 +1,11 @@
package com.sk89q.worldedit;
public class MutableBlockVector extends BlockVector {
import java.io.IOException;
import java.io.Serializable;
public class MutableBlockVector extends BlockVector implements Serializable {
private transient int x,y,z;
private static ThreadLocal<MutableBlockVector> MUTABLE_CACHE = new ThreadLocal<MutableBlockVector>() {
@Override
protected MutableBlockVector initialValue() {
@ -12,8 +17,6 @@ public class MutableBlockVector extends BlockVector {
return MUTABLE_CACHE.get().setComponents(x, y, z);
}
private int x,y,z;
public MutableBlockVector(Vector v) {
this(v.getBlockX(), v.getBlockY(), v.getBlockZ());
}
@ -105,4 +108,16 @@ public class MutableBlockVector extends BlockVector {
public int getBlockZ() {
return this.z;
}
private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
stream.writeInt(x);
stream.writeByte((byte) y);
stream.writeInt(z);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
this.x = stream.readInt();
this.y = stream.readByte() & 0xFF;
this.z = stream.readInt();
}
}

View File

@ -1,6 +1,9 @@
package com.sk89q.worldedit;
public final class MutableBlockVector2D extends Vector2D {
import java.io.IOException;
import java.io.Serializable;
public final class MutableBlockVector2D extends Vector2D implements Serializable {
private static ThreadLocal<MutableBlockVector2D> MUTABLE_CACHE = new ThreadLocal<MutableBlockVector2D>() {
@Override
protected MutableBlockVector2D initialValue() {
@ -12,7 +15,7 @@ public final class MutableBlockVector2D extends Vector2D {
return MUTABLE_CACHE.get().setComponents(x, z);
}
private int x, z;
private transient int x, z;
public MutableBlockVector2D() {
this.x = 0;
@ -64,4 +67,14 @@ public final class MutableBlockVector2D extends Vector2D {
public void mutZ(double z) {
this.z = (int) z;
}
private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
stream.writeInt(x);
stream.writeInt(z);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
this.x = stream.readInt();
this.z = stream.readInt();
}
}

View File

@ -21,12 +21,14 @@ package com.sk89q.worldedit;
import com.sk89q.worldedit.math.transform.AffineTransform;
import java.io.IOException;
import java.io.Serializable;
import javax.annotation.Nullable;
/**
* An immutable 3-dimensional vector.
*/
public class Vector implements Comparable<Vector> {
public class Vector implements Comparable<Vector>, Serializable {
public static final Vector ZERO = new Vector(0, 0, 0);
public static final Vector UNIT_X = new Vector(1, 0, 0);
@ -34,9 +36,7 @@ public class Vector implements Comparable<Vector> {
public static final Vector UNIT_Z = new Vector(0, 0, 1);
public static final Vector ONE = new Vector(1, 1, 1);
private double x;
private double y;
private double z;
private transient double x, y, z;
/**
* Construct an instance.
@ -888,6 +888,21 @@ public class Vector implements Comparable<Vector> {
);
}
private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
if (!(this instanceof Vector)) {
stream.writeDouble(x);
stream.writeDouble(y);
stream.writeDouble(z);
}
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
if (this instanceof MutableBlockVector) return;
this.x = stream.readDouble();
this.y = stream.readDouble();
this.z = stream.readDouble();
}
public static Class<?> inject() {
return Vector.class;
}

View File

@ -20,18 +20,19 @@
package com.sk89q.worldedit;
import com.sk89q.worldedit.math.transform.AffineTransform;
import java.io.IOException;
import java.io.Serializable;
/**
* An immutable 2-dimensional vector.
*/
public class Vector2D {
public class Vector2D implements Serializable {
public static final Vector2D ZERO = new Vector2D(0, 0);
public static final Vector2D UNIT_X = new Vector2D(1, 0);
public static final Vector2D UNIT_Z = new Vector2D(0, 1);
public static final Vector2D ONE = new Vector2D(1, 1);
public double x;
public double z;
public transient double x, z;
/**
* Construct an instance.
@ -665,6 +666,18 @@ public class Vector2D {
);
}
private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
if (this instanceof MutableBlockVector2D) return;
stream.writeDouble(x);
stream.writeDouble(z);
}
private void readObject(java.io.ObjectInputStream stream) throws IOException, ClassNotFoundException {
if (this instanceof MutableBlockVector2D) return;
this.x = stream.readDouble();
this.z = stream.readDouble();
}
public static Class<?> inject() {
return Vector2D.class;
}

View File

@ -21,6 +21,8 @@ package com.sk89q.worldedit.blocks;
import com.boydti.fawe.FaweCache;
import com.sk89q.jnbt.CompoundTag;
import com.sk89q.jnbt.NBTInputStream;
import com.sk89q.jnbt.NBTOutputStream;
import com.sk89q.jnbt.StringTag;
import com.sk89q.jnbt.Tag;
import com.sk89q.worldedit.CuboidClipboard.FlipDirection;
@ -31,9 +33,11 @@ import com.sk89q.worldedit.foundation.Block;
import com.sk89q.worldedit.function.mask.Mask;
import com.sk89q.worldedit.function.pattern.Pattern;
import com.sk89q.worldedit.world.registry.WorldData;
import javax.annotation.Nullable;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.util.Collection;
import javax.annotation.Nullable;
/**
* Represents a mutable "snapshot" of a block.
@ -59,7 +63,7 @@ import java.util.Collection;
* more appropriate.</p>
*/
@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<BaseBlock> inject() {
return BaseBlock.class;
}

View File

@ -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;

View File

@ -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() {

Some files were not shown because too many files have changed in this diff Show More