mirror of
https://github.com/boy0001/FastAsyncWorldedit.git
synced 2024-12-29 12:37:53 +01:00
Various
Optimize for 1.12 Refactor commands / style / cleanup Brush saving/loading Tweak / improve ChunkListener
This commit is contained in:
parent
de26c22f05
commit
b9c056c879
@ -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'
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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"),
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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) {
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)));
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@ -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!");
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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!");
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -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() {
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -1,8 +1,3 @@
|
||||
//
|
||||
// Source code recreated from a .class file by IntelliJ IDEA
|
||||
// (powered by Fernflower decompiler)
|
||||
//
|
||||
|
||||
package com.sk89q.worldedit;
|
||||
|
||||
/** @deprecated */
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user