Update to 1.9

This commit is contained in:
Jesse Boyd 2016-03-03 08:51:41 +11:00
parent 58b6a946de
commit 5edfcecc69
7 changed files with 978 additions and 6 deletions

View File

@ -8,7 +8,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties> </properties>
<artifactId>FastAsyncWorldEdit</artifactId> <artifactId>FastAsyncWorldEdit</artifactId>
<version>1.3.1</version> <version>1.3.2</version>
<name>FastAsyncWorldEdit</name> <name>FastAsyncWorldEdit</name>
<packaging>jar</packaging> <packaging>jar</packaging>
<build> <build>
@ -213,7 +213,7 @@
<dependency> <dependency>
<groupId>com.intellectualcrafters.plot</groupId> <groupId>com.intellectualcrafters.plot</groupId>
<artifactId>plotsquared</artifactId> <artifactId>plotsquared</artifactId>
<version>3.2.24</version> <version>3.3.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>com.worldcretornica</groupId> <groupId>com.worldcretornica</groupId>

View File

@ -133,6 +133,10 @@ public class Fawe {
TaskManager.IMP.repeat(lag, 100); TaskManager.IMP.repeat(lag, 100);
} }
public boolean checkVersion(final int[] version, final int major, final int minor, final int minor2) {
return (version[0] > major) || ((version[0] == major) && (version[1] > minor)) || ((version[0] == major) && (version[1] == minor) && (version[2] >= minor2));
}
private void setupEvents() { private void setupEvents() {
WorldEdit.getInstance().getEventBus().register(new WESubscriber()); WorldEdit.getInstance().getEventBus().register(new WESubscriber());
if (Settings.COMMAND_PROCESSOR) { if (Settings.COMMAND_PROCESSOR) {

View File

@ -24,6 +24,7 @@ import com.boydti.fawe.bukkit.regions.TownyFeature;
import com.boydti.fawe.bukkit.regions.Worldguard; import com.boydti.fawe.bukkit.regions.Worldguard;
import com.boydti.fawe.bukkit.v1_8.BukkitEditSessionWrapper_1_8; import com.boydti.fawe.bukkit.v1_8.BukkitEditSessionWrapper_1_8;
import com.boydti.fawe.bukkit.v1_8.BukkitQueue_1_8; import com.boydti.fawe.bukkit.v1_8.BukkitQueue_1_8;
import com.boydti.fawe.bukkit.v1_9.BukkitQueue_1_9;
import com.boydti.fawe.object.EditSessionWrapper; import com.boydti.fawe.object.EditSessionWrapper;
import com.boydti.fawe.object.FaweCommand; import com.boydti.fawe.object.FaweCommand;
import com.boydti.fawe.object.FawePlayer; import com.boydti.fawe.object.FawePlayer;
@ -133,9 +134,38 @@ public class FaweBukkit extends JavaPlugin implements IFawe {
@Override @Override
public FaweQueue getQueue() { public FaweQueue getQueue() {
if (Fawe.get().checkVersion(getServerVersion(), 1, 9, 0)) {
try {
return new BukkitQueue_1_9();
} catch (Throwable e) {
e.printStackTrace();
}
}
return new BukkitQueue_1_8(); return new BukkitQueue_1_8();
} }
private int[] version;
public int[] getServerVersion() {
if (version == null) {
try {
version = new int[3];
final String[] split = Bukkit.getBukkitVersion().split("-")[0].split("\\.");
version[0] = Integer.parseInt(split[0]);
version[1] = Integer.parseInt(split[1]);
if (split.length == 3) {
version[2] = Integer.parseInt(split[2]);
}
} catch (NumberFormatException e) {
e.printStackTrace();
Fawe.debug(StringMan.getString(Bukkit.getBukkitVersion()));
Fawe.debug(StringMan.getString(Bukkit.getBukkitVersion().split("-")[0].split("\\.")));
return new int[] { Integer.MAX_VALUE, 0, 0 };
}
}
return version;
}
@Override @Override
public EditSessionWrapper getEditSessionWrapper(final EditSession session) { public EditSessionWrapper getEditSessionWrapper(final EditSession session) {
return new BukkitEditSessionWrapper_1_8(session); return new BukkitEditSessionWrapper_1_8(session);

View File

@ -15,7 +15,6 @@ import com.intellectualcrafters.plot.PS;
import com.intellectualcrafters.plot.object.Plot; import com.intellectualcrafters.plot.object.Plot;
import com.intellectualcrafters.plot.object.PlotId; import com.intellectualcrafters.plot.object.PlotId;
import com.intellectualcrafters.plot.object.PlotPlayer; import com.intellectualcrafters.plot.object.PlotPlayer;
import com.intellectualcrafters.plot.util.MainUtil;
import com.plotsquared.bukkit.BukkitMain; import com.plotsquared.bukkit.BukkitMain;
public class PlotSquaredFeature extends BukkitMaskManager implements Listener { public class PlotSquaredFeature extends BukkitMaskManager implements Listener {
@ -37,7 +36,7 @@ public class PlotSquaredFeature extends BukkitMaskManager implements Listener {
final String world = loc.getWorld(); final String world = loc.getWorld();
int min = Integer.MAX_VALUE; int min = Integer.MAX_VALUE;
for (final Plot p : pp.getPlots()) { for (final Plot p : pp.getPlots()) {
if (p.world.equals(world)) { if (p.getArea().worldname.equals(world)) {
final double d = p.getHome().getEuclideanDistanceSquared(loc); final double d = p.getHome().getEuclideanDistanceSquared(loc);
if (d < min) { if (d < min) {
min = (int) d; min = (int) d;
@ -57,8 +56,8 @@ public class PlotSquaredFeature extends BukkitMaskManager implements Listener {
} }
if (hasPerm) { if (hasPerm) {
final World world = fp.parent.getWorld(); final World world = fp.parent.getWorld();
final com.intellectualcrafters.plot.object.RegionWrapper region = MainUtil.getLargestRegion(plot); final com.intellectualcrafters.plot.object.RegionWrapper region = plot.getLargestRegion();
final HashSet<com.intellectualcrafters.plot.object.RegionWrapper> regions = MainUtil.getRegions(plot); final HashSet<com.intellectualcrafters.plot.object.RegionWrapper> regions = plot.getRegions();
final Location pos1 = new Location(world, region.minX, 0, region.minZ); final Location pos1 = new Location(world, region.minX, 0, region.minZ);
final Location pos2 = new Location(world, region.maxX, 256, region.maxZ); final Location pos2 = new Location(world, region.maxX, 256, region.maxZ);

View File

@ -0,0 +1,237 @@
package com.boydti.fawe.bukkit.v1_9;
import java.util.Arrays;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.object.ChunkLoc;
import com.boydti.fawe.object.FaweChunk;
import com.sk89q.worldedit.world.biome.BaseBiome;
public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
private int[][] ids;
private final short[] count;
private final short[] air;
private final short[] relight;
public int[][] biomes;
public Chunk chunk;
/**
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
*/
protected BukkitChunk_1_9(final ChunkLoc chunk) {
super(chunk);
ids = new int[16][];
count = new short[16];
air = new short[16];
relight = new short[16];
}
@Override
public Chunk getChunk() {
if (chunk == null) {
final ChunkLoc cl = getChunkLoc();
chunk = Bukkit.getWorld(cl.world).getChunkAt(cl.x, cl.z);
}
return chunk;
}
@Override
public void setChunkLoc(final ChunkLoc loc) {
super.setChunkLoc(loc);
chunk = null;
}
/**
* Get the number of block changes in a specified section
* @param i
* @return
*/
public int getCount(final int i) {
return count[i];
}
public int getAir(final int i) {
return air[i];
}
public void setCount(int i, short value) {
count[i] = value;
}
/**
* Get the number of block changes in a specified section
* @param i
* @return
*/
public int getRelight(final int i) {
return relight[i];
}
public int getTotalCount() {
int total = 0;
for (int i = 0; i < 16; i++) {
total += count[i];
}
return total;
}
public int getTotalRelight() {
if (getTotalCount() == 0 && biomes == null) {
Arrays.fill(count, (short) 1);
Arrays.fill(relight, Short.MAX_VALUE);
return Short.MAX_VALUE;
}
int total = 0;
for (int i = 0; i < 16; i++) {
total += relight[i];
}
return total;
}
/**
* Get the raw data for a section
* @param i
* @return
*/
public int[] getIdArray(final int i) {
return ids[i];
}
public int[][] getIdArrays() {
return ids;
}
public void clear() {
ids = null;
biomes = null;
}
public int[][] getBiomeArray() {
return biomes;
}
@Override
public void setBlock(final int x, final int y, final int z, final int id, byte data) {
final int i = FaweCache.CACHE_I[y][x][z];
final int j = FaweCache.CACHE_J[y][x][z];
int[] vs = ids[i];
if (vs == null) {
vs = ids[i] = new int[4096];
count[i]++;
} else if (vs[j] == 0) {
count[i]++;
}
switch (id) {
case 0:
air[i]++;
vs[j] = -1;
return;
case 10:
case 11:
case 39:
case 40:
case 51:
case 74:
case 89:
case 122:
case 124:
case 138:
case 169:
relight[i]++;
case 2:
case 4:
case 13:
case 14:
case 15:
case 20:
case 21:
case 22:
case 30:
case 32:
case 37:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
case 55:
case 56:
case 57:
case 58:
case 60:
case 7:
case 8:
case 9:
case 73:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 85:
case 87:
case 88:
case 101:
case 102:
case 103:
case 110:
case 112:
case 113:
case 121:
case 129:
case 133:
case 165:
case 166:
case 170:
case 172:
case 173:
case 174:
case 181:
case 182:
case 188:
case 189:
case 190:
case 191:
case 192:
vs[j] = (id);
return;
case 130:
case 76:
case 62:
relight[i]++;
case 54:
case 146:
case 61:
case 65:
case 68:
case 50:
if (data < 2) {
data = 2;
}
default:
vs[j] = id + (data << 12);
return;
}
}
@Override
public void setBiome(int x, int z, BaseBiome biome) {
if (biomes == null) {
biomes = new int[16][];
}
int[] index = biomes[x];
if (index == null) {
index = biomes[x] = new int[16];
}
index[z] = biome.getId();
}
}

View File

@ -0,0 +1,699 @@
package com.boydti.fawe.bukkit.v1_9;
import static com.boydti.fawe.util.ReflectionUtils.getRefClass;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.bukkit.Bukkit;
import org.bukkit.Chunk;
import org.bukkit.Location;
import org.bukkit.Material;
import org.bukkit.World;
import org.bukkit.World.Environment;
import org.bukkit.block.Biome;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.generator.BlockPopulator;
import org.bukkit.generator.ChunkGenerator;
import com.boydti.fawe.Fawe;
import com.boydti.fawe.FaweCache;
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
import com.boydti.fawe.config.Settings;
import com.boydti.fawe.object.ChunkLoc;
import com.boydti.fawe.object.FaweChunk;
import com.boydti.fawe.object.FawePlayer;
import com.boydti.fawe.object.IntegerPair;
import com.boydti.fawe.object.PseudoRandom;
import com.boydti.fawe.util.MemUtil;
import com.boydti.fawe.util.ReflectionUtils.RefClass;
import com.boydti.fawe.util.ReflectionUtils.RefConstructor;
import com.boydti.fawe.util.ReflectionUtils.RefField;
import com.boydti.fawe.util.ReflectionUtils.RefMethod;
import com.boydti.fawe.util.ReflectionUtils.RefMethod.RefExecutor;
import com.sk89q.worldedit.LocalSession;
public class BukkitQueue_1_9 extends BukkitQueue_0 {
private final RefClass classEntityPlayer = getRefClass("{nms}.EntityPlayer");
private final RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk");
private final RefClass classPacket = getRefClass("{nms}.Packet");
private final RefClass classConnection = getRefClass("{nms}.PlayerConnection");
private final RefClass classChunk = getRefClass("{nms}.Chunk");
private final RefClass classCraftPlayer = getRefClass("{cb}.entity.CraftPlayer");
private final RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
private final RefClass classWorld = getRefClass("{nms}.World");
private final RefField mustSave = classChunk.getField("mustSave");
private final RefClass classBlockPosition = getRefClass("{nms}.BlockPosition");
private final RefClass classChunkSection = getRefClass("{nms}.ChunkSection");
private final RefClass classBlock = getRefClass("{nms}.Block");
private final RefClass classIBlockData = getRefClass("{nms}.IBlockData");
private final RefMethod methodGetHandleChunk;
private final RefConstructor MapChunk;
private final RefMethod methodInitLighting;
private final RefConstructor classBlockPositionConstructor;
private final RefConstructor classChunkSectionConstructor;
private final RefMethod methodW;
private final RefMethod methodAreNeighborsLoaded;
private final RefField fieldSections;
private final RefField fieldWorld;
private final RefMethod methodGetBlocks;
private final RefMethod methodGetType;
private final RefMethod methodSetType;
private final RefMethod methodGetCombinedId;
private final RefMethod methodGetByCombinedId;
private final Object air;
private final RefMethod methodGetHandlePlayer;
private final RefField connection;
private final RefMethod send;
public BukkitQueue_1_9() throws NoSuchMethodException, RuntimeException {
methodGetHandlePlayer = classCraftPlayer.getMethod("getHandle");
connection = classEntityPlayer.getField("playerConnection");
send = classConnection.getMethod("sendPacket", classPacket.getRealClass());
methodGetHandleChunk = classCraftChunk.getMethod("getHandle");
methodInitLighting = classChunk.getMethod("initLighting");
MapChunk = classMapChunk.getConstructor(classChunk.getRealClass(), boolean.class, int.class);
classBlockPositionConstructor = classBlockPosition.getConstructor(int.class, int.class, int.class);
methodW = classWorld.getMethod("w", classBlockPosition.getRealClass());
fieldSections = classChunk.getField("sections");
fieldWorld = classChunk.getField("world");
methodGetCombinedId = classBlock.getMethod("getCombinedId", classIBlockData.getRealClass());
methodGetByCombinedId = classBlock.getMethod("getByCombinedId", int.class);
methodGetBlocks = classChunkSection.getMethod("getBlocks");
methodGetType = classChunkSection.getMethod("getType", int.class, int.class, int.class);
methodSetType = classChunkSection.getMethod("setType", int.class, int.class, int.class, classIBlockData.getRealClass());
methodAreNeighborsLoaded = classChunk.getMethod("areNeighborsLoaded", int.class);
classChunkSectionConstructor = classChunkSection.getConstructor(int.class, boolean.class, char[].class);
air = methodGetByCombinedId.call(0);
}
@Override
public Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs) {
final HashMap<FaweChunk<Chunk>, Object> packets = new HashMap<>();
final HashMap<String, ArrayList<FaweChunk<Chunk>>> map = new HashMap<>();
for (final FaweChunk<Chunk> fc : fcs) {
String world = fc.getChunkLoc().world;
ArrayList<FaweChunk<Chunk>> list = map.get(world);
if (list == null) {
list = new ArrayList<>();
map.put(world, list);
}
list.add(fc);
}
final int view = Bukkit.getServer().getViewDistance();
for (final Player player : Bukkit.getOnlinePlayers()) {
final String world = player.getWorld().getName();
final ArrayList<FaweChunk<Chunk>> list = map.get(world);
if (list == null) {
continue;
}
final Location loc = player.getLocation();
final int cx = loc.getBlockX() >> 4;
final int cz = loc.getBlockZ() >> 4;
final Object entity = methodGetHandlePlayer.of(player).call();
for (final FaweChunk<Chunk> fc : list) {
final int dx = Math.abs(cx - fc.getChunkLoc().x);
final int dz = Math.abs(cz - fc.getChunkLoc().z);
if ((dx > view) || (dz > view)) {
continue;
}
RefExecutor con = send.of(connection.of(entity).get());
Object packet = packets.get(fc);
if (packet == null) {
final Object c = methodGetHandleChunk.of(fc.getChunk()).call();
packet = MapChunk.create(c, true, 65535);
packets.put(fc, packet);
con.call(packet);
} else {
con.call(packet);
}
}
}
final HashSet<FaweChunk<Chunk>> chunks = new HashSet<FaweChunk<Chunk>>();
for (FaweChunk<Chunk> fc : fcs) {
Chunk chunk = fc.getChunk();
chunk.unload(true, false);
chunk.load();
ChunkLoc loc = fc.getChunkLoc();
chunk.getWorld().refreshChunk(loc.x, loc.z);
if (!fixLighting(fc, Settings.FIX_ALL_LIGHTING)) {
chunks.add(fc);
}
}
return chunks;
}
@Override
public boolean fixLighting(final FaweChunk<?> pc, boolean fixAll) {
try {
BukkitChunk_1_9 bc = (BukkitChunk_1_9) pc;
final Chunk chunk = bc.getChunk();
if (!chunk.isLoaded()) {
chunk.load(false);
} else {
chunk.unload(true, false);
chunk.load(false);
}
// Initialize lighting
final Object c = methodGetHandleChunk.of(chunk).call();
if (fixAll && !(boolean) methodAreNeighborsLoaded.of(c).call(1)) {
World world = chunk.getWorld();
ChunkLoc wrapper = bc.getChunkLoc();
String worldname = wrapper.world;
for (int x = wrapper.x - 1; x <= wrapper.x + 1; x++) {
for (int z = wrapper.z - 1; z <= wrapper.z + 1; z++) {
if (x != 0 && z != 0) {
Chunk other = world.getChunkAt(x, z);
while (!other.isLoaded()) {
other.load(true);
}
}
}
}
}
methodInitLighting.of(c).call();
if ((bc.getTotalRelight() == 0 && !fixAll)) {
return true;
}
final Object[] sections = (Object[]) fieldSections.of(c).get();
final Object w = fieldWorld.of(c).get();
final int X = chunk.getX() << 4;
final int Z = chunk.getZ() << 4;
RefExecutor relight = methodW.of(w);
for (int j = 0; j < sections.length; j++) {
final Object section = sections[j];
if (section == null) {
continue;
}
if ((bc.getRelight(j) == 0 && !fixAll) || bc.getCount(j) == 0 || (bc.getCount(j) >= 4096 && bc.getAir(j) == 0)) {
continue;
}
final int[] array = bc.getIdArray(j);
int l = PseudoRandom.random.random(2);
for (int k = 0; k < array.length; k++) {
final int i = array[k];
if (i < 16) {
continue;
}
final short id = (short) (i >> 4);
switch (id) { // Lighting
default:
if (!fixAll) {
continue;
}
if ((k & 1) == l) {
l = 1 - l;
continue;
}
case 10:
case 11:
case 39:
case 40:
case 50:
case 51:
case 62:
case 74:
case 76:
case 89:
case 122:
case 124:
case 130:
case 138:
case 169:
final int x = FaweCache.CACHE_X[j][k];
final int y = FaweCache.CACHE_Y[j][k];
final int z = FaweCache.CACHE_Z[j][k];
if (isSurrounded(bc.getIdArrays(), x, y, z)) {
continue;
}
final Object pos = classBlockPositionConstructor.create(X + x, y, Z + z);
relight.call(pos);
}
}
}
return true;
} catch (final Throwable e) {
e.printStackTrace();
}
return false;
}
public boolean isSurrounded(int[][] sections, int x, int y, int z) {
return isSolid(getId(sections, x, y + 1, z))
&& isSolid(getId(sections, x + 1, y - 1, z))
&& isSolid(getId(sections, x - 1, y, z))
&& isSolid(getId(sections, x, y, z + 1))
&& isSolid(getId(sections, x, y, z - 1));
}
public boolean isSolid(int i) {
return i != 0 && Material.getMaterial(i).isOccluding();
}
public int getId(int[][] sections, int x, int y, int z) {
if (x < 0 || x > 15 || z < 0 || z > 15) {
return 1;
}
if (y < 0 || y > 255) {
return 1;
}
int i = FaweCache.CACHE_I[y][x][z];
int[] section = sections[i];
if (section == null) {
return 0;
}
int j = FaweCache.CACHE_J[y][x][z];
return section[j];
}
public Object getBlocks(final Object obj) {
return methodGetBlocks.of(obj).call();
}
@Override
public boolean setComponents(final FaweChunk<Chunk> pc) {
BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc;
Chunk chunk = pc.getChunk();
final World world = chunk.getWorld();
ChunkLoc wrapper = pc.getChunkLoc();
chunk.load(true);
try {
final boolean flag = world.getEnvironment() == Environment.NORMAL;
// Sections
final Method getHandele = chunk.getClass().getDeclaredMethod("getHandle");
final Object c = getHandele.invoke(chunk);
final Class<? extends Object> clazz = c.getClass();
final Field sf = clazz.getDeclaredField("sections");
sf.setAccessible(true);
final Field tf = clazz.getDeclaredField("tileEntities");
final Field ef = clazz.getDeclaredField("entitySlices");
final Object[] sections = (Object[]) sf.get(c);
final HashMap<?, ?> tiles = (HashMap<?, ?>) tf.get(c);
final List<?>[] entities = (List<?>[]) ef.get(c);
Method xm = null;
Method ym = null;
Method zm = null;
// Trim tiles
final Set<Entry<?, ?>> entryset = (Set<Entry<?, ?>>) (Set<?>) tiles.entrySet();
final Iterator<Entry<?, ?>> iter = entryset.iterator();
while (iter.hasNext()) {
final Entry<?, ?> tile = iter.next();
final Object pos = tile.getKey();
if (xm == null) {
final Class<? extends Object> clazz2 = pos.getClass().getSuperclass();
xm = clazz2.getDeclaredMethod("getX");
ym = clazz2.getDeclaredMethod("getY");
zm = clazz2.getDeclaredMethod("getZ");
}
final int lx = (int) xm.invoke(pos) & 15;
final int ly = (int) ym.invoke(pos);
final int lz = (int) zm.invoke(pos) & 15;
final int j = FaweCache.CACHE_I[ly][lx][lz];
final int k = FaweCache.CACHE_J[ly][lx][lz];
final int[] array = fs.getIdArray(j);
if (array == null) {
continue;
}
if (array[k] != 0) {
iter.remove();
}
}
// Trim entities
for (int i = 0; i < 16; i++) {
if ((entities[i] != null) && (fs.getCount(i) >= 4096)) {
entities[i].clear();
}
}
// Efficiently merge sections
for (int j = 0; j < sections.length; j++) {
if (fs.getCount(j) == 0) {
continue;
}
final int[] newArray = fs.getIdArray(j);
if (newArray == null) {
continue;
}
Object section = sections[j];
if ((section == null) || (fs.getCount(j) >= 4096)) {
char[] array = new char[4096];
for (int i = 0; i < newArray.length; i++) {
int combined = newArray[i];
int id = combined & 4095;
int data = combined >> 12;
array[i] = (char) ((id << 4) + data);
}
section = sections[j] = newChunkSection(j << 4, flag, array);
continue;
}
final Object currentArray = getBlocks(section);
RefExecutor setType = methodSetType.of(section);
boolean fill = true;
for (int k = 0; k < newArray.length; k++) {
final int n = newArray[k];
switch (n) {
case 0:
fill = false;
continue;
case -1: {
fill = false;
int x = FaweCache.CACHE_X[j][k];
int y = FaweCache.CACHE_Y[j][k];
int z = FaweCache.CACHE_Z[j][k];
setType.call(x, y & 15, z, air);
continue;
}
default: {
int x = FaweCache.CACHE_X[j][k];
int y = FaweCache.CACHE_Y[j][k];
int z = FaweCache.CACHE_Z[j][k];
int id = n;
Object iblock = methodGetByCombinedId.call(n);
setType.call(x, y & 15, z, iblock);
continue;
}
}
}
if (fill) {
fs.setCount(j, Short.MAX_VALUE);
}
}
// Clear
} catch (IllegalAccessException | IllegalArgumentException | NoSuchMethodException | SecurityException | InvocationTargetException | NoSuchFieldException e) {
e.printStackTrace();
}
int[][] biomes = fs.biomes;
Biome[] values = Biome.values();
if (biomes != null) {
for (int x = 0; x < 16; x++) {
int[] array = biomes[x];
if (array == null) {
continue;
}
for (int z = 0; z < 16; z++) {
int biome = array[z];
if (biome == 0) {
continue;
}
chunk.getBlock(x, 0, z).setBiome(values[biome]);
}
}
}
return true;
}
@Override
public void clear() {
super.clear();
ArrayDeque<Chunk> toUnload = new ArrayDeque<>();
final int distance = Bukkit.getViewDistance() + 2;
HashMap<String, HashMap<IntegerPair, Integer>> players = new HashMap<>();
for (final Player player : Bukkit.getOnlinePlayers()) {
// Clear history
FawePlayer<Object> fp = FawePlayer.wrap(player);
LocalSession s = fp.getSession();
if (s != null) {
s.clearHistory();
s.setClipboard(null);
}
final Location loc = player.getLocation();
final World worldObj = loc.getWorld();
final String world = worldObj.getName();
HashMap<IntegerPair, Integer> map = players.get(world);
if (map == null) {
map = new HashMap<>();
players.put(world, map);
}
final IntegerPair origin = new IntegerPair(loc.getBlockX() >> 4, loc.getBlockZ() >> 4);
Integer val = map.get(origin);
int check;
if (val != null) {
if (val == distance) {
continue;
}
check = distance - val;
} else {
check = distance;
map.put(origin, distance);
}
for (int x = -distance; x <= distance; x++) {
if ((x >= check) || (-x >= check)) {
continue;
}
for (int z = -distance; z <= distance; z++) {
if ((z >= check) || (-z >= check)) {
continue;
}
final int weight = distance - Math.max(Math.abs(x), Math.abs(z));
final IntegerPair chunk = new IntegerPair(x + origin.x, z + origin.z);
val = map.get(chunk);
if ((val == null) || (val < weight)) {
map.put(chunk, weight);
}
}
}
}
Fawe.get().getWorldEdit().clearSessions();
for (final World world : Bukkit.getWorlds()) {
final String name = world.getName();
final HashMap<IntegerPair, Integer> map = players.get(name);
if ((map == null) || (map.size() == 0)) {
final boolean save = world.isAutoSave();
world.setAutoSave(false);
for (final Chunk chunk : world.getLoadedChunks()) {
unloadChunk(name, chunk);
}
world.setAutoSave(save);
continue;
}
final Chunk[] chunks = world.getLoadedChunks();
for (final Chunk chunk : chunks) {
final int x = chunk.getX();
final int z = chunk.getZ();
if (!map.containsKey(new IntegerPair(x, z))) {
toUnload.add(chunk);
} else if (chunk.getEntities().length > 4096) {
for (final Entity ent : chunk.getEntities()) {
ent.remove();
}
}
}
}
// GC again
System.gc();
System.gc();
// If still critical memory
int free = MemUtil.calculateMemory();
if (free <= 1) {
for (final Chunk chunk : toUnload) {
unloadChunk(chunk.getWorld().getName(), chunk);
}
} else if (free == Integer.MAX_VALUE) {
for (final Chunk chunk : toUnload) {
chunk.unload(true, false);
}
} else {
return;
}
toUnload = null;
players = null;
System.gc();
System.gc();
free = MemUtil.calculateMemory();
if (free > 1) {
return;
}
Collection<? extends Player> online = Bukkit.getOnlinePlayers();
if (online.size() > 0) {
online.iterator().next().kickPlayer("java.lang.OutOfMemoryError");
}
online = null;
System.gc();
System.gc();
free = MemUtil.calculateMemory();
if ((free > 1) || (Bukkit.getOnlinePlayers().size() > 0)) {
return;
}
for (final World world : Bukkit.getWorlds()) {
final String name = world.getName();
for (final Chunk chunk : world.getLoadedChunks()) {
unloadChunk(name, chunk);
}
}
System.gc();
System.gc();
}
public Object newChunkSection(final int i, final boolean flag, final char[] ids) {
return classChunkSectionConstructor.create(i, flag, ids);
}
@Override
public FaweChunk<Chunk> getChunk(final ChunkLoc wrap) {
return new BukkitChunk_1_9(wrap);
}
public boolean unloadChunk(final String world, final Chunk chunk) {
final Object c = methodGetHandleChunk.of(chunk).call();
mustSave.of(c).set(false);
if (chunk.isLoaded()) {
chunk.unload(false, false);
}
return true;
}
public ChunkGenerator setGenerator(final World world, final ChunkGenerator newGen) {
try {
final ChunkGenerator gen = world.getGenerator();
final Class<? extends World> clazz = world.getClass();
final Field generator = clazz.getDeclaredField("generator");
generator.setAccessible(true);
generator.set(world, newGen);
final Field wf = clazz.getDeclaredField("world");
wf.setAccessible(true);
final Object w = wf.get(world);
final Class<?> clazz2 = w.getClass().getSuperclass();
final Field generator2 = clazz2.getDeclaredField("generator");
generator2.set(w, newGen);
return gen;
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
public List<BlockPopulator> setPopulator(final World world, final List<BlockPopulator> newPop) {
try {
final List<BlockPopulator> pop = world.getPopulators();
final Field populators = world.getClass().getDeclaredField("populators");
populators.setAccessible(true);
populators.set(world, newPop);
return pop;
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
public void setEntitiesAndTiles(final Chunk chunk, final List<?>[] entities, final Map<?, ?> tiles) {
try {
final Class<? extends Chunk> clazz = chunk.getClass();
final Method handle = clazz.getMethod("getHandle");
final Object c = handle.invoke(chunk);
final Class<? extends Object> clazz2 = c.getClass();
if (tiles.size() > 0) {
final Field tef = clazz2.getDeclaredField("tileEntities");
final Map<?, ?> te = (Map<?, ?>) tef.get(c);
final Method put = te.getClass().getMethod("putAll", Map.class);
put.invoke(te, tiles);
}
final Field esf = clazz2.getDeclaredField("entitySlices");
esf.setAccessible(true);
esf.set(c, entities);
} catch (final Exception e) {
e.printStackTrace();
}
}
public Object getProvider(final World world) {
try {
// Provider 1
final Class<? extends World> clazz = world.getClass();
final Field wf = clazz.getDeclaredField("world");
wf.setAccessible(true);
final Object w = wf.get(world);
final Field provider = w.getClass().getSuperclass().getDeclaredField("chunkProvider");
provider.setAccessible(true);
// ChunkProviderServer
final Class<? extends Object> clazz2 = w.getClass();
final Field wpsf = clazz2.getDeclaredField("chunkProviderServer");
// Store old provider server
final Object worldProviderServer = wpsf.get(w);
// Store the old provider
final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider");
return cp.get(worldProviderServer);
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
public Object setProvider(final World world, Object newProvider) {
try {
// Provider 1
final Class<? extends World> clazz = world.getClass();
final Field wf = clazz.getDeclaredField("world");
wf.setAccessible(true);
final Object w = wf.get(world);
// ChunkProviderServer
final Class<? extends Object> clazz2 = w.getClass();
final Field wpsf = clazz2.getDeclaredField("chunkProviderServer");
// Store old provider server
final Object worldProviderServer = wpsf.get(w);
// Store the old provider
final Field cp = worldProviderServer.getClass().getDeclaredField("chunkProvider");
final Object oldProvider = cp.get(worldProviderServer);
// Provider 2
final Class<? extends Object> clazz3 = worldProviderServer.getClass();
final Field provider2 = clazz3.getDeclaredField("chunkProvider");
// If the provider needs to be calculated
if (newProvider == null) {
Method k;
try {
k = clazz2.getDeclaredMethod("k");
} catch (final Throwable e) {
try {
k = clazz2.getDeclaredMethod("j");
} catch (final Throwable e2) {
e2.printStackTrace();
return null;
}
}
k.setAccessible(true);
final Object tempProviderServer = k.invoke(w);
newProvider = cp.get(tempProviderServer);
// Restore old provider
wpsf.set(w, worldProviderServer);
}
// Set provider for provider server
provider2.set(worldProviderServer, newProvider);
// Return the previous provider
return oldProvider;
} catch (final Exception e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -1,6 +1,9 @@
package com.boydti.fawe.object; package com.boydti.fawe.object;
public class PseudoRandom { public class PseudoRandom {
public static PseudoRandom random = new PseudoRandom();
private long state; private long state;
public PseudoRandom() { public PseudoRandom() {