Various
Fixes #62 Fixes #63 Fixes #64 (maybe) Fixes #66 Fixes #61 Fixes #67 Minor cleanup
This commit is contained in:
parent
3b9408d381
commit
06a548e09e
@ -1,50 +0,0 @@
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile 'org.bukkit.craftbukkit:CraftBukkit:1.8.8'
|
||||
compile 'org.bukkit.craftbukkit:CraftBukkit:1.9.2'
|
||||
compile 'net.milkbowl.vault:VaultAPI:1.5'
|
||||
compile 'com.massivecraft:factions:2.8.0'
|
||||
compile 'com.drtshock:factions:1.6.9.5'
|
||||
compile 'com.factionsone:FactionsOne:1.2.2'
|
||||
compile 'me.ryanhamshire:GriefPrevention:11.5.2'
|
||||
compile 'com.massivecraft:mcore:7.0.1'
|
||||
compile 'net.sacredlabyrinth.Phaed:PreciousStones:10.0.4-SNAPSHOT'
|
||||
compile 'net.jzx7:regios:5.9.9'
|
||||
compile 'com.bekvon.bukkit:residence:2.6.6.6'
|
||||
compile 'com.palmergames.bukkit:towny:0.84.0.9'
|
||||
compile 'com.worldcretornica:plotme_core:0.16.3'
|
||||
compile 'junit:junit:4.11'
|
||||
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.7
|
||||
targetCompatibility = 1.7
|
||||
|
||||
processResources {
|
||||
from('src/main/resources') {
|
||||
include 'plugin.yml'
|
||||
expand(
|
||||
name: project.parent.name,
|
||||
version: project.parent.version
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
// We only want the shadow jar produced
|
||||
jar.enabled = false
|
||||
shadowJar {
|
||||
dependencies {
|
||||
include(dependency(':core'))
|
||||
include(dependency('org.mcstats.bukkit:metrics:R7'))
|
||||
}
|
||||
relocate 'org.mcstats', 'com.plotsquared.stats'
|
||||
archiveName = "${parent.name}-${project.name}.jar"
|
||||
destinationDir = file '../target'
|
||||
}
|
||||
shadowJar.doLast {
|
||||
task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar);
|
@ -1,189 +0,0 @@
|
||||
package com.boydti.fawe.bukkit.v0;
|
||||
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.event.Listener;
|
||||
|
||||
/**
|
||||
* The base object for
|
||||
*/
|
||||
public abstract class BukkitQueue_0 extends FaweQueue implements Listener {
|
||||
|
||||
protected World bukkitWorld;
|
||||
|
||||
/**
|
||||
* Map of chunks in the queue
|
||||
*/
|
||||
private ConcurrentHashMap<Long, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
|
||||
private LinkedBlockingDeque<FaweChunk<Chunk>> chunks = new LinkedBlockingDeque<>();
|
||||
|
||||
public BukkitQueue_0(final String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(int x, int z) {
|
||||
if (bukkitWorld == null) {
|
||||
bukkitWorld = Bukkit.getServer().getWorld(world);
|
||||
}
|
||||
return bukkitWorld.isChunkLoaded(x, z);
|
||||
// long id = ((long) x << 32) | (z & 0xFFFFFFFFL);
|
||||
// HashSet<Long> map = this.loaded.get(world);
|
||||
// if (map != null) {
|
||||
// return map.contains(id);
|
||||
// }
|
||||
// return false;
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(int x, int z) {
|
||||
if (bukkitWorld == null) {
|
||||
bukkitWorld = Bukkit.getServer().getWorld(world);
|
||||
}
|
||||
return bukkitWorld.regenerateChunk(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTask(int x, int z, Runnable runnable) {
|
||||
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x, z);
|
||||
result.addTask(runnable);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous == null) {
|
||||
chunks.add(result);
|
||||
return;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
}
|
||||
result.addTask(runnable);
|
||||
}
|
||||
|
||||
private FaweChunk lastChunk;
|
||||
private int lastX = Integer.MIN_VALUE;
|
||||
private int lastZ = Integer.MIN_VALUE;
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, short id, byte data) {
|
||||
if ((y > 255) || (y < 0)) {
|
||||
return false;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
if (cx != lastX || cz != lastZ) {
|
||||
lastX = cx;
|
||||
lastZ = cz;
|
||||
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
|
||||
lastChunk = this.blocks.get(pair);
|
||||
if (lastChunk == null) {
|
||||
lastChunk = this.getChunk(x >> 4, z >> 4);
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, lastChunk);
|
||||
if (previous == null) {
|
||||
chunks.add(lastChunk);
|
||||
return true;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
lastChunk = previous;
|
||||
}
|
||||
}
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int z, BaseBiome biome) {
|
||||
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x >> 4, z >> 4);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous != null) {
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
} else {
|
||||
chunks.add(result);
|
||||
}
|
||||
}
|
||||
result.setBiome(x & 15, z & 15, biome);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> next() {
|
||||
lastX = Integer.MIN_VALUE;
|
||||
lastZ = Integer.MIN_VALUE;
|
||||
try {
|
||||
if (this.blocks.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
synchronized (blocks) {
|
||||
FaweChunk<Chunk> chunk = chunks.poll();
|
||||
if (chunk != null) {
|
||||
blocks.remove(chunk.longHash());
|
||||
this.execute(chunk);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return chunks.size();
|
||||
}
|
||||
|
||||
private LinkedBlockingDeque<FaweChunk<Chunk>> toUpdate = new LinkedBlockingDeque<>();
|
||||
|
||||
public boolean execute(FaweChunk<Chunk> fc) {
|
||||
if (fc == null) {
|
||||
return false;
|
||||
}
|
||||
// Load chunk
|
||||
Chunk chunk = fc.getChunk();
|
||||
chunk.load(true);
|
||||
// Set blocks / entities / biome
|
||||
if (!this.setComponents(fc)) {
|
||||
return false;
|
||||
}
|
||||
fc.executeTasks();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.blocks.clear();
|
||||
this.chunks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(FaweChunk<?> chunk) {
|
||||
FaweChunk<Chunk> previous = this.blocks.put(chunk.longHash(), (FaweChunk<Chunk>) chunk);
|
||||
if (previous != null) {
|
||||
chunks.remove(previous);
|
||||
}
|
||||
chunks.add((FaweChunk<Chunk>) chunk);
|
||||
}
|
||||
|
||||
public abstract Collection<FaweChunk<Chunk>> sendChunk(Collection<FaweChunk<Chunk>> fcs);
|
||||
|
||||
public abstract boolean setComponents(FaweChunk<Chunk> fc);
|
||||
|
||||
@Override
|
||||
public abstract FaweChunk<Chunk> getChunk(int x, int z);
|
||||
|
||||
@Override
|
||||
public abstract boolean fixLighting(FaweChunk<?> fc, boolean fixAll);
|
||||
}
|
@ -1,164 +0,0 @@
|
||||
package com.boydti.fawe.bukkit.v1_8;
|
||||
|
||||
import com.boydti.fawe.bukkit.v0.BukkitEditSessionWrapper_0;
|
||||
import com.boydti.fawe.util.ReflectionUtils.RefClass;
|
||||
import com.boydti.fawe.util.ReflectionUtils.RefField;
|
||||
import com.boydti.fawe.util.ReflectionUtils.RefMethod;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
import org.bukkit.Bukkit;
|
||||
|
||||
|
||||
import static com.boydti.fawe.util.ReflectionUtils.getRefClass;
|
||||
|
||||
public class BukkitEditSessionWrapper_1_8 extends BukkitEditSessionWrapper_0 {
|
||||
|
||||
private final RefClass classCraftWorld = getRefClass("{cb}.CraftWorld");
|
||||
private final RefClass classChunk = getRefClass("{nms}.Chunk");
|
||||
private final RefClass classWorld = getRefClass("{nms}.World");
|
||||
|
||||
private RefMethod worldGetHandle;
|
||||
private RefMethod methodGetChunkAt;
|
||||
private RefField heightMap;
|
||||
private Object nmsWorld;
|
||||
|
||||
private int lastXMin;
|
||||
private int lastZMin;
|
||||
private Object lastChunk;
|
||||
|
||||
public BukkitEditSessionWrapper_1_8(final EditSession session) {
|
||||
super(session);
|
||||
try {
|
||||
this.worldGetHandle = this.classCraftWorld.getMethod("getHandle");
|
||||
this.methodGetChunkAt = this.classWorld.getMethod("getChunkAt", int.class, int.class);
|
||||
this.heightMap = this.classChunk.getField("heightMap");
|
||||
this.nmsWorld = this.worldGetHandle.of(Bukkit.getWorld(session.getWorld().getName())).call();
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getHighestTerrainBlock(final int x, final int z, final int minY, final int maxY, final boolean naturalOnly) {
|
||||
final int bx = x >> 4;
|
||||
final int bz = z >> 4;
|
||||
int[] heights;
|
||||
if ((this.lastChunk == null) || (bx != this.lastXMin) || (bz != this.lastZMin)) {
|
||||
this.lastXMin = bx;
|
||||
this.lastZMin = bz;
|
||||
this.lastChunk = this.methodGetChunkAt.of(this.nmsWorld).call(bx, bz);
|
||||
}
|
||||
if (this.lastChunk != null) {
|
||||
heights = (int[]) this.heightMap.of(this.lastChunk).get();
|
||||
final int lx = x & 15;
|
||||
final int lz = z & 15;
|
||||
final int height = heights[((lz << 4) | lx)];
|
||||
if ((height <= maxY) && (height >= minY)) {
|
||||
final Vector pt = new Vector(x, height, z);
|
||||
final int id = this.session.getBlockType(pt);
|
||||
if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, 0) : !BlockType.canPassThrough(id, 0)) {
|
||||
return height;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int y = maxY; y >= minY; --y) {
|
||||
final Vector pt = new Vector(x, y, z);
|
||||
final int id = this.session.getBlockType(pt);
|
||||
int data;
|
||||
switch (id) {
|
||||
case 0: {
|
||||
continue;
|
||||
}
|
||||
case 2:
|
||||
case 4:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 25:
|
||||
case 30:
|
||||
case 32:
|
||||
case 37:
|
||||
case 39:
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 51:
|
||||
case 52:
|
||||
case 54:
|
||||
case 55:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 61:
|
||||
case 62:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 73:
|
||||
case 74:
|
||||
case 78:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 84:
|
||||
case 85:
|
||||
case 87:
|
||||
case 88:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 110:
|
||||
case 112:
|
||||
case 113:
|
||||
case 117:
|
||||
case 121:
|
||||
case 122:
|
||||
case 123:
|
||||
case 124:
|
||||
case 129:
|
||||
case 133:
|
||||
case 138:
|
||||
case 137:
|
||||
case 140:
|
||||
case 165:
|
||||
case 166:
|
||||
case 169:
|
||||
case 170:
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 176:
|
||||
case 177:
|
||||
case 181:
|
||||
case 182:
|
||||
case 188:
|
||||
case 189:
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
return y;
|
||||
default:
|
||||
data = 0;
|
||||
}
|
||||
if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, data) : !BlockType.canPassThrough(id, data)) {
|
||||
return y;
|
||||
}
|
||||
}
|
||||
return minY;
|
||||
}
|
||||
|
||||
}
|
@ -1,692 +0,0 @@
|
||||
package com.boydti.fawe.bukkit.v1_8;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
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.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import com.sk89q.worldedit.LocalWorld;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.bukkit.BukkitUtil;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
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.entity.Entity;
|
||||
import org.bukkit.entity.Player;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
|
||||
import static com.boydti.fawe.util.ReflectionUtils.getRefClass;
|
||||
|
||||
public class BukkitQueue_1_8 extends BukkitQueue_All {
|
||||
|
||||
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 = this.classChunk.getField("mustSave");
|
||||
private final RefClass classBlockPosition = getRefClass("{nms}.BlockPosition");
|
||||
private final RefClass classChunkSection = getRefClass("{nms}.ChunkSection");
|
||||
|
||||
private RefMethod methodRecalcBlockCounts;
|
||||
private RefMethod methodGetHandlePlayer;
|
||||
private RefMethod methodGetHandleChunk;
|
||||
private RefConstructor MapChunk;
|
||||
private RefField connection;
|
||||
private RefMethod send;
|
||||
private RefMethod methodInitLighting;
|
||||
private RefConstructor classBlockPositionConstructor;
|
||||
private RefConstructor classChunkSectionConstructor;
|
||||
private RefMethod methodX;
|
||||
private RefMethod methodAreNeighborsLoaded;
|
||||
private RefField fieldSections;
|
||||
private RefField fieldWorld;
|
||||
private RefMethod methodGetIdArray;
|
||||
private RefMethod methodGetWorld;
|
||||
private RefField tileEntityListTick;
|
||||
|
||||
public BukkitQueue_1_8(final String world) {
|
||||
super(world);
|
||||
try {
|
||||
this.methodGetHandlePlayer = this.classCraftPlayer.getMethod("getHandle");
|
||||
this.methodGetHandleChunk = this.classCraftChunk.getMethod("getHandle");
|
||||
this.methodInitLighting = this.classChunk.getMethod("initLighting");
|
||||
this.MapChunk = this.classMapChunk.getConstructor(this.classChunk.getRealClass(), boolean.class, int.class);
|
||||
this.connection = this.classEntityPlayer.getField("playerConnection");
|
||||
this.send = this.classConnection.getMethod("sendPacket", this.classPacket.getRealClass());
|
||||
this.classBlockPositionConstructor = this.classBlockPosition.getConstructor(int.class, int.class, int.class);
|
||||
this.methodX = this.classWorld.getMethod("x", this.classBlockPosition.getRealClass());
|
||||
this.fieldSections = this.classChunk.getField("sections");
|
||||
this.fieldWorld = this.classChunk.getField("world");
|
||||
this.methodGetIdArray = this.classChunkSection.getMethod("getIdArray");
|
||||
this.methodAreNeighborsLoaded = this.classChunk.getMethod("areNeighborsLoaded", int.class);
|
||||
this.classChunkSectionConstructor = this.classChunkSection.getConstructor(int.class, boolean.class, char[].class);
|
||||
this.tileEntityListTick = this.classWorld.getField("tileEntityList");
|
||||
this.methodGetWorld = this.classChunk.getMethod("getWorld");
|
||||
this.methodRecalcBlockCounts = this.classChunkSection.getMethod("recalcBlockCounts");
|
||||
} catch (final NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Object getCachedChunk(int cx, int cz) {
|
||||
return methodGetHandleChunk.of(bukkitWorld.getChunkAt(cx, cz)).call();
|
||||
}
|
||||
|
||||
public Object getCachedSection(Object chunk, int cy) {
|
||||
Object storage = ((Object[]) fieldSections.of(chunk).get())[cy];
|
||||
if (storage == null) {
|
||||
return null;
|
||||
}
|
||||
return getIdArray(storage);
|
||||
}
|
||||
|
||||
public int getCombinedId4Data(Object section, int x, int y, int z) {
|
||||
char[] ls = (char[]) section;
|
||||
return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs) {
|
||||
for (final FaweChunk<Chunk> fc : fcs) {
|
||||
sendChunk(fc);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void sendChunk(final FaweChunk<Chunk> fc) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
|
||||
TaskManager.IMP.sync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
}
|
||||
Chunk chunk = fc.getChunk();
|
||||
World world = chunk.getWorld();
|
||||
final int view = Bukkit.getServer().getViewDistance();
|
||||
int cx = chunk.getX();
|
||||
int cz = chunk.getZ();
|
||||
for (final Player player : Bukkit.getOnlinePlayers()) {
|
||||
if (!player.getWorld().equals(world)) {
|
||||
continue;
|
||||
}
|
||||
final Location loc = player.getLocation();
|
||||
final int px = loc.getBlockX() >> 4;
|
||||
final int pz = loc.getBlockZ() >> 4;
|
||||
if ((Math.abs(cx - px) > view) || (Math.abs(cz - pz) > view)) {
|
||||
continue;
|
||||
}
|
||||
final Object entity = methodGetHandlePlayer.of(player).call();
|
||||
final RefExecutor con = send.of(connection.of(entity).get());
|
||||
final Object c = methodGetHandleChunk.of(fc.getChunk()).call();
|
||||
Object packet = MapChunk.create(c, false, 65535);
|
||||
con.call(packet);
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}, Settings.ASYNC_LIGHTING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(final FaweChunk<?> fc, final boolean fixAll) {
|
||||
try {
|
||||
final BukkitChunk_1_8 bc = (BukkitChunk_1_8) fc;
|
||||
final Chunk chunk = bc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
if (Fawe.get().getMainThread() != Thread.currentThread()) {
|
||||
return false;
|
||||
}
|
||||
chunk.load(false);
|
||||
}
|
||||
|
||||
// Initialize lighting
|
||||
final Object c = this.methodGetHandleChunk.of(chunk).call();
|
||||
|
||||
this.methodInitLighting.of(c).call();
|
||||
|
||||
if (((bc.getTotalRelight() == 0) && !fixAll)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Object[] sections = (Object[]) this.fieldSections.of(c).get();
|
||||
final Object w = this.fieldWorld.of(c).get();
|
||||
|
||||
final int X = chunk.getX() << 4;
|
||||
final int Z = chunk.getZ() << 4;
|
||||
|
||||
final RefExecutor relight = this.methodX.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 char[] array = this.getIdArray(section);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
int l = FaweCache.RANDOM.random(2);
|
||||
for (int k = 0; k < array.length; k++) {
|
||||
final int i = array[k];
|
||||
if (i < 16) {
|
||||
continue;
|
||||
}
|
||||
final short id = FaweCache.CACHE_ID[i];
|
||||
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 (this.isSurrounded(sections, x, y, z)) {
|
||||
continue;
|
||||
}
|
||||
final Object pos = this.classBlockPositionConstructor.create(X + x, y, Z + z);
|
||||
relight.call(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (final Throwable e) {
|
||||
if (Thread.currentThread() == Fawe.get().getMainThread()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSurrounded(final Object[] sections, final int x, final int y, final int z) {
|
||||
return this.isSolid(this.getId(sections, x, y + 1, z))
|
||||
&& this.isSolid(this.getId(sections, x + 1, y - 1, z))
|
||||
&& this.isSolid(this.getId(sections, x - 1, y, z))
|
||||
&& this.isSolid(this.getId(sections, x, y, z + 1))
|
||||
&& this.isSolid(this.getId(sections, x, y, z - 1));
|
||||
}
|
||||
|
||||
public boolean isSolid(final int i) {
|
||||
if (i == 0) {
|
||||
return false;
|
||||
}
|
||||
return Material.getMaterial(i).isOccluding();
|
||||
}
|
||||
|
||||
public int getId(final Object[] sections, final int x, final int y, final int z) {
|
||||
if ((x < 0) || (x > 15) || (z < 0) || (z > 15)) {
|
||||
return 1;
|
||||
}
|
||||
if ((y < 0) || (y > 255)) {
|
||||
return 1;
|
||||
}
|
||||
final int i = FaweCache.CACHE_I[y][x][z];
|
||||
final Object section = sections[i];
|
||||
if (section == null) {
|
||||
return 0;
|
||||
}
|
||||
final char[] array = this.getIdArray(section);
|
||||
final int j = FaweCache.CACHE_J[y][x][z];
|
||||
return array[j] >> 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponents(final FaweChunk<Chunk> fc) {
|
||||
try {
|
||||
final BukkitChunk_1_8 fs = ((BukkitChunk_1_8) fc);
|
||||
final Chunk chunk = fs.getChunk();
|
||||
final World world = chunk.getWorld();
|
||||
|
||||
final boolean flag = world.getEnvironment() == Environment.NORMAL;
|
||||
|
||||
// Sections
|
||||
final Method getHandele = chunk.getClass().getDeclaredMethod("getHandle");
|
||||
final Object c = getHandele.invoke(chunk);
|
||||
final Object w = this.methodGetWorld.of(c).call();
|
||||
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 Collection<?>[] entities = (Collection<?>[]) ef.get(c);
|
||||
|
||||
Method xm = null;
|
||||
Method ym = null;
|
||||
Method zm = null;
|
||||
|
||||
// Trim tiles
|
||||
boolean removed = false;
|
||||
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 char[] array = fs.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
if (array[k] != 0) {
|
||||
removed = true;
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
if (removed) {
|
||||
((Collection) this.tileEntityListTick.of(w).get()).clear();
|
||||
}
|
||||
|
||||
// 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 char[] newArray = fs.getIdArray(j);
|
||||
if (newArray == null) {
|
||||
continue;
|
||||
}
|
||||
Object section = sections[j];
|
||||
if ((section == null) || (fs.getCount(j) >= 4096)) {
|
||||
section = sections[j] = this.newChunkSection(j << 4, flag, newArray);
|
||||
continue;
|
||||
}
|
||||
final char[] currentArray = this.getIdArray(section);
|
||||
boolean fill = true;
|
||||
for (int k = 0; k < newArray.length; k++) {
|
||||
final char n = newArray[k];
|
||||
if (n == 0) {
|
||||
fill = false;
|
||||
continue;
|
||||
}
|
||||
switch (n) {
|
||||
case 0:
|
||||
fill = false;
|
||||
continue;
|
||||
case 1:
|
||||
fill = false;
|
||||
currentArray[k] = 0;
|
||||
continue;
|
||||
default:
|
||||
currentArray[k] = n;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (fill) {
|
||||
fs.setCount(j, Short.MAX_VALUE);
|
||||
}
|
||||
methodRecalcBlockCounts.of(section).call();
|
||||
}
|
||||
|
||||
// Biomes
|
||||
final int[][] biomes = fs.getBiomeArray();
|
||||
if (biomes != null) {
|
||||
final LocalWorld lw = BukkitUtil.getLocalWorld(world);
|
||||
final int X = fs.getX() << 4;
|
||||
final int Z = fs.getZ() << 4;
|
||||
final BaseBiome bb = new BaseBiome(0);
|
||||
int last = 0;
|
||||
for (int x = 0; x < 16; x++) {
|
||||
final int[] array = biomes[x];
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
for (int z = 0; z < 16; z++) {
|
||||
final int biome = array[z];
|
||||
if (biome == 0) {
|
||||
continue;
|
||||
}
|
||||
if (last != biome) {
|
||||
last = biome;
|
||||
bb.setId(biome);
|
||||
}
|
||||
lw.setBiome(new Vector2D(X + x, Z + z), bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
TaskManager.IMP.later(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sendChunk(fs);
|
||||
}
|
||||
}, 1);
|
||||
return true;
|
||||
} catch (final Exception e) {
|
||||
if (Thread.currentThread() == Fawe.get().getMainThread()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the server is < 1% available memory (i.e. likely to crash)<br>
|
||||
* - You can disable this in the conifg<br>
|
||||
* - Will try to free up some memory<br>
|
||||
* - Clears the queue<br>
|
||||
* - Clears worldedit history<br>
|
||||
* - Clears entities<br>
|
||||
* - Unloads chunks in vacant worlds<br>
|
||||
* - Unloads non visible chunks<br>
|
||||
*/
|
||||
@Override
|
||||
public void saveMemory() {
|
||||
super.saveMemory();
|
||||
// Clear the queue
|
||||
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
|
||||
final FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
final 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()) {
|
||||
this.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) {
|
||||
this.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;
|
||||
}
|
||||
|
||||
public Object newChunkSection(final int i, final boolean flag, final char[] ids) {
|
||||
return this.classChunkSectionConstructor.create(i, flag, ids);
|
||||
}
|
||||
|
||||
public char[] getIdArray(final Object obj) {
|
||||
return (char[]) this.methodGetIdArray.of(obj).call();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getChunk(int x, int z) {
|
||||
return new BukkitChunk_1_8(this, x, z);
|
||||
}
|
||||
|
||||
public boolean unloadChunk(final String world, final Chunk chunk) {
|
||||
final Object c = this.methodGetHandleChunk.of(chunk).call();
|
||||
this.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;
|
||||
}
|
||||
}
|
@ -1,658 +0,0 @@
|
||||
package com.boydti.fawe.bukkit.v1_9;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
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.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
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.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 static com.boydti.fawe.util.ReflectionUtils.getRefClass;
|
||||
|
||||
public class BukkitQueue_1_9 extends BukkitQueue_All {
|
||||
|
||||
private final RefClass classMapChunk = getRefClass("{nms}.PacketPlayOutMapChunk");
|
||||
private final RefClass classChunk = getRefClass("{nms}.Chunk");
|
||||
private final RefClass classCraftChunk = getRefClass("{cb}.CraftChunk");
|
||||
private final RefClass classWorld = getRefClass("{nms}.World");
|
||||
private final RefField mustSave = this.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 RefMethod methodInitLighting;
|
||||
private final RefConstructor classBlockPositionConstructor;
|
||||
private final RefConstructor classChunkSectionConstructor;
|
||||
private final RefMethod methodW;
|
||||
private final RefField fieldSections;
|
||||
private final RefField fieldWorld;
|
||||
private final RefMethod methodGetBlocks;
|
||||
private final RefMethod methodSetType;
|
||||
private final RefMethod methodGetType;
|
||||
private final RefMethod methodGetByCombinedId;
|
||||
private final RefMethod methodGetCombinedId;
|
||||
private final Object air;
|
||||
private final RefMethod methodGetWorld;
|
||||
private final RefField tileEntityListTick;
|
||||
|
||||
public BukkitQueue_1_9(final String world) throws NoSuchMethodException, RuntimeException {
|
||||
super(world);
|
||||
this.methodGetHandleChunk = this.classCraftChunk.getMethod("getHandle");
|
||||
this.methodInitLighting = this.classChunk.getMethod("initLighting");
|
||||
this.classBlockPositionConstructor = this.classBlockPosition.getConstructor(int.class, int.class, int.class);
|
||||
this.methodW = this.classWorld.getMethod("w", this.classBlockPosition.getRealClass());
|
||||
this.fieldSections = this.classChunk.getField("sections");
|
||||
this.fieldWorld = this.classChunk.getField("world");
|
||||
this.methodGetByCombinedId = this.classBlock.getMethod("getByCombinedId", int.class);
|
||||
this.methodGetBlocks = this.classChunkSection.getMethod("getBlocks");
|
||||
this.methodSetType = this.classChunkSection.getMethod("setType", int.class, int.class, int.class, this.classIBlockData.getRealClass());
|
||||
this.methodGetType = this.classChunk.getMethod("a", int.class, int.class, int.class);
|
||||
this.classChunkSectionConstructor = this.classChunkSection.getConstructor(int.class, boolean.class, char[].class);
|
||||
this.air = this.methodGetByCombinedId.call(0);
|
||||
this.tileEntityListTick = this.classWorld.getField("tileEntityListTick");
|
||||
this.methodGetWorld = this.classChunk.getMethod("getWorld");
|
||||
this.methodGetCombinedId = classBlock.getMethod("getCombinedId", classIBlockData.getRealClass());
|
||||
}
|
||||
|
||||
public Object getCachedChunk(int cx, int cz) {
|
||||
return methodGetType.of(methodGetHandleChunk.of(bukkitWorld.getChunkAt(cx, cz)).call());
|
||||
}
|
||||
|
||||
public Object getCachedSection(Object chunk, int cy) {
|
||||
return chunk;
|
||||
}
|
||||
|
||||
public int getCombinedId4Data(Object section, int x, int y, int z) {
|
||||
int combined = (int) methodGetCombinedId.call(((RefExecutor) section).call(x & 15, y, z & 15));
|
||||
return ((combined & 4095) << 4) + (combined >> 12);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs) {
|
||||
for (final FaweChunk<Chunk> fc : fcs) {
|
||||
sendChunk(fc);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void sendChunk(final FaweChunk<Chunk> fc) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
|
||||
TaskManager.IMP.sync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
}
|
||||
final Chunk chunk = fc.getChunk();
|
||||
chunk.getWorld().refreshChunk(fc.getX(), fc.getZ());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}, Settings.ASYNC_LIGHTING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(final FaweChunk<?> pc, final boolean fixAll) {
|
||||
try {
|
||||
final BukkitChunk_1_9 bc = (BukkitChunk_1_9) pc;
|
||||
final Chunk chunk = bc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
if (Fawe.get().getMainThread() != Thread.currentThread()) {
|
||||
return false;
|
||||
}
|
||||
chunk.load(false);
|
||||
}
|
||||
// Initialize lighting
|
||||
final Object c = this.methodGetHandleChunk.of(chunk).call();
|
||||
|
||||
this.methodInitLighting.of(c).call();
|
||||
|
||||
if (((bc.getTotalRelight() == 0) && !fixAll)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
final Object[] sections = (Object[]) this.fieldSections.of(c).get();
|
||||
final Object w = this.fieldWorld.of(c).get();
|
||||
|
||||
final int X = chunk.getX() << 4;
|
||||
final int Z = chunk.getZ() << 4;
|
||||
|
||||
final RefExecutor relight = this.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);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
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 & 0xFFF);
|
||||
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 (this.isSurrounded(bc.getIdArrays(), x, y, z)) {
|
||||
continue;
|
||||
}
|
||||
final Object pos = this.classBlockPositionConstructor.create(X + x, y, Z + z);
|
||||
relight.call(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (final Throwable e) {
|
||||
if (Thread.currentThread() == Fawe.get().getMainThread()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSurrounded(final int[][] sections, final int x, final int y, final int z) {
|
||||
return this.isSolid(this.getId(sections, x, y + 1, z))
|
||||
&& this.isSolid(this.getId(sections, x + 1, y - 1, z))
|
||||
&& this.isSolid(this.getId(sections, x - 1, y, z))
|
||||
&& this.isSolid(this.getId(sections, x, y, z + 1))
|
||||
&& this.isSolid(this.getId(sections, x, y, z - 1));
|
||||
}
|
||||
|
||||
public boolean isSolid(final int i) {
|
||||
if (i != 0) {
|
||||
final Material material = Material.getMaterial(i);
|
||||
return (material != null) && Material.getMaterial(i).isOccluding();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getId(final int[][] sections, final int x, final int y, final int z) {
|
||||
if ((x < 0) || (x > 15) || (z < 0) || (z > 15)) {
|
||||
return 1;
|
||||
}
|
||||
if ((y < 0) || (y > 255)) {
|
||||
return 1;
|
||||
}
|
||||
final int i = FaweCache.CACHE_I[y][x][z];
|
||||
final int[] section = sections[i];
|
||||
if (section == null) {
|
||||
return 0;
|
||||
}
|
||||
final int j = FaweCache.CACHE_J[y][x][z];
|
||||
return section[j];
|
||||
}
|
||||
|
||||
public Object getBlocks(final Object obj) {
|
||||
return this.methodGetBlocks.of(obj).call();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponents(final FaweChunk<Chunk> pc) {
|
||||
final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc;
|
||||
final Chunk chunk = pc.getChunk();
|
||||
final World world = chunk.getWorld();
|
||||
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 Object w = this.methodGetWorld.of(c).call();
|
||||
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 Collection<?>[] entities = (Collection<?>[]) ef.get(c);
|
||||
|
||||
Method xm = null;
|
||||
Method ym = null;
|
||||
Method zm = null;
|
||||
|
||||
// Trim tiles
|
||||
boolean removed = false;
|
||||
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) {
|
||||
removed = true;
|
||||
iter.remove();
|
||||
}
|
||||
}
|
||||
if (removed) {
|
||||
((Collection) this.tileEntityListTick.of(w).get()).clear();
|
||||
}
|
||||
|
||||
// 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)) {
|
||||
final char[] array = new char[4096];
|
||||
for (int i = 0; i < newArray.length; i++) {
|
||||
final int combined = newArray[i];
|
||||
final int id = combined & 4095;
|
||||
final int data = combined >> 12;
|
||||
array[i] = (char) ((id << 4) + data);
|
||||
}
|
||||
section = sections[j] = this.newChunkSection(j << 4, flag, array);
|
||||
continue;
|
||||
}
|
||||
this.getBlocks(section);
|
||||
final RefExecutor setType = this.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;
|
||||
final int x = FaweCache.CACHE_X[j][k];
|
||||
final int y = FaweCache.CACHE_Y[j][k];
|
||||
final int z = FaweCache.CACHE_Z[j][k];
|
||||
setType.call(x, y & 15, z, this.air);
|
||||
continue;
|
||||
}
|
||||
default: {
|
||||
final int x = FaweCache.CACHE_X[j][k];
|
||||
final int y = FaweCache.CACHE_Y[j][k];
|
||||
final int z = FaweCache.CACHE_Z[j][k];
|
||||
final Object iblock = this.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();
|
||||
}
|
||||
final int[][] biomes = fs.biomes;
|
||||
final Biome[] values = Biome.values();
|
||||
if (biomes != null) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
final int[] array = biomes[x];
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
for (int z = 0; z < 16; z++) {
|
||||
final int biome = array[z];
|
||||
if (biome == 0) {
|
||||
continue;
|
||||
}
|
||||
chunk.getBlock(x, 0, z).setBiome(values[biome]);
|
||||
}
|
||||
}
|
||||
}
|
||||
TaskManager.IMP.later(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
sendChunk(fs);
|
||||
}
|
||||
}, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the server is < 1% available memory (i.e. likely to crash)<br>
|
||||
* - You can disable this in the conifg<br>
|
||||
* - Will try to free up some memory<br>
|
||||
* - Clears the queue<br>
|
||||
* - Clears worldedit history<br>
|
||||
* - Clears entities<br>
|
||||
* - Unloads chunks in vacant worlds<br>
|
||||
* - Unloads non visible chunks<br>
|
||||
*/
|
||||
@Override
|
||||
public void saveMemory() {
|
||||
super.saveMemory();
|
||||
// Clear the queue
|
||||
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
|
||||
final FawePlayer<Object> fp = FawePlayer.wrap(player);
|
||||
final 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()) {
|
||||
this.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) {
|
||||
this.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;
|
||||
}
|
||||
|
||||
public Object newChunkSection(final int i, final boolean flag, final char[] ids) {
|
||||
return this.classChunkSectionConstructor.create(i, flag, ids);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getChunk(int x, int z) {
|
||||
return new BukkitChunk_1_9(this, x, z);
|
||||
}
|
||||
|
||||
public boolean unloadChunk(final String world, final Chunk chunk) {
|
||||
final Object c = this.methodGetHandleChunk.of(chunk).call();
|
||||
this.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;
|
||||
}
|
||||
}
|
25
bukkit0/build.gradle
Normal file
25
bukkit0/build.gradle
Normal file
@ -0,0 +1,25 @@
|
||||
dependencies {
|
||||
compile project(':core')
|
||||
compile 'net.milkbowl.vault:VaultAPI:1.5'
|
||||
compile 'com.massivecraft:factions:2.8.0'
|
||||
compile 'com.drtshock:factions:1.6.9.5'
|
||||
compile 'com.factionsone:FactionsOne:1.2.2'
|
||||
compile 'me.ryanhamshire:GriefPrevention:11.5.2'
|
||||
compile 'com.massivecraft:mcore:7.0.1'
|
||||
compile 'net.sacredlabyrinth.Phaed:PreciousStones:10.0.4-SNAPSHOT'
|
||||
compile 'net.jzx7:regios:5.9.9'
|
||||
compile 'com.bekvon.bukkit:residence:2.6.6.6'
|
||||
compile 'com.palmergames.bukkit:towny:0.84.0.9'
|
||||
compile 'com.worldcretornica:plotme_core:0.16.3'
|
||||
compile 'junit:junit:4.11'
|
||||
}
|
||||
|
||||
processResources {
|
||||
from('src/main/resources') {
|
||||
include 'plugin.yml'
|
||||
expand(
|
||||
name: project.parent.name,
|
||||
version: project.parent.version
|
||||
)
|
||||
}
|
||||
}
|
BIN
bukkit0/build/libs/bukkit-all.jar
Normal file
BIN
bukkit0/build/libs/bukkit-all.jar
Normal file
Binary file not shown.
1
bukkit0/build/libs/bukkit-all.jar.MD5
Normal file
1
bukkit0/build/libs/bukkit-all.jar.MD5
Normal file
@ -0,0 +1 @@
|
||||
b88df720766580832fc345218f204c5f
|
BIN
bukkit0/build/libs/bukkit.jar
Normal file
BIN
bukkit0/build/libs/bukkit.jar
Normal file
Binary file not shown.
BIN
bukkit0/build/libs/bukkit0.jar
Normal file
BIN
bukkit0/build/libs/bukkit0.jar
Normal file
Binary file not shown.
2
bukkit0/build/tmp/shadowJar/MANIFEST.MF
Normal file
2
bukkit0/build/tmp/shadowJar/MANIFEST.MF
Normal file
@ -0,0 +1,2 @@
|
||||
Manifest-Version: 1.0
|
||||
|
18
bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java
Normal file
18
bukkit0/src/main/java/com/boydti/fawe/bukkit/BukkitMain.java
Normal file
@ -0,0 +1,18 @@
|
||||
package com.boydti.fawe.bukkit;
|
||||
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public abstract class BukkitMain extends JavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
new FaweBukkit(this);
|
||||
}
|
||||
|
||||
public abstract FaweQueue getQueue(String world);
|
||||
|
||||
public abstract EditSessionWrapper getEditSessionWrapper(EditSession session);
|
||||
}
|
@ -37,14 +37,14 @@ public class BukkitPlayer extends FawePlayer<Player> {
|
||||
* - The `/wea` command will give/remove the required bypass permission
|
||||
*/
|
||||
if (Fawe.<FaweBukkit> imp().getVault() == null || Fawe.<FaweBukkit> imp().getVault().permission == null) {
|
||||
this.parent.addAttachment(Fawe.<FaweBukkit> imp()).setPermission("fawe.bypass", flag);
|
||||
this.parent.addAttachment(Fawe.<FaweBukkit> imp().getPlugin()).setPermission("fawe.bypass", flag);
|
||||
} else if (flag) {
|
||||
if (!Fawe.<FaweBukkit> imp().getVault().permission.playerAdd(this.parent, perm)) {
|
||||
this.parent.addAttachment(Fawe.<FaweBukkit> imp()).setPermission("fawe.bypass", flag);
|
||||
this.parent.addAttachment(Fawe.<FaweBukkit> imp().getPlugin()).setPermission("fawe.bypass", flag);
|
||||
}
|
||||
} else {
|
||||
if (!Fawe.<FaweBukkit> imp().getVault().permission.playerRemove(this.parent, perm)) {
|
||||
this.parent.addAttachment(Fawe.<FaweBukkit> imp()).setPermission("fawe.bypass", flag);
|
||||
this.parent.addAttachment(Fawe.<FaweBukkit> imp().getPlugin()).setPermission("fawe.bypass", flag);
|
||||
}
|
||||
}
|
||||
}
|
@ -13,10 +13,7 @@ import com.boydti.fawe.bukkit.regions.ResidenceFeature;
|
||||
import com.boydti.fawe.bukkit.regions.TownyFeature;
|
||||
import com.boydti.fawe.bukkit.regions.Worldguard;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
|
||||
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_9.BukkitQueue_1_9;
|
||||
import com.boydti.fawe.bukkit.v1_9.BukkitQueue_1_9_R1;
|
||||
import com.boydti.fawe.bukkit.v0.ChunkListener;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
@ -43,10 +40,10 @@ import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.player.PlayerChangedWorldEvent;
|
||||
import org.bukkit.event.player.PlayerQuitEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.bukkit.plugin.java.JavaPlugin;
|
||||
|
||||
public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
public class FaweBukkit implements IFawe, Listener {
|
||||
|
||||
private final BukkitMain plugin;
|
||||
private VaultUtil vault;
|
||||
private WorldEditPlugin worldedit;
|
||||
|
||||
@ -61,10 +58,10 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
return this.worldedit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onEnable() {
|
||||
public FaweBukkit(BukkitMain plugin) {
|
||||
this.plugin = plugin;
|
||||
try {
|
||||
Bukkit.getPluginManager().registerEvents(this, this);
|
||||
Bukkit.getPluginManager().registerEvents(this, plugin);
|
||||
Fawe.set(this);
|
||||
if (Bukkit.getVersion().contains("git-Spigot") && FaweAPI.checkVersion(this.getVersion(), 1, 7, 10)) {
|
||||
debug("====== USE PAPER SPIGOT ======");
|
||||
@ -76,23 +73,29 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
|
||||
} catch (final Throwable e) {
|
||||
e.printStackTrace();
|
||||
this.getServer().shutdown();
|
||||
Bukkit.getServer().shutdown();
|
||||
}
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
new ChunkListener();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void debug(final String s) {
|
||||
this.getLogger().info(ChatColor.translateAlternateColorCodes('&', s));
|
||||
Bukkit.getLogger().info(ChatColor.translateAlternateColorCodes('&', s));
|
||||
}
|
||||
|
||||
@Override
|
||||
public File getDirectory() {
|
||||
return this.getDataFolder();
|
||||
return plugin.getDataFolder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setupCommand(final String label, final FaweCommand cmd) {
|
||||
this.getCommand(label).setExecutor(new BukkitCommand(cmd));
|
||||
plugin.getCommand(label).setExecutor(new BukkitCommand(cmd));
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -115,7 +118,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
|
||||
@Override
|
||||
public void startMetrics() {
|
||||
Metrics metrics = new Metrics(this);
|
||||
Metrics metrics = new Metrics(plugin);
|
||||
metrics.start();
|
||||
debug("&6Metrics enabled.");
|
||||
}
|
||||
@ -131,7 +134,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
*/
|
||||
@Override
|
||||
public void setupWEListener() {
|
||||
this.getServer().getPluginManager().registerEvents(new WEListener(), this);
|
||||
Bukkit.getServer().getPluginManager().registerEvents(new WEListener(), plugin);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -152,7 +155,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
*/
|
||||
@Override
|
||||
public TaskManager getTaskManager() {
|
||||
return new BukkitTaskMan(this);
|
||||
return new BukkitTaskMan(plugin);
|
||||
}
|
||||
|
||||
private int[] version;
|
||||
@ -188,7 +191,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
* - When a block change is requested, the SetQueue will first check if the chunk exists in the queue, or it will create and add it<br>
|
||||
*/
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world) {
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
try {
|
||||
Field fieldDirtyCount = ReflectionUtils.getRefClass("{nms}.PlayerChunk").getField("dirtyCount").getRealField();
|
||||
fieldDirtyCount.setAccessible(true);
|
||||
@ -200,19 +203,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
}
|
||||
} catch (Throwable ignore) {}
|
||||
try {
|
||||
if (FaweAPI.checkVersion(this.getVersion(), 1, 9, 0)) {
|
||||
try {
|
||||
return new BukkitQueue_1_9_R1(world);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
try {
|
||||
return new BukkitQueue_1_9(world);
|
||||
} catch (final Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return new BukkitQueue_1_8(world);
|
||||
return plugin.getQueue(world);
|
||||
} catch (Throwable ignore) {}
|
||||
if (hasNMS) {
|
||||
debug("====== NO NMS BLOCK PLACER FOUND ======");
|
||||
@ -226,6 +217,10 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
return new BukkitQueue_All(world);
|
||||
}
|
||||
|
||||
public BukkitMain getPlugin() {
|
||||
return plugin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWorldName(World world) {
|
||||
return world.getName();
|
||||
@ -236,7 +231,7 @@ public class FaweBukkit extends JavaPlugin implements IFawe, Listener {
|
||||
*/
|
||||
@Override
|
||||
public EditSessionWrapper getEditSessionWrapper(final EditSession session) {
|
||||
return new BukkitEditSessionWrapper_1_8(session);
|
||||
return plugin.getEditSessionWrapper(session);
|
||||
}
|
||||
|
||||
/**
|
@ -95,8 +95,6 @@ public class LoggingExtent extends AbstractDelegateExtent {
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 61:
|
||||
case 62:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
@ -1,14 +1,9 @@
|
||||
package com.boydti.fawe.bukkit.v0;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.bukkit.v1_8.BukkitChunk_1_8;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.LocalWorld;
|
||||
import com.sk89q.worldedit.Vector2D;
|
||||
import com.sk89q.worldedit.bukkit.BukkitUtil;
|
||||
@ -16,52 +11,53 @@ import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
import org.bukkit.event.entity.ItemSpawnEvent;
|
||||
import org.bukkit.plugin.Plugin;
|
||||
import org.spigotmc.AsyncCatcher;
|
||||
|
||||
public class BukkitQueue_All extends BukkitQueue_0 {
|
||||
public abstract class BukkitQueue_0<CHUNK, CHUNKSECTIONS, SECTION> extends NMSMappedFaweQueue<World, CHUNK, CHUNKSECTIONS, SECTION> {
|
||||
|
||||
public BukkitQueue_All(final String world) {
|
||||
public BukkitQueue_0(final String world) {
|
||||
super(world);
|
||||
if (getClass() == BukkitQueue_All.class) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
Bukkit.getPluginManager().registerEvents(BukkitQueue_All.this, (Plugin) Fawe.imp());
|
||||
}
|
||||
});
|
||||
}
|
||||
public World getWorld(String world) {
|
||||
return Bukkit.getWorld(world);
|
||||
}
|
||||
|
||||
|
||||
private boolean physicsFreeze = false;
|
||||
|
||||
@EventHandler
|
||||
public void onPhysics(BlockPhysicsEvent event) {
|
||||
if (physicsFreeze) {
|
||||
event.setCancelled(true);
|
||||
}
|
||||
@Override
|
||||
public boolean isChunkLoaded(World world, int x, int z) {
|
||||
return world.isChunkLoaded(x, z);
|
||||
}
|
||||
|
||||
@EventHandler
|
||||
public void onItemSpawn(ItemSpawnEvent event) {
|
||||
if (physicsFreeze) {
|
||||
event.setCancelled(true);
|
||||
@Override
|
||||
public void refreshChunk(World world, CHUNK chunk) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(World world, int x, int z) {
|
||||
return world.regenerateChunk(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(FaweChunk fc, boolean fixAll) {
|
||||
// Not implemented
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadChunk(World impWorld, int x, int z, boolean generate) {
|
||||
return impWorld.loadChunk(x, z, generate);
|
||||
}
|
||||
|
||||
private volatile boolean timingsEnabled;
|
||||
|
||||
@Override
|
||||
public void startSet(boolean parallel) {
|
||||
ChunkListener.physicsFreeze = true;
|
||||
if (parallel) {
|
||||
try {
|
||||
Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");
|
||||
@ -80,6 +76,7 @@ public class BukkitQueue_All extends BukkitQueue_0 {
|
||||
|
||||
@Override
|
||||
public void endSet(boolean parallel) {
|
||||
ChunkListener.physicsFreeze = false;
|
||||
if (parallel) {
|
||||
try {Field fieldEnabled = Class.forName("co.aikar.timings.Timings").getDeclaredField("timingsEnabled");fieldEnabled.setAccessible(true);fieldEnabled.set(null, timingsEnabled);
|
||||
} catch (Throwable ignore) {ignore.printStackTrace();}
|
||||
@ -88,15 +85,9 @@ public class BukkitQueue_All extends BukkitQueue_0 {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweChunk<Chunk>> sendChunk(Collection<FaweChunk<Chunk>> fcs) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponents(FaweChunk<Chunk> fc) {
|
||||
public boolean setComponents(FaweChunk fc) {
|
||||
try {
|
||||
startSet();
|
||||
final BukkitChunk_1_8 fs = ((BukkitChunk_1_8) fc);
|
||||
final CharFaweChunk<Chunk> fs = ((CharFaweChunk<Chunk>) fc);
|
||||
final Chunk chunk = fs.getChunk();
|
||||
chunk.load(true);
|
||||
final World world = chunk.getWorld();
|
||||
@ -191,115 +182,20 @@ public class BukkitQueue_All extends BukkitQueue_0 {
|
||||
}
|
||||
}
|
||||
}
|
||||
endSet();
|
||||
return true;
|
||||
} catch (final Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
endSet();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void startSet() {
|
||||
physicsFreeze = true;
|
||||
try {
|
||||
// Need to temporarily disable the async catcher since it can't discern safe/unsafe async calls
|
||||
// The main thread will be locked until it is enabled again (if anything fails it will be enabled again)
|
||||
AsyncCatcher.enabled = false;
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
|
||||
public void endSet() {
|
||||
physicsFreeze = false;
|
||||
try {
|
||||
AsyncCatcher.enabled = true;
|
||||
} catch (Throwable ignore) {}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getChunk(int x, int z) {
|
||||
return new BukkitChunk_1_8(this, x, z);
|
||||
}
|
||||
|
||||
public FaweChunk getChunk(final int x, final int z) {
|
||||
return new CharFaweChunk<Chunk>(this, x, z) {
|
||||
@Override
|
||||
public boolean fixLighting(FaweChunk<?> fc, boolean fixAll) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int lastChunkX = Integer.MIN_VALUE;
|
||||
public int lastChunkZ = Integer.MIN_VALUE;
|
||||
public int lastChunkY = Integer.MIN_VALUE;
|
||||
|
||||
private Object lastChunk;
|
||||
private Object lastSection;
|
||||
|
||||
public Object getCachedChunk(int cx, int cz) {
|
||||
return bukkitWorld.getChunkAt(cx, cz);
|
||||
}
|
||||
|
||||
public Object getCachedSection(Object chunk, int cy) {
|
||||
return lastChunk;
|
||||
}
|
||||
|
||||
public int getCombinedId4Data(Object section, int x, int y, int z) {
|
||||
Block block = ((Chunk) lastChunk).getBlock(x & 15, y, z & 15);
|
||||
int combined = block.getTypeId() << 4;
|
||||
if (FaweCache.hasData(combined)) {
|
||||
combined += block.getData();
|
||||
}
|
||||
return combined;
|
||||
}
|
||||
|
||||
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||
@Override
|
||||
public void run(IntegerPair coord) {
|
||||
bukkitWorld.loadChunk(coord.x, coord.z, true);
|
||||
public Chunk getNewChunk() {
|
||||
return getWorld().getChunkAt(x, z);
|
||||
}
|
||||
};
|
||||
|
||||
long average = 0;
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
||||
if (y < 0 || y > 255) {
|
||||
return 0;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
int cy = y >> 4;
|
||||
if (cx != lastChunkX || cz != lastChunkZ) {
|
||||
if (bukkitWorld == null) {
|
||||
bukkitWorld = Bukkit.getServer().getWorld(world);
|
||||
}
|
||||
lastChunkX = cx;
|
||||
lastChunkZ = cz;
|
||||
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
|
||||
long start = System.currentTimeMillis();
|
||||
boolean sync = Thread.currentThread() == Fawe.get().getMainThread();
|
||||
if (sync) {
|
||||
bukkitWorld.loadChunk(cx, cz, true);
|
||||
} else if (Settings.CHUNK_WAIT > 0) {
|
||||
loadChunk.value = new IntegerPair(cx, cz);
|
||||
TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT);
|
||||
if (!bukkitWorld.isChunkLoaded(cx, cz)) {
|
||||
throw new FaweException.FaweChunkLoadException();
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
lastChunk = getCachedChunk(cx, cz);
|
||||
lastSection = getCachedSection(lastChunk, cy);
|
||||
} else if (cy != lastChunkY) {
|
||||
if (lastChunk == null) {
|
||||
return 0;
|
||||
}
|
||||
lastSection = getCachedSection(lastChunk, cy);
|
||||
}
|
||||
|
||||
if (lastSection == null) {
|
||||
return 0;
|
||||
}
|
||||
return getCombinedId4Data(lastSection, x, y, z);
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package com.boydti.fawe.bukkit.v0;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.block.Block;
|
||||
|
||||
public class BukkitQueue_All extends BukkitQueue_0<Chunk, Chunk, Chunk> {
|
||||
public BukkitQueue_All(String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
public int getCombinedId4Data(Chunk section, int x, int y, int z) {
|
||||
Block block = ((Chunk) section).getBlock(x & 15, y, z & 15);
|
||||
int combined = block.getTypeId() << 4;
|
||||
if (FaweCache.hasData(combined)) {
|
||||
combined += block.getData();
|
||||
}
|
||||
return combined;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getCachedChunk(World impWorld, int cx, int cz) {
|
||||
return impWorld.getChunkAt(cx, cz);
|
||||
}
|
||||
}
|
@ -0,0 +1,48 @@
|
||||
package com.boydti.fawe.bukkit.v0;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.bukkit.FaweBukkit;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.event.EventHandler;
|
||||
import org.bukkit.event.EventPriority;
|
||||
import org.bukkit.event.Listener;
|
||||
import org.bukkit.event.block.BlockPhysicsEvent;
|
||||
import org.bukkit.event.entity.ItemSpawnEvent;
|
||||
|
||||
public class ChunkListener implements Listener {
|
||||
public ChunkListener() {
|
||||
Bukkit.getPluginManager().registerEvents(ChunkListener.this, Fawe.<FaweBukkit>imp().getPlugin());
|
||||
TaskManager.IMP.repeat(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
physicsFreeze = false;
|
||||
physicsLimit = Settings.PHYSICS_PER_TICK;
|
||||
itemLimit = Settings.ITEMS_PER_TICK;
|
||||
}
|
||||
}, 1);
|
||||
}
|
||||
|
||||
private int physicsLimit = Settings.PHYSICS_PER_TICK;
|
||||
private int itemLimit = Settings.ITEMS_PER_TICK;
|
||||
public static boolean physicsFreeze = false;
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onPhysics(BlockPhysicsEvent event) {
|
||||
if (physicsFreeze) {
|
||||
event.setCancelled(true);
|
||||
} else if (--physicsLimit < 0) {
|
||||
physicsFreeze = true;
|
||||
}
|
||||
}
|
||||
|
||||
@EventHandler(priority = EventPriority.LOWEST)
|
||||
public void onItemSpawn(ItemSpawnEvent event) {
|
||||
if (physicsFreeze) {
|
||||
event.setCancelled(true);
|
||||
} else if (--itemLimit < 0) {
|
||||
physicsFreeze = true;
|
||||
}
|
||||
}
|
||||
}
|
21
bukkit18/build.gradle
Normal file
21
bukkit18/build.gradle
Normal file
@ -0,0 +1,21 @@
|
||||
dependencies {
|
||||
compile project(':bukkit0')
|
||||
compile 'org.bukkit.craftbukkit:CraftBukkit:1.8.8'
|
||||
}
|
||||
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
// We only want the shadow jar produced
|
||||
jar.enabled = false
|
||||
shadowJar {
|
||||
dependencies {
|
||||
include(dependency(':bukkit0'))
|
||||
}
|
||||
archiveName = "${parent.name}-${project.name}.jar"
|
||||
destinationDir = file '../target'
|
||||
}
|
||||
shadowJar.doLast {
|
||||
task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar);
|
43
bukkit18/build/resources/main/plugin.yml
Normal file
43
bukkit18/build/resources/main/plugin.yml
Normal file
@ -0,0 +1,43 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.v1_8.BukkitMain_1_8
|
||||
version: 3.4.2
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
loadbefore: [WorldEdit]
|
||||
load: STARTUP
|
||||
database: false
|
||||
#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones]
|
||||
commands:
|
||||
wea:
|
||||
description: (FAWE) Bypass WorldEdit processing and area restrictions
|
||||
aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere]
|
||||
usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass"
|
||||
fixlighting:
|
||||
description: (FAWE) Fix the lighting in your current chunk
|
||||
aliases: [/fixlighting]
|
||||
stream:
|
||||
description: (FAWE) Stream a schematic into the world
|
||||
aliases: [/stream]
|
||||
fawe:
|
||||
description: (FAWE) Reload the plugin
|
||||
aliases: [/fawe,/fawereload]
|
||||
wrg:
|
||||
description: (FAWE) Select your current WorldEdit Region.
|
||||
aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region]
|
||||
frb:
|
||||
description: (FAWE) Rollback an edit
|
||||
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
|
||||
fcancel:
|
||||
description: (FAWE) Cancel your edit
|
||||
aliases: [fawecancel,/fcancel,/cancel,/fawecancel]
|
||||
permissions:
|
||||
fawe.bypass:
|
||||
default: false
|
||||
fawe.admin:
|
||||
default: false
|
||||
fawe.stream:
|
||||
default: false
|
||||
fawe.fixlighting:
|
||||
default: false
|
||||
fawe.reload:
|
||||
default: false
|
@ -0,0 +1,24 @@
|
||||
package com.boydti.fawe.bukkit.v1_8;
|
||||
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
|
||||
public class BukkitChunk_1_8 extends CharFaweChunk<Chunk> {
|
||||
/**
|
||||
* 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_8(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getNewChunk() {
|
||||
return Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ());
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.boydti.fawe.bukkit.v1_8;
|
||||
|
||||
import com.boydti.fawe.bukkit.BukkitMain;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
|
||||
public class BukkitMain_1_8 extends BukkitMain {
|
||||
@Override
|
||||
public BukkitQueue_0 getQueue(String world) {
|
||||
return new BukkitQueue18R3(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditSessionWrapper getEditSessionWrapper(EditSession session) {
|
||||
return new EditSessionWrapper(session);
|
||||
}
|
||||
}
|
@ -0,0 +1,327 @@
|
||||
package com.boydti.fawe.bukkit.v1_8;
|
||||
|
||||
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.FaweLocation;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import net.minecraft.server.v1_8_R3.BlockPosition;
|
||||
import net.minecraft.server.v1_8_R3.ChunkCoordIntPair;
|
||||
import net.minecraft.server.v1_8_R3.ChunkSection;
|
||||
import net.minecraft.server.v1_8_R3.PacketPlayOutMapChunk;
|
||||
import net.minecraft.server.v1_8_R3.PlayerConnection;
|
||||
import net.minecraft.server.v1_8_R3.TileEntity;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
import org.bukkit.Material;
|
||||
import org.bukkit.World;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.CraftChunk;
|
||||
import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
|
||||
|
||||
public class BukkitQueue18R3 extends BukkitQueue_0<Chunk, ChunkSection[], char[]> {
|
||||
|
||||
public BukkitQueue18R3(final String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(int x, int z) {
|
||||
return getWorld().isChunkLoaded(x, z);
|
||||
}
|
||||
|
||||
public World getWorld(String world) {
|
||||
return Bukkit.getWorld(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(World world, int x, int z) {
|
||||
return world.regenerateChunk(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadChunk(World world, int x, int z, boolean generate) {
|
||||
return getCachedChunk(world, x, z) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ChunkSection[] getCachedChunk(World world, int x, int z) {
|
||||
Chunk chunk = world.getChunkAt(x, z);
|
||||
if (chunk == null) {
|
||||
return null;
|
||||
}
|
||||
if (!chunk.isLoaded()) {
|
||||
chunk.load(true);
|
||||
}
|
||||
return ((CraftChunk) chunk).getHandle().getSections();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(char[] ls, int x, int y, int z) {
|
||||
return ls[FaweCache.CACHE_J[y][x & 15][z & 15]];
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(World world, int x, int z) {
|
||||
return world.isChunkLoaded(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponents(FaweChunk fc) {
|
||||
CharFaweChunk<Chunk> fs = (CharFaweChunk<Chunk>) fc;
|
||||
CraftChunk chunk = (CraftChunk) fs.getChunk();
|
||||
net.minecraft.server.v1_8_R3.Chunk nmsChunk = chunk.getHandle();
|
||||
net.minecraft.server.v1_8_R3.World nmsWorld = nmsChunk.getWorld();
|
||||
try {
|
||||
final boolean flag = getWorld().getEnvironment() == World.Environment.NORMAL;
|
||||
// Sections
|
||||
ChunkSection[] sections = nmsChunk.getSections();
|
||||
Map<BlockPosition, TileEntity> tiles = nmsChunk.getTileEntities();
|
||||
Collection<net.minecraft.server.v1_8_R3.Entity>[] entities = nmsChunk.getEntitySlices();
|
||||
// Trim tiles
|
||||
Set<Map.Entry<BlockPosition, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Map.Entry<BlockPosition, TileEntity>> iterator = entryset.iterator();
|
||||
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][lx][lz];
|
||||
int k = FaweCache.CACHE_J[ly][lx][lz];
|
||||
char[] array = fs.getIdArray(j);
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
if (array[k] != 0) {
|
||||
iterator.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;
|
||||
}
|
||||
char[] newArray = fs.getIdArray(j);
|
||||
if (newArray == null) {
|
||||
continue;
|
||||
}
|
||||
ChunkSection section = sections[j];
|
||||
if ((section == null) || (fs.getCount(j) >= 4096)) {
|
||||
section = new ChunkSection(j << 4, flag, newArray);
|
||||
sections[j] = section;
|
||||
continue;
|
||||
}
|
||||
char[] currentArray = section.getIdArray();
|
||||
boolean fill = true;
|
||||
int solid = 0;
|
||||
for (int k = 0; k < newArray.length; k++) {
|
||||
char n = newArray[k];
|
||||
switch (n) {
|
||||
case 0:
|
||||
fill = false;
|
||||
continue;
|
||||
case 1:
|
||||
fill = false;
|
||||
if (currentArray[k] > 1) {
|
||||
solid++;
|
||||
}
|
||||
currentArray[k] = 0;
|
||||
continue;
|
||||
default:
|
||||
solid++;
|
||||
currentArray[k] = n;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
setCount(0, solid, section);
|
||||
if (fill) {
|
||||
fs.setCount(j, Short.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
// // Clear
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
int[][] biomes = fs.biomes;
|
||||
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;
|
||||
}
|
||||
nmsChunk.getBiomeIndex()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
sendChunk(fc);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ChunkSection section) throws NoSuchFieldException, IllegalAccessException {
|
||||
Class<? extends ChunkSection> clazz = section.getClass();
|
||||
Field fieldTickingBlockCount = clazz.getDeclaredField("tickingBlockCount");
|
||||
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("nonEmptyBlockCount");
|
||||
fieldTickingBlockCount.setAccessible(true);
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
fieldTickingBlockCount.set(section, tickingBlockCount);
|
||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshChunk(World world, Chunk chunk) {
|
||||
if (!chunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
net.minecraft.server.v1_8_R3.Chunk nmsChunk = ((CraftChunk) chunk).getHandle();
|
||||
ChunkCoordIntPair pos = nmsChunk.j();
|
||||
int cx = pos.x;
|
||||
int cz = pos.z;
|
||||
int view = Bukkit.getViewDistance();
|
||||
for (FawePlayer fp : Fawe.get().getCachedPlayers()) {
|
||||
BukkitPlayer bukkitPlayer = (BukkitPlayer) fp;
|
||||
if (!bukkitPlayer.getWorld().equals(world)) {
|
||||
continue;
|
||||
}
|
||||
net.minecraft.server.v1_8_R3.EntityPlayer nmsPlayer = ((CraftPlayer) bukkitPlayer.parent).getHandle();
|
||||
FaweLocation loc = fp.getLocation();
|
||||
int px = loc.x >> 4;
|
||||
int pz = loc.z >> 4;
|
||||
int dx = Math.abs(cx - (loc.x >> 4));
|
||||
int dz = Math.abs(cz - (loc.z >> 4));
|
||||
if ((dx > view) || (dz > view)) {
|
||||
continue;
|
||||
}
|
||||
PlayerConnection con = nmsPlayer.playerConnection;
|
||||
con.sendPacket(new PacketPlayOutMapChunk(nmsChunk, false, 65535));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(FaweChunk chunk, boolean fixAll) {
|
||||
try {
|
||||
CharFaweChunk<Chunk> fc = (CharFaweChunk<Chunk>) chunk;
|
||||
CraftChunk craftChunk = (CraftChunk) fc.getChunk();
|
||||
net.minecraft.server.v1_8_R3.Chunk nmsChunk = craftChunk.getHandle();
|
||||
if (!craftChunk.isLoaded()) {
|
||||
return false;
|
||||
}
|
||||
nmsChunk.initLighting();
|
||||
if (fc.getTotalRelight() == 0 && !fixAll) {
|
||||
return true;
|
||||
}
|
||||
ChunkSection[] sections = nmsChunk.getSections();
|
||||
net.minecraft.server.v1_8_R3.World nmsWorld = nmsChunk.getWorld();
|
||||
|
||||
int X = fc.getX() << 4;
|
||||
int Z = fc.getZ() << 4;
|
||||
|
||||
BlockPosition.MutableBlockPosition pos = new BlockPosition.MutableBlockPosition(0, 0, 0);
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
ChunkSection section = sections[j];
|
||||
if (section == null) {
|
||||
continue;
|
||||
}
|
||||
if ((fc.getRelight(j) == 0 && !fixAll) || fc.getCount(j) == 0 || (fc.getCount(j) >= 4096 && fc.getAir(j) == 0)) {
|
||||
continue;
|
||||
}
|
||||
char[] array = section.getIdArray();
|
||||
int l = PseudoRandom.random.random(2);
|
||||
for (int k = 0; k < array.length; k++) {
|
||||
int i = array[k];
|
||||
if (i < 16) {
|
||||
continue;
|
||||
}
|
||||
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:
|
||||
int x = FaweCache.CACHE_X[j][k];
|
||||
int y = FaweCache.CACHE_Y[j][k];
|
||||
int z = FaweCache.CACHE_Z[j][k];
|
||||
if (isSurrounded(sections, x, y, z)) {
|
||||
continue;
|
||||
}
|
||||
pos.c(X + x, y, Z + z);
|
||||
nmsWorld.x(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
if (Thread.currentThread() == Fawe.get().getMainThread()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSurrounded(ChunkSection[] 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 Material.getMaterial(i).isOccluding();
|
||||
}
|
||||
|
||||
public int getId(ChunkSection[] 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];
|
||||
ChunkSection section = sections[i];
|
||||
if (section == null) {
|
||||
return 0;
|
||||
}
|
||||
char[] array = section.getIdArray();
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
return array[j] >> 4;
|
||||
}
|
||||
}
|
43
bukkit18/src/main/resources/plugin.yml
Normal file
43
bukkit18/src/main/resources/plugin.yml
Normal file
@ -0,0 +1,43 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.v1_8.BukkitMain_1_8
|
||||
version: 3.4.2
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
loadbefore: [WorldEdit]
|
||||
load: STARTUP
|
||||
database: false
|
||||
#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones]
|
||||
commands:
|
||||
wea:
|
||||
description: (FAWE) Bypass WorldEdit processing and area restrictions
|
||||
aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere]
|
||||
usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass"
|
||||
fixlighting:
|
||||
description: (FAWE) Fix the lighting in your current chunk
|
||||
aliases: [/fixlighting]
|
||||
stream:
|
||||
description: (FAWE) Stream a schematic into the world
|
||||
aliases: [/stream]
|
||||
fawe:
|
||||
description: (FAWE) Reload the plugin
|
||||
aliases: [/fawe,/fawereload]
|
||||
wrg:
|
||||
description: (FAWE) Select your current WorldEdit Region.
|
||||
aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region]
|
||||
frb:
|
||||
description: (FAWE) Rollback an edit
|
||||
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
|
||||
fcancel:
|
||||
description: (FAWE) Cancel your edit
|
||||
aliases: [fawecancel,/fcancel,/cancel,/fawecancel]
|
||||
permissions:
|
||||
fawe.bypass:
|
||||
default: false
|
||||
fawe.admin:
|
||||
default: false
|
||||
fawe.stream:
|
||||
default: false
|
||||
fawe.fixlighting:
|
||||
default: false
|
||||
fawe.reload:
|
||||
default: false
|
22
bukkit19/build.gradle
Normal file
22
bukkit19/build.gradle
Normal file
@ -0,0 +1,22 @@
|
||||
dependencies {
|
||||
compile project(':bukkit0')
|
||||
compile 'org.bukkit.craftbukkit:CraftBukkit:1.9.2'
|
||||
}
|
||||
|
||||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
// We only want the shadow jar produced
|
||||
jar.enabled = false
|
||||
shadowJar {
|
||||
dependencies {
|
||||
include(dependency(':bukkit0'))
|
||||
include(dependency(':core'))
|
||||
}
|
||||
archiveName = "${parent.name}-${project.name}.jar"
|
||||
destinationDir = file '../target'
|
||||
}
|
||||
shadowJar.doLast {
|
||||
task ->
|
||||
ant.checksum file: task.archivePath
|
||||
}
|
||||
|
||||
build.dependsOn(shadowJar);
|
BIN
bukkit19/build/libs/bukkit19-all.jar
Normal file
BIN
bukkit19/build/libs/bukkit19-all.jar
Normal file
Binary file not shown.
1
bukkit19/build/libs/bukkit19-all.jar.MD5
Normal file
1
bukkit19/build/libs/bukkit19-all.jar.MD5
Normal file
@ -0,0 +1 @@
|
||||
0b4c7b4aeeea42cb68e5ccfcc8c82b14
|
43
bukkit19/build/resources/main/plugin.yml
Normal file
43
bukkit19/build/resources/main/plugin.yml
Normal file
@ -0,0 +1,43 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.v1_9.BukkitMain_1_9
|
||||
version: 3.4.2
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
loadbefore: [WorldEdit]
|
||||
load: STARTUP
|
||||
database: false
|
||||
#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones]
|
||||
commands:
|
||||
wea:
|
||||
description: (FAWE) Bypass WorldEdit processing and area restrictions
|
||||
aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere]
|
||||
usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass"
|
||||
fixlighting:
|
||||
description: (FAWE) Fix the lighting in your current chunk
|
||||
aliases: [/fixlighting]
|
||||
stream:
|
||||
description: (FAWE) Stream a schematic into the world
|
||||
aliases: [/stream]
|
||||
fawe:
|
||||
description: (FAWE) Reload the plugin
|
||||
aliases: [/fawe,/fawereload]
|
||||
wrg:
|
||||
description: (FAWE) Select your current WorldEdit Region.
|
||||
aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region]
|
||||
frb:
|
||||
description: (FAWE) Rollback an edit
|
||||
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
|
||||
fcancel:
|
||||
description: (FAWE) Cancel your edit
|
||||
aliases: [fawecancel,/fcancel,/cancel,/fawecancel]
|
||||
permissions:
|
||||
fawe.bypass:
|
||||
default: false
|
||||
fawe.admin:
|
||||
default: false
|
||||
fawe.stream:
|
||||
default: false
|
||||
fawe.fixlighting:
|
||||
default: false
|
||||
fawe.reload:
|
||||
default: false
|
2
bukkit19/build/tmp/shadowJar/MANIFEST.MF
Normal file
2
bukkit19/build/tmp/shadowJar/MANIFEST.MF
Normal file
@ -0,0 +1,2 @@
|
||||
Manifest-Version: 1.0
|
||||
|
@ -0,0 +1,114 @@
|
||||
package com.boydti.fawe.bukkit.v1_9;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import net.minecraft.server.v1_9_R1.Block;
|
||||
import net.minecraft.server.v1_9_R1.DataBits;
|
||||
import net.minecraft.server.v1_9_R1.DataPalette;
|
||||
import net.minecraft.server.v1_9_R1.DataPaletteBlock;
|
||||
import net.minecraft.server.v1_9_R1.DataPaletteGlobal;
|
||||
import net.minecraft.server.v1_9_R1.IBlockData;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
|
||||
public class BukkitChunk_1_9 extends CharFaweChunk<Chunk> {
|
||||
|
||||
public DataPaletteBlock[] sectionPalettes;
|
||||
|
||||
/**
|
||||
* 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_9(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getNewChunk() {
|
||||
return Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharFaweChunk<Chunk> copy(boolean shallow) {
|
||||
BukkitChunk_1_9 value = (BukkitChunk_1_9) super.copy(shallow);
|
||||
if (sectionPalettes != null) {
|
||||
value.sectionPalettes = new DataPaletteBlock[16];
|
||||
try {
|
||||
Field fieldBits = DataPaletteBlock.class.getDeclaredField("b");
|
||||
fieldBits.setAccessible(true);
|
||||
Field fieldPalette = DataPaletteBlock.class.getDeclaredField("c");
|
||||
fieldPalette.setAccessible(true);
|
||||
Field fieldSize = DataPaletteBlock.class.getDeclaredField("e");
|
||||
fieldSize.setAccessible(true);
|
||||
for (int i = 0; i < sectionPalettes.length; i++) {
|
||||
DataPaletteBlock current = sectionPalettes[i];
|
||||
if (current == null) {
|
||||
continue;
|
||||
}
|
||||
DataPaletteBlock paletteBlock = new DataPaletteBlock();
|
||||
// Clone palette
|
||||
DataPalette currentPalette = (DataPalette) fieldPalette.get(paletteBlock);
|
||||
if (!(currentPalette instanceof DataPaletteGlobal)) {
|
||||
try {
|
||||
Method resize = DataPaletteBlock.class.getDeclaredMethod("b", int.class);
|
||||
resize.setAccessible(true);
|
||||
resize.invoke(paletteBlock, 128);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
currentPalette = (DataPalette) fieldPalette.get(paletteBlock);
|
||||
fieldPalette.set(paletteBlock, currentPalette);
|
||||
// Clone size
|
||||
fieldSize.set(paletteBlock, fieldSize.get(current));
|
||||
// Clone pallete
|
||||
DataBits currentBits = (DataBits) fieldBits.get(current);
|
||||
DataBits newBits = new DataBits(1, 0);
|
||||
for (Field field : DataBits.class.getDeclaredFields()) {
|
||||
field.setAccessible(true);
|
||||
field.set(newBits, field.get(currentBits));
|
||||
}
|
||||
fieldBits.set(paletteBlock, newBits);
|
||||
value.sectionPalettes[i] = paletteBlock;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
public void optimize() {
|
||||
if (sectionPalettes != null) {
|
||||
return;
|
||||
}
|
||||
char[][] arrays = getIdArrays();
|
||||
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 = sectionPalettes[layer] = new DataPaletteBlock();
|
||||
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][x][z]];
|
||||
if (combinedId > 1) {
|
||||
palette.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.boydti.fawe.bukkit.v1_9;
|
||||
|
||||
import com.boydti.fawe.bukkit.BukkitMain;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_0;
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
|
||||
public class BukkitMain_1_9 extends BukkitMain {
|
||||
@Override
|
||||
public BukkitQueue_0 getQueue(String world) {
|
||||
return new BukkitQueue_1_9_R1(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public EditSessionWrapper getEditSessionWrapper(EditSession session) {
|
||||
return new EditSessionWrapper(session);
|
||||
}
|
||||
}
|
@ -2,20 +2,17 @@ package com.boydti.fawe.bukkit.v1_9;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.bukkit.v0.BukkitQueue_All;
|
||||
import com.boydti.fawe.bukkit.v1_8.BukkitChunk_1_8;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
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.IntegerPair;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.util.MemUtil;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.LocalSession;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
@ -24,6 +21,7 @@ import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import net.minecraft.server.v1_9_R1.Block;
|
||||
import net.minecraft.server.v1_9_R1.BlockPosition;
|
||||
import net.minecraft.server.v1_9_R1.Blocks;
|
||||
import net.minecraft.server.v1_9_R1.ChunkSection;
|
||||
import net.minecraft.server.v1_9_R1.DataBits;
|
||||
import net.minecraft.server.v1_9_R1.DataPalette;
|
||||
@ -43,25 +41,26 @@ import org.bukkit.entity.Player;
|
||||
import org.bukkit.generator.BlockPopulator;
|
||||
import org.bukkit.generator.ChunkGenerator;
|
||||
|
||||
public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
||||
public class BukkitQueue_1_9_R1 extends BukkitQueue_0<Chunk, ChunkSection[], DataPaletteBlock> {
|
||||
|
||||
public BukkitQueue_1_9_R1(final String world) throws NoSuchMethodException, RuntimeException {
|
||||
public BukkitQueue_1_9_R1(final String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
public Object getCachedChunk(int cx, int cz) {
|
||||
CraftChunk chunk = (CraftChunk) bukkitWorld.getChunkAt(cx, cz);
|
||||
@Override
|
||||
public ChunkSection[] getCachedChunk(World world, int cx, int cz) {
|
||||
CraftChunk chunk = (CraftChunk) world.getChunkAt(cx, cz);
|
||||
return chunk.getHandle().getSections();
|
||||
}
|
||||
|
||||
public Object getCachedSection(Object chunk, int cy) {
|
||||
ChunkSection[] chunkSections = (ChunkSection[]) chunk;
|
||||
@Override
|
||||
public DataPaletteBlock getCachedSection(ChunkSection[] chunkSections, int cy) {
|
||||
ChunkSection nibble = chunkSections[cy];
|
||||
return nibble != null ? nibble.getBlocks() : null;
|
||||
}
|
||||
|
||||
public int getCombinedId4Data(Object section, int x, int y, int z) {
|
||||
DataPaletteBlock lastSection = (DataPaletteBlock) section;
|
||||
@Override
|
||||
public int getCombinedId4Data(DataPaletteBlock lastSection, int x, int y, int z) {
|
||||
IBlockData ibd = lastSection.a(x & 15, y & 15, z & 15);
|
||||
Block block = ibd.getBlock();
|
||||
int id = Block.getId(block);
|
||||
@ -73,37 +72,15 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs) {
|
||||
for (final FaweChunk<Chunk> fc : fcs) {
|
||||
sendChunk(fc);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public void sendChunk(final FaweChunk<Chunk> fc) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
|
||||
TaskManager.IMP.sync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
}
|
||||
final Chunk chunk = fc.getChunk();
|
||||
chunk.getWorld().refreshChunk(fc.getX(), fc.getZ());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}, Settings.ASYNC_LIGHTING);
|
||||
public void refreshChunk(World world, Chunk fc) {
|
||||
world.refreshChunk(fc.getX(), fc.getZ());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(final FaweChunk<?> pc, final boolean fixAll) {
|
||||
public boolean fixLighting(final FaweChunk pc, final boolean fixAll) {
|
||||
try {
|
||||
final BukkitChunk_1_8 bc = (BukkitChunk_1_8) pc;
|
||||
final Chunk chunk = bc.getChunk();
|
||||
final CharFaweChunk bc = (CharFaweChunk) pc;
|
||||
final Chunk chunk = (Chunk) bc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
if (Fawe.get().getMainThread() != Thread.currentThread()) {
|
||||
return false;
|
||||
@ -232,10 +209,16 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||
}
|
||||
|
||||
public void setPalette(ChunkSection section, DataPaletteBlock palette) throws NoSuchFieldException, IllegalAccessException {
|
||||
Field fieldSection = ChunkSection.class.getDeclaredField("blockIds");
|
||||
fieldSection.setAccessible(true);
|
||||
fieldSection.set(section, palette);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponents(final FaweChunk<Chunk> pc) {
|
||||
final BukkitChunk_1_8 fs = (BukkitChunk_1_8) pc;
|
||||
final Chunk chunk = pc.getChunk();
|
||||
public boolean setComponents(final FaweChunk pc) {
|
||||
final BukkitChunk_1_9 fs = (BukkitChunk_1_9) pc;
|
||||
final Chunk chunk = (Chunk) fs.getChunk();
|
||||
final World world = chunk.getWorld();
|
||||
chunk.load(true);
|
||||
try {
|
||||
@ -286,10 +269,10 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
||||
entities[i].clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Efficiently merge sections
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
if (fs.getCount(j) == 0) {
|
||||
int count = fs.getCount(j);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
}
|
||||
final char[] array = fs.getIdArray(j);
|
||||
@ -298,7 +281,23 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
||||
}
|
||||
ChunkSection section = sections[j];
|
||||
if (section == null) {
|
||||
if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) {
|
||||
section = sections[j] = new ChunkSection(j << 4, flag);
|
||||
setPalette(section, fs.sectionPalettes[j]);
|
||||
setCount(0, count - fs.getAir(j), section);
|
||||
continue;
|
||||
} else {
|
||||
sections[j] = new ChunkSection(j << 4, flag, array);
|
||||
}
|
||||
continue;
|
||||
} else if (count >= 4096) {
|
||||
if (fs.sectionPalettes != null && fs.sectionPalettes[j] != null) {
|
||||
setPalette(section, fs.sectionPalettes[j]);
|
||||
setCount(0, count - fs.getAir(j), section);
|
||||
continue;
|
||||
} else {
|
||||
sections[j] = new ChunkSection(j << 4, flag, array);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
DataPaletteBlock nibble = section.getBlocks();
|
||||
@ -309,94 +308,24 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
||||
Field fieldPalette = nibble.getClass().getDeclaredField("c");
|
||||
fieldPalette.setAccessible(true);
|
||||
DataPalette palette = (DataPalette) fieldPalette.get(nibble);
|
||||
|
||||
if (fs.getCount(j) >= 4096) {
|
||||
int tickingBlockCount = 0;
|
||||
int nonEmptyBlockCount = fs.getCount(j) - fs.getAir(j);
|
||||
setCount(tickingBlockCount, nonEmptyBlockCount, section);
|
||||
int lastId = -1;
|
||||
int lastBit = -1;
|
||||
for (int i = 0; i < array.length; i++) {
|
||||
int value = array[i];
|
||||
if (value != lastId) {
|
||||
lastId = value;
|
||||
int id = lastId >> 4;
|
||||
int data = lastId & 0xF;
|
||||
IBlockData ibd = Block.getById(id).fromLegacyData(data);
|
||||
lastBit = palette.a(ibd);
|
||||
palette = (DataPalette) fieldPalette.get(nibble);
|
||||
bits = (DataBits) fieldBits.get(nibble);
|
||||
}
|
||||
bits.a(i, lastBit);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
boolean fill = true;
|
||||
int nonEmptyBlockCount = 0;
|
||||
int lastId = -1;
|
||||
int lastBit = -1;
|
||||
for (int k = 0; k < array.length; k++) {
|
||||
final char combined = array[k];
|
||||
switch (combined) {
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
char combinedId = array[FaweCache.CACHE_J[y][x][z]];
|
||||
switch (combinedId) {
|
||||
case 0:
|
||||
int existingBit = bits.a(k);
|
||||
if (existingBit != lastBit) {
|
||||
palette = (DataPalette) fieldPalette.get(nibble);
|
||||
bits = (DataBits) fieldBits.get(nibble);
|
||||
lastBit = existingBit;
|
||||
IBlockData ibd = palette.a(existingBit);
|
||||
if (ibd == null) {
|
||||
fill = false;
|
||||
continue;
|
||||
}
|
||||
Block block = ibd.getBlock();
|
||||
int id = Block.getId(block);
|
||||
if (FaweCache.hasData(id)) {
|
||||
lastId = (id << 4) + block.toLegacyData(ibd);
|
||||
} else {
|
||||
lastId = id << 4;
|
||||
}
|
||||
}
|
||||
if (lastId != 0) {
|
||||
case 1:
|
||||
// TODO check existing
|
||||
nibble.setBlock(x, y, z, Blocks.AIR.getBlockData());
|
||||
continue;
|
||||
default:
|
||||
nonEmptyBlockCount++;
|
||||
} else {
|
||||
fill = false;
|
||||
}
|
||||
continue;
|
||||
case 1: {
|
||||
fill = false;
|
||||
int value = 0;
|
||||
if (value != lastId) {
|
||||
lastId = value;
|
||||
int id = lastId >> 4;
|
||||
int data = lastId & 0xF;
|
||||
IBlockData ibd = Block.getById(id).fromLegacyData(data);
|
||||
lastBit = palette.a(ibd);
|
||||
palette = (DataPalette) fieldPalette.get(nibble);
|
||||
bits = (DataBits) fieldBits.get(nibble);
|
||||
}
|
||||
bits.a(k, lastBit);
|
||||
continue;
|
||||
}
|
||||
default: {
|
||||
nonEmptyBlockCount++;
|
||||
int value = combined;
|
||||
if (value != lastId) {
|
||||
lastId = value;
|
||||
int id = lastId >> 4;
|
||||
int data = lastId & 0xF;
|
||||
IBlockData ibd = Block.getById(id).fromLegacyData(data);
|
||||
lastBit = palette.a(ibd);
|
||||
palette = (DataPalette) fieldPalette.get(nibble);
|
||||
bits = (DataBits) fieldBits.get(nibble);
|
||||
}
|
||||
bits.a(k, lastBit);
|
||||
continue;
|
||||
nibble.setBlock(x, y, z, Block.getById(combinedId >> 4).fromLegacyData(combinedId & 0xF));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fill) {
|
||||
fs.setCount(j, Short.MAX_VALUE);
|
||||
}
|
||||
setCount(0, nonEmptyBlockCount, section);
|
||||
}
|
||||
@ -534,11 +463,6 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
||||
players = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getChunk(int x, int z) {
|
||||
return new BukkitChunk_1_8(this, x, z);
|
||||
}
|
||||
|
||||
public boolean unloadChunk(final String world, final Chunk chunk) {
|
||||
net.minecraft.server.v1_9_R1.Chunk c = ((CraftChunk) chunk).getHandle();
|
||||
c.mustSave = false;
|
||||
@ -674,4 +598,9 @@ public class BukkitQueue_1_9_R1 extends BukkitQueue_All {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk getChunk(int x, int z) {
|
||||
return new BukkitChunk_1_9(this, x, z);
|
||||
}
|
||||
}
|
43
bukkit19/src/main/resources/plugin.yml
Normal file
43
bukkit19/src/main/resources/plugin.yml
Normal file
@ -0,0 +1,43 @@
|
||||
name: FastAsyncWorldEdit
|
||||
main: com.boydti.fawe.bukkit.v1_9.BukkitMain_1_9
|
||||
version: 3.4.2
|
||||
description: Fast Async WorldEdit plugin
|
||||
authors: [Empire92]
|
||||
loadbefore: [WorldEdit]
|
||||
load: STARTUP
|
||||
database: false
|
||||
#softdepend: [WorldGuard, PlotSquared, MCore, Factions, GriefPrevention, Residence, Towny, PlotMe, PreciousStones]
|
||||
commands:
|
||||
wea:
|
||||
description: (FAWE) Bypass WorldEdit processing and area restrictions
|
||||
aliases: [weanywhere,worldeditanywhere,/wea,/weanywhere,/worldeditanywhere]
|
||||
usage: "Vault is required for the toggle. Optionally, you can set the permission fawe.bypass"
|
||||
fixlighting:
|
||||
description: (FAWE) Fix the lighting in your current chunk
|
||||
aliases: [/fixlighting]
|
||||
stream:
|
||||
description: (FAWE) Stream a schematic into the world
|
||||
aliases: [/stream]
|
||||
fawe:
|
||||
description: (FAWE) Reload the plugin
|
||||
aliases: [/fawe,/fawereload]
|
||||
wrg:
|
||||
description: (FAWE) Select your current WorldEdit Region.
|
||||
aliases: [/wrg,wer,/wer,worldeditregion,/worldeditregion,/region]
|
||||
frb:
|
||||
description: (FAWE) Rollback an edit
|
||||
aliases: [fawerollback,fawerb,/uu,/rb,/frb,/fawerollback,/fawerb]
|
||||
fcancel:
|
||||
description: (FAWE) Cancel your edit
|
||||
aliases: [fawecancel,/fcancel,/cancel,/fawecancel]
|
||||
permissions:
|
||||
fawe.bypass:
|
||||
default: false
|
||||
fawe.admin:
|
||||
default: false
|
||||
fawe.stream:
|
||||
default: false
|
||||
fawe.fixlighting:
|
||||
default: false
|
||||
fawe.reload:
|
||||
default: false
|
@ -84,7 +84,7 @@ public class FaweAPI {
|
||||
* @return
|
||||
*/
|
||||
public FaweQueue createQueue(String worldName, boolean autoqueue) {
|
||||
return SetQueue.IMP.getNewQueue(worldName, autoqueue);
|
||||
return SetQueue.IMP.getNewQueue(worldName, true, autoqueue);
|
||||
}
|
||||
|
||||
public static World getWorld(String worldName) {
|
||||
@ -295,7 +295,7 @@ public class FaweAPI {
|
||||
* @param fixAll
|
||||
*/
|
||||
public static void fixLighting(String world, int x, int z, final boolean fixAll) {
|
||||
FaweQueue queue = SetQueue.IMP.getNewQueue(world, false);
|
||||
FaweQueue queue = SetQueue.IMP.getNewQueue(world, true, false);
|
||||
queue.fixLighting(queue.getChunk(x, z), fixAll);
|
||||
}
|
||||
|
||||
@ -305,7 +305,7 @@ public class FaweAPI {
|
||||
* @param fixAll
|
||||
*/
|
||||
public static void fixLighting(final Chunk chunk, final boolean fixAll) {
|
||||
FaweQueue queue = SetQueue.IMP.getNewQueue(chunk.getWorld().getName(), false);
|
||||
FaweQueue queue = SetQueue.IMP.getNewQueue(chunk.getWorld().getName(), true, false);
|
||||
queue.fixLighting(queue.getChunk(chunk.getX(), chunk.getZ()), fixAll);
|
||||
}
|
||||
|
||||
@ -388,7 +388,7 @@ public class FaweAPI {
|
||||
tagMap = null;
|
||||
tag = null;
|
||||
|
||||
FaweQueue queue = SetQueue.IMP.getNewQueue(loc.world, true);
|
||||
FaweQueue queue = SetQueue.IMP.getNewQueue(loc.world, true, true);
|
||||
|
||||
for (int y = 0; y < height; y++) {
|
||||
final int yy = y_offset + y;
|
||||
|
@ -5,7 +5,13 @@ import com.sk89q.worldedit.CuboidClipboard;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
|
||||
public class FaweCache {
|
||||
/**
|
||||
* y | x | z
|
||||
*/
|
||||
public final static short[][][] CACHE_I = new short[256][16][16];
|
||||
/**
|
||||
* y | x | z
|
||||
*/
|
||||
public final static short[][][] CACHE_J = new short[256][16][16];
|
||||
|
||||
public final static byte[][] CACHE_X = new byte[16][4096];
|
||||
@ -105,13 +111,10 @@ public class FaweCache {
|
||||
case 49:
|
||||
case 51:
|
||||
case 52:
|
||||
case 54:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 61:
|
||||
case 62:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
|
@ -29,7 +29,7 @@ public interface IFawe {
|
||||
|
||||
public int[] getVersion();
|
||||
|
||||
public FaweQueue getNewQueue(String world);
|
||||
public FaweQueue getNewQueue(String world, boolean fast);
|
||||
|
||||
public String getWorldName(World world);
|
||||
|
||||
|
@ -22,7 +22,6 @@ public class Settings {
|
||||
public static boolean ENABLE_HARD_LIMIT = true;
|
||||
public static boolean STORE_HISTORY_ON_DISK = false;
|
||||
public static boolean STORE_CLIPBOARD_ON_DISK = false;
|
||||
|
||||
public static int DELETE_HISTORY_AFTER_DAYS = 7;
|
||||
public static int DELETE_CLIPBOARD_AFTER_DAYS = 1;
|
||||
public static int COMPRESSION_LEVEL = 0;
|
||||
@ -39,6 +38,8 @@ public class Settings {
|
||||
public static int UNSAFE_PARALLEL_THREADS = 1;
|
||||
public static boolean FIX_ALL_LIGHTING = true;
|
||||
public static boolean ASYNC_LIGHTING = true;
|
||||
public static int PHYSICS_PER_TICK = 1337;
|
||||
public static int ITEMS_PER_TICK = 1337;
|
||||
|
||||
public static HashMap<String, FaweLimit> limits;
|
||||
|
||||
@ -103,6 +104,9 @@ public class Settings {
|
||||
options.put("extent.debug", EXTENT_DEBUG);
|
||||
options.put("metrics", METRICS);
|
||||
|
||||
options.put("tick-limiter.physics", PHYSICS_PER_TICK);
|
||||
options.put("tick-limiter.items", ITEMS_PER_TICK);
|
||||
|
||||
// Default limit
|
||||
FaweLimit defaultLimit = new FaweLimit();
|
||||
if (!config.contains("limits.default")) {
|
||||
@ -141,6 +145,9 @@ public class Settings {
|
||||
EXTENT_DEBUG = config.getBoolean("extent.debug");
|
||||
STORE_CLIPBOARD_ON_DISK = config.getBoolean("clipboard.use-disk");
|
||||
DELETE_CLIPBOARD_AFTER_DAYS = config.getInt("clipboard.delete-after-days");
|
||||
PHYSICS_PER_TICK = config.getInt("tick-limiter.physics");
|
||||
ITEMS_PER_TICK = config.getInt("tick-limiter.items");
|
||||
|
||||
if (STORE_HISTORY_ON_DISK = config.getBoolean("history.use-disk")) {
|
||||
LocalSession.MAX_HISTORY_SIZE = Integer.MAX_VALUE;
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
package com.boydti.fawe.bukkit.v1_8;
|
||||
package com.boydti.fawe.example;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
@ -6,24 +6,25 @@ import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.Arrays;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
|
||||
public class BukkitChunk_1_8 extends FaweChunk<Chunk> {
|
||||
public abstract class CharFaweChunk<T> extends FaweChunk<T> {
|
||||
|
||||
private char[][] ids;
|
||||
public char[][] ids;
|
||||
public short[] count;
|
||||
public short[] air;
|
||||
public short[] relight;
|
||||
public int[][] biomes;
|
||||
|
||||
private short[] count;
|
||||
private short[] air;
|
||||
private short[] relight;
|
||||
private int[][] biomes;
|
||||
|
||||
public Chunk chunk;
|
||||
public T chunk;
|
||||
|
||||
/**
|
||||
* 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_8(FaweQueue parent, int x, int z) {
|
||||
public CharFaweChunk(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
this.ids = new char[16][];
|
||||
this.count = new short[16];
|
||||
@ -32,13 +33,15 @@ public class BukkitChunk_1_8 extends FaweChunk<Chunk> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk() {
|
||||
public T getChunk() {
|
||||
if (this.chunk == null) {
|
||||
this.chunk = Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ());
|
||||
this.chunk = getNewChunk();
|
||||
}
|
||||
return this.chunk;
|
||||
}
|
||||
|
||||
public abstract T getNewChunk();
|
||||
|
||||
@Override
|
||||
public void setLoc(final FaweQueue parent, int x, int z) {
|
||||
super.setLoc(parent, x, z);
|
||||
@ -199,15 +202,17 @@ public class BukkitChunk_1_8 extends FaweChunk<Chunk> {
|
||||
case 130:
|
||||
case 76:
|
||||
case 62:
|
||||
case 50:
|
||||
this.relight[i]++;
|
||||
case 54:
|
||||
case 146:
|
||||
case 61:
|
||||
case 65:
|
||||
case 68:
|
||||
if (data < 2) {
|
||||
data = 2;
|
||||
}
|
||||
// if (data < 2) {
|
||||
// data = 2;
|
||||
// }
|
||||
|
||||
default:
|
||||
vs[j] = (char) ((id << 4) + data);
|
||||
return;
|
||||
@ -227,8 +232,8 @@ public class BukkitChunk_1_8 extends FaweChunk<Chunk> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> copy(boolean shallow) {
|
||||
BukkitChunk_1_8 copy = new BukkitChunk_1_8(getParent(), getX(), getZ());
|
||||
public CharFaweChunk<T> copy(boolean shallow) {
|
||||
CharFaweChunk<T> copy = (CharFaweChunk<T>) getParent().getChunk(getX(), getZ());
|
||||
if (shallow) {
|
||||
copy.ids = ids;
|
||||
copy.air = air;
|
@ -1,4 +1,4 @@
|
||||
package com.boydti.fawe.bukkit.v1_9;
|
||||
package com.boydti.fawe.example;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
@ -6,24 +6,26 @@ import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.Arrays;
|
||||
import org.bukkit.Bukkit;
|
||||
import org.bukkit.Chunk;
|
||||
|
||||
public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
|
||||
public abstract class IntFaweChunk<T> extends FaweChunk<T> {
|
||||
|
||||
private int[][] ids;
|
||||
|
||||
private short[] count;
|
||||
private short[] air;
|
||||
private short[] relight;
|
||||
public int[][] biomes;
|
||||
private int[][] biomes;
|
||||
|
||||
public Chunk chunk;
|
||||
private T chunk;
|
||||
|
||||
/**
|
||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||
*
|
||||
* @param parent
|
||||
* @param x
|
||||
* @param z
|
||||
*/
|
||||
protected BukkitChunk_1_9(FaweQueue parent, int x, int z) {
|
||||
public IntFaweChunk(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
this.ids = new int[16][];
|
||||
this.count = new short[16];
|
||||
@ -32,13 +34,15 @@ public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Chunk getChunk() {
|
||||
public T getChunk() {
|
||||
if (this.chunk == null) {
|
||||
this.chunk = Bukkit.getWorld(getParent().world).getChunkAt(getX(), getZ());
|
||||
this.chunk = getNewChunk();
|
||||
}
|
||||
return this.chunk;
|
||||
}
|
||||
|
||||
public abstract T getNewChunk();
|
||||
|
||||
@Override
|
||||
public void setLoc(final FaweQueue parent, int x, int z) {
|
||||
super.setLoc(parent, x, z);
|
||||
@ -197,6 +201,7 @@ public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
|
||||
vs[j] = (id);
|
||||
return;
|
||||
case 130:
|
||||
case 50:
|
||||
case 76:
|
||||
case 62:
|
||||
this.relight[i]++;
|
||||
@ -205,9 +210,9 @@ public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
|
||||
case 61:
|
||||
case 65:
|
||||
case 68:
|
||||
if (data < 2) {
|
||||
data = 2;
|
||||
}
|
||||
// if (data < 2) {
|
||||
// data = 2;
|
||||
// }
|
||||
default:
|
||||
vs[j] = id + (data << 12);
|
||||
return;
|
||||
@ -227,8 +232,8 @@ public class BukkitChunk_1_9 extends FaweChunk<Chunk> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> copy(boolean shallow) {
|
||||
BukkitChunk_1_9 copy = new BukkitChunk_1_9(getParent(), getX(), getZ());
|
||||
public IntFaweChunk<T> copy(boolean shallow) {
|
||||
IntFaweChunk<T> copy = (IntFaweChunk<T>) getParent().getChunk(getX(), getZ());
|
||||
if (shallow) {
|
||||
copy.ids = ids;
|
||||
copy.air = air;
|
283
core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java
Normal file
283
core/src/main/java/com/boydti/fawe/example/MappedFaweQueue.java
Normal file
@ -0,0 +1,283 @@
|
||||
package com.boydti.fawe.example;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
|
||||
public abstract class MappedFaweQueue<WORLD, CHUNK, SECTION> extends FaweQueue {
|
||||
|
||||
private WORLD impWorld;
|
||||
|
||||
/**
|
||||
* Map of chunks in the queue
|
||||
*/
|
||||
private ConcurrentHashMap<Long, FaweChunk> blocks = new ConcurrentHashMap<>();
|
||||
private LinkedBlockingDeque<FaweChunk> chunks = new LinkedBlockingDeque<>();
|
||||
|
||||
@Override
|
||||
public void optimize() {
|
||||
ArrayList<Thread> threads = new ArrayList<Thread>();
|
||||
for (final FaweChunk chunk : chunks) {
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
chunk.optimize();
|
||||
}
|
||||
});
|
||||
threads.add(thread);
|
||||
thread.start();
|
||||
}
|
||||
for (Thread thread : threads) {
|
||||
try {
|
||||
thread.join();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public MappedFaweQueue(final String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
public abstract WORLD getWorld(String world);
|
||||
|
||||
public abstract boolean isChunkLoaded(WORLD world, int x, int z);
|
||||
|
||||
public abstract boolean regenerateChunk(WORLD world, int x, int z);
|
||||
|
||||
public abstract void sendChunk(FaweChunk chunk);
|
||||
|
||||
public abstract boolean setComponents(FaweChunk fc);
|
||||
|
||||
@Override
|
||||
public abstract FaweChunk getChunk(int x, int z);
|
||||
|
||||
@Override
|
||||
public abstract boolean fixLighting(FaweChunk fc, boolean fixAll);
|
||||
|
||||
public abstract boolean loadChunk(WORLD world, int x, int z, boolean generate);
|
||||
|
||||
public abstract CHUNK getCachedChunk(WORLD world, int cx, int cz);
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(int x, int z) {
|
||||
return isChunkLoaded(getWorld(), x, z);
|
||||
};
|
||||
|
||||
public WORLD getWorld() {
|
||||
if (impWorld != null) {
|
||||
return impWorld;
|
||||
}
|
||||
return impWorld = getWorld(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(int x, int z) {
|
||||
return regenerateChunk(getWorld(), x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTask(int x, int z, Runnable runnable) {
|
||||
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
|
||||
FaweChunk result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x, z);
|
||||
result.addTask(runnable);
|
||||
FaweChunk previous = this.blocks.put(pair, result);
|
||||
if (previous == null) {
|
||||
chunks.add(result);
|
||||
return;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
}
|
||||
result.addTask(runnable);
|
||||
}
|
||||
|
||||
private FaweChunk lastWrappedChunk;
|
||||
private int lastX = Integer.MIN_VALUE;
|
||||
private int lastZ = Integer.MIN_VALUE;
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, short id, byte data) {
|
||||
if ((y > 255) || (y < 0)) {
|
||||
return false;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
if (cx != lastX || cz != lastZ) {
|
||||
lastX = cx;
|
||||
lastZ = cz;
|
||||
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
|
||||
lastWrappedChunk = this.blocks.get(pair);
|
||||
if (lastWrappedChunk == null) {
|
||||
lastWrappedChunk = this.getChunk(x >> 4, z >> 4);
|
||||
lastWrappedChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
FaweChunk previous = this.blocks.put(pair, lastWrappedChunk);
|
||||
if (previous == null) {
|
||||
chunks.add(lastWrappedChunk);
|
||||
return true;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
lastWrappedChunk = previous;
|
||||
}
|
||||
}
|
||||
lastWrappedChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int z, BaseBiome biome) {
|
||||
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
|
||||
FaweChunk result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x >> 4, z >> 4);
|
||||
FaweChunk previous = this.blocks.put(pair, result);
|
||||
if (previous != null) {
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
} else {
|
||||
chunks.add(result);
|
||||
}
|
||||
}
|
||||
result.setBiome(x & 15, z & 15, biome);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk next() {
|
||||
lastX = Integer.MIN_VALUE;
|
||||
lastZ = Integer.MIN_VALUE;
|
||||
try {
|
||||
if (this.blocks.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
synchronized (blocks) {
|
||||
FaweChunk chunk = chunks.poll();
|
||||
if (chunk != null) {
|
||||
blocks.remove(chunk.longHash());
|
||||
this.execute(chunk);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return chunks.size();
|
||||
}
|
||||
|
||||
private LinkedBlockingDeque<FaweChunk> toUpdate = new LinkedBlockingDeque<>();
|
||||
|
||||
public boolean execute(FaweChunk fc) {
|
||||
if (fc == null) {
|
||||
return false;
|
||||
}
|
||||
// Set blocks / entities / biome
|
||||
if (!this.setComponents(fc)) {
|
||||
return false;
|
||||
}
|
||||
fc.executeTasks();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.blocks.clear();
|
||||
this.chunks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(FaweChunk chunk) {
|
||||
FaweChunk previous = this.blocks.put(chunk.longHash(), (FaweChunk) chunk);
|
||||
if (previous != null) {
|
||||
chunks.remove(previous);
|
||||
}
|
||||
chunks.add((FaweChunk) chunk);
|
||||
}
|
||||
|
||||
public Collection<FaweChunk> sendChunk(Collection<FaweChunk> fcs) {
|
||||
for (final FaweChunk fc : fcs) {
|
||||
sendChunk(fc);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
public int lastChunkX = Integer.MIN_VALUE;
|
||||
public int lastChunkZ = Integer.MIN_VALUE;
|
||||
public int lastChunkY = Integer.MIN_VALUE;
|
||||
|
||||
private CHUNK lastChunk;
|
||||
private SECTION lastSection;
|
||||
|
||||
public SECTION getCachedSection(CHUNK chunk, int cy) {
|
||||
return (SECTION) lastChunk;
|
||||
}
|
||||
|
||||
public abstract int getCombinedId4Data(SECTION section, int x, int y, int z);
|
||||
|
||||
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||
@Override
|
||||
public void run(IntegerPair coord) {
|
||||
loadChunk(getWorld(), coord.x, coord.z, true);
|
||||
}
|
||||
};
|
||||
|
||||
long average = 0;
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
||||
if (y < 0 || y > 255) {
|
||||
return 0;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
int cy = y >> 4;
|
||||
if (cx != lastChunkX || cz != lastChunkZ) {
|
||||
lastChunkX = cx;
|
||||
lastChunkZ = cz;
|
||||
if (!isChunkLoaded(cx, cz)) {
|
||||
long start = System.currentTimeMillis();
|
||||
boolean sync = Thread.currentThread() == Fawe.get().getMainThread();
|
||||
if (sync) {
|
||||
loadChunk(getWorld(), cx, cz, true);
|
||||
} else if (Settings.CHUNK_WAIT > 0) {
|
||||
loadChunk.value = new IntegerPair(cx, cz);
|
||||
TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT);
|
||||
if (!isChunkLoaded(cx, cz)) {
|
||||
throw new FaweException.FaweChunkLoadException();
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
lastChunk = getCachedChunk(getWorld(), cx, cz);
|
||||
lastSection = getCachedSection(lastChunk, cy);
|
||||
} else if (cy != lastChunkY) {
|
||||
if (lastChunk == null) {
|
||||
return 0;
|
||||
}
|
||||
lastSection = getCachedSection(lastChunk, cy);
|
||||
}
|
||||
|
||||
if (lastSection == null) {
|
||||
return 0;
|
||||
}
|
||||
return getCombinedId4Data(lastSection, x, y, z);
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
package com.boydti.fawe.example;
|
||||
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
|
||||
public abstract class NMSMappedFaweQueue<WORLD, CHUNK, CHUNKSECTION, SECTION> extends MappedFaweQueue<WORLD, CHUNKSECTION, SECTION> {
|
||||
public NMSMappedFaweQueue(String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendChunk(final FaweChunk fc) {
|
||||
TaskManager.IMP.taskSyncSoon(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
|
||||
TaskManager.IMP.taskSyncNow(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
}
|
||||
CHUNK chunk = (CHUNK) fc.getChunk();
|
||||
refreshChunk(getWorld(), chunk);
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}, Settings.ASYNC_LIGHTING);
|
||||
}
|
||||
|
||||
public abstract void refreshChunk(WORLD world, CHUNK chunk);
|
||||
|
||||
@Override
|
||||
public abstract boolean setComponents(FaweChunk fc);
|
||||
|
||||
@Override
|
||||
public abstract boolean fixLighting(FaweChunk fc, boolean fixAll);
|
||||
}
|
@ -4,6 +4,7 @@ import com.boydti.fawe.object.changeset.FaweChangeSet;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.Vector;
|
||||
import com.sk89q.worldedit.blocks.BaseBlock;
|
||||
import com.sk89q.worldedit.blocks.BlockType;
|
||||
import com.sk89q.worldedit.extent.Extent;
|
||||
|
||||
@ -16,10 +17,99 @@ public class EditSessionWrapper {
|
||||
}
|
||||
|
||||
public int getHighestTerrainBlock(final int x, final int z, final int minY, final int maxY, final boolean naturalOnly) {
|
||||
Vector pt = new Vector(x, 0, z);
|
||||
for (int y = maxY; y >= minY; --y) {
|
||||
final Vector pt = new Vector(x, y, z);
|
||||
final int id = this.session.getBlockType(pt);
|
||||
final int data = this.session.getBlockData(pt);
|
||||
BaseBlock block = session.getLazyBlock(x, y, z);
|
||||
final int id = block.getId();
|
||||
int data;
|
||||
switch (id) {
|
||||
case 0: {
|
||||
continue;
|
||||
}
|
||||
case 2:
|
||||
case 4:
|
||||
case 13:
|
||||
case 14:
|
||||
case 15:
|
||||
case 20:
|
||||
case 21:
|
||||
case 22:
|
||||
case 25:
|
||||
case 30:
|
||||
case 32:
|
||||
case 37:
|
||||
case 39:
|
||||
case 40:
|
||||
case 41:
|
||||
case 42:
|
||||
case 45:
|
||||
case 46:
|
||||
case 47:
|
||||
case 48:
|
||||
case 49:
|
||||
case 51:
|
||||
case 52:
|
||||
case 54:
|
||||
case 55:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 61:
|
||||
case 62:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
case 11:
|
||||
case 73:
|
||||
case 74:
|
||||
case 78:
|
||||
case 79:
|
||||
case 80:
|
||||
case 81:
|
||||
case 82:
|
||||
case 83:
|
||||
case 84:
|
||||
case 85:
|
||||
case 87:
|
||||
case 88:
|
||||
case 101:
|
||||
case 102:
|
||||
case 103:
|
||||
case 110:
|
||||
case 112:
|
||||
case 113:
|
||||
case 117:
|
||||
case 121:
|
||||
case 122:
|
||||
case 123:
|
||||
case 124:
|
||||
case 129:
|
||||
case 133:
|
||||
case 138:
|
||||
case 137:
|
||||
case 140:
|
||||
case 165:
|
||||
case 166:
|
||||
case 169:
|
||||
case 170:
|
||||
case 172:
|
||||
case 173:
|
||||
case 174:
|
||||
case 176:
|
||||
case 177:
|
||||
case 181:
|
||||
case 182:
|
||||
case 188:
|
||||
case 189:
|
||||
case 190:
|
||||
case 191:
|
||||
case 192:
|
||||
return y;
|
||||
default:
|
||||
data = 0;
|
||||
}
|
||||
if (naturalOnly ? BlockType.isNaturalTerrainBlock(id, data) : !BlockType.canPassThrough(id, data)) {
|
||||
return y;
|
||||
}
|
||||
|
@ -105,6 +105,8 @@ public abstract class FaweChunk<T> {
|
||||
|
||||
public abstract void setBiome(final int x, final int z, final BaseBiome biome);
|
||||
|
||||
public void optimize() {}
|
||||
|
||||
@Override
|
||||
public boolean equals(final Object obj) {
|
||||
if ((obj == null) || obj.hashCode() != hashCode() || !(obj instanceof FaweChunk)) {
|
||||
|
@ -172,7 +172,7 @@ public abstract class FawePlayer<T> {
|
||||
DiskStorageHistory set = new DiskStorageHistory(world, uuid, index);
|
||||
EditSession edit = set.toEditSession(getPlayer());
|
||||
if (world.equals(getWorld())) {
|
||||
session.remember(edit, 0);
|
||||
session.remember(edit, false);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
@ -26,6 +26,11 @@ public abstract class FaweClipboard {
|
||||
|
||||
public void setOrigin(Vector offset) {} // Do nothing
|
||||
|
||||
/**
|
||||
* The locations provided are relative to the clipboard min
|
||||
* @param task
|
||||
* @param air
|
||||
*/
|
||||
public abstract void forEach(final RunnableVal2<Vector,BaseBlock> task, boolean air);
|
||||
|
||||
/**
|
||||
|
@ -24,6 +24,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
||||
|
||||
// x,z,y+15>>4 | y&15
|
||||
private final byte[][] ids;
|
||||
private final byte[] heights;
|
||||
private byte[][] datas;
|
||||
private final HashMap<IntegerTrio, CompoundTag> nbtMap;
|
||||
private final HashSet<ClipboardEntity> entities;
|
||||
@ -33,6 +34,10 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
||||
this.height = height;
|
||||
this.length = length;
|
||||
this.area = width * length;
|
||||
heights = new byte[(height + 15) >> 4];
|
||||
for (int y = 0; y < ((height + 15) >> 4); y++) {
|
||||
heights[y] = (byte) Math.min(16, height - (y << 4));
|
||||
}
|
||||
ids = new byte[width * length * ((height + 15) >> 4)][];
|
||||
nbtMap = new HashMap<>();
|
||||
entities = new HashSet<>();
|
||||
@ -186,7 +191,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
||||
int y2 = y & 0xF;
|
||||
byte[] idArray = ids[i];
|
||||
if (idArray == null) {
|
||||
idArray = new byte[16];
|
||||
idArray = new byte[heights[ylast >> 4]];
|
||||
ids[i] = idArray;
|
||||
}
|
||||
idArray[y2] = (byte) id;
|
||||
@ -200,7 +205,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
||||
}
|
||||
byte[] dataArray = datas[i];
|
||||
if (dataArray == null) {
|
||||
dataArray = datas[i] = new byte[16];
|
||||
dataArray = datas[i] = new byte[heights[ylast >> 4]];
|
||||
}
|
||||
dataArray[y2] = (byte) data;
|
||||
}
|
||||
@ -275,7 +280,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
||||
int y2 = y & 0xF;
|
||||
byte[] idArray = ids[i];
|
||||
if (idArray == null) {
|
||||
idArray = new byte[16];
|
||||
idArray = new byte[heights[ylast >> 4]];
|
||||
ids[i] = idArray;
|
||||
}
|
||||
idArray[y2] = (byte) id;
|
||||
@ -286,7 +291,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
||||
int y2 = y & 0xF;
|
||||
byte[] idArray = ids[i];
|
||||
if (idArray == null) {
|
||||
idArray = new byte[16];
|
||||
idArray = new byte[heights[ylast >> 4]];
|
||||
ids[i] = idArray;
|
||||
}
|
||||
idArray[y2] = (byte) id;
|
||||
@ -299,7 +304,7 @@ public class MemoryOptimizedClipboard extends FaweClipboard {
|
||||
}
|
||||
byte[] dataArray = datas[i];
|
||||
if (dataArray == null) {
|
||||
dataArray = datas[i] = new byte[16];
|
||||
dataArray = datas[i] = new byte[heights[ylast >> 4]];
|
||||
}
|
||||
dataArray[y2] = (byte) data;
|
||||
return true;
|
||||
|
@ -29,12 +29,14 @@ public class FastWorldEditExtent extends FaweExtent {
|
||||
|
||||
@Override
|
||||
public Entity createEntity(final Location location, final BaseEntity entity) {
|
||||
if (entity != null) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
FastWorldEditExtent.super.createEntity(location, entity);
|
||||
}
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -47,7 +47,7 @@ public class ProcessedWEExtent extends FaweExtent {
|
||||
|
||||
@Override
|
||||
public Entity createEntity(final Location location, final BaseEntity entity) {
|
||||
if (limit.MAX_ENTITIES-- < 0) {
|
||||
if (limit.MAX_ENTITIES-- < 0 || entity == null) {
|
||||
return null;
|
||||
}
|
||||
if (WEManager.IMP.maskContains(this.mask, location.getBlockX(), location.getBlockZ())) {
|
||||
@ -227,13 +227,10 @@ public class ProcessedWEExtent extends FaweExtent {
|
||||
case 49:
|
||||
case 51:
|
||||
case 52:
|
||||
case 54:
|
||||
case 56:
|
||||
case 57:
|
||||
case 58:
|
||||
case 60:
|
||||
case 61:
|
||||
case 62:
|
||||
case 7:
|
||||
case 8:
|
||||
case 9:
|
||||
|
@ -0,0 +1,275 @@
|
||||
package com.boydti.fawe.object.io;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* ch-commons-util
|
||||
* %%
|
||||
* Copyright (C) 2012 Cloudhopper by Twitter
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.io.Writer;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Originally found here: http://www.java2s.com/Code/Java/File-Input-Output/AspeedyimplementationofByteArrayOutputStream.htm
|
||||
*
|
||||
* A speedy implementation of ByteArrayOutputStream. It's not synchronized, and it
|
||||
* does not copy buffers when it's expanded. There's also no copying of the internal buffer
|
||||
* if it's contents is extracted with the writeTo(stream) method.
|
||||
*
|
||||
* @author Rickard berg
|
||||
* @author Brat Baker (Atlassian)
|
||||
* @author Alexey
|
||||
* @version $Date: 2008-01-19 10:09:56 +0800 (Sat, 19 Jan 2008) $ $Id: FastByteArrayOutputStream.java 3000 2008-01-19 02:09:56Z tm_jee $
|
||||
*/
|
||||
public class FastByteArrayOutputStream extends OutputStream {
|
||||
|
||||
// Static --------------------------------------------------------
|
||||
private static final int DEFAULT_BLOCK_SIZE = 16384;
|
||||
private LinkedList<byte[]> buffers;
|
||||
// Attributes ----------------------------------------------------
|
||||
// internal buffer
|
||||
private byte[] buffer;
|
||||
// is the stream closed?
|
||||
private boolean closed;
|
||||
private int blockSize;
|
||||
private int index;
|
||||
private int size;
|
||||
|
||||
// Constructors --------------------------------------------------
|
||||
public FastByteArrayOutputStream() {
|
||||
this(DEFAULT_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
public FastByteArrayOutputStream(int aSize) {
|
||||
blockSize = aSize;
|
||||
buffer = new byte[blockSize];
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return size + index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
closed = true;
|
||||
}
|
||||
|
||||
public byte[] toByteArray() {
|
||||
byte[] data = new byte[getSize()];
|
||||
|
||||
// Check if we have a list of buffers
|
||||
int pos = 0;
|
||||
|
||||
if (buffers != null) {
|
||||
Iterator iter = buffers.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
byte[] bytes = (byte[])iter.next();
|
||||
System.arraycopy(bytes, 0, data, pos, blockSize);
|
||||
pos += blockSize;
|
||||
}
|
||||
}
|
||||
|
||||
// write the internal buffer directly
|
||||
System.arraycopy(buffer, 0, data, pos, index);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new String(toByteArray());
|
||||
}
|
||||
|
||||
// OutputStream overrides ----------------------------------------
|
||||
public void write(int datum) throws IOException {
|
||||
if (closed) {
|
||||
throw new IOException("Stream closed");
|
||||
} else {
|
||||
if (index == blockSize) {
|
||||
addBuffer();
|
||||
}
|
||||
|
||||
// store the byte
|
||||
buffer[index++] = (byte) datum;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] data, int offset, int length) throws IOException {
|
||||
if (data == null) {
|
||||
throw new NullPointerException();
|
||||
} else if ((offset < 0) || ((offset + length) > data.length) || (length < 0)) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
} else if (closed) {
|
||||
throw new IOException("Stream closed");
|
||||
} else {
|
||||
if ((index + length) > blockSize) {
|
||||
int copyLength;
|
||||
|
||||
do {
|
||||
if (index == blockSize) {
|
||||
addBuffer();
|
||||
}
|
||||
|
||||
copyLength = blockSize - index;
|
||||
|
||||
if (length < copyLength) {
|
||||
copyLength = length;
|
||||
}
|
||||
|
||||
System.arraycopy(data, offset, buffer, index, copyLength);
|
||||
offset += copyLength;
|
||||
index += copyLength;
|
||||
length -= copyLength;
|
||||
} while (length > 0);
|
||||
} else {
|
||||
// Copy in the subarray
|
||||
System.arraycopy(data, offset, buffer, index, length);
|
||||
index += length;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Public
|
||||
public void writeTo(OutputStream out) throws IOException {
|
||||
// Check if we have a list of buffers
|
||||
if (buffers != null) {
|
||||
Iterator iter = buffers.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
byte[] bytes = (byte[]) iter.next();
|
||||
out.write(bytes, 0, blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
// write the internal buffer directly
|
||||
out.write(buffer, 0, index);
|
||||
}
|
||||
|
||||
public void writeTo(RandomAccessFile out) throws IOException {
|
||||
// Check if we have a list of buffers
|
||||
if (buffers != null) {
|
||||
Iterator iter = buffers.iterator();
|
||||
|
||||
while (iter.hasNext()) {
|
||||
byte[] bytes = (byte[]) iter.next();
|
||||
out.write(bytes, 0, blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
// write the internal buffer directly
|
||||
out.write(buffer, 0, index);
|
||||
}
|
||||
|
||||
public void writeTo(Writer out, String encoding) throws IOException {
|
||||
/*
|
||||
There is design tradeoff between being fast, correct and using too much memory when decoding bytes to strings.
|
||||
|
||||
The rules are thus :
|
||||
|
||||
1. if there is only one buffer then its a simple String conversion
|
||||
|
||||
REASON : Fast!!!
|
||||
|
||||
2. uses full buffer allocation annd System.arrayCopy() to smooosh together the bytes
|
||||
and then use String conversion
|
||||
|
||||
REASON : Fast at the expense of a known amount of memory (eg the used memory * 2)
|
||||
*/
|
||||
if (buffers != null) {
|
||||
// RULE 2 : a balance between using some memory and speed
|
||||
writeToViaSmoosh(out, encoding);
|
||||
} else {
|
||||
// RULE 1 : fastest!
|
||||
writeToViaString(out, encoding);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This can <b>ONLY</b> be called if there is only a single buffer to write, instead
|
||||
* use {@link #writeTo(java.io.Writer, String)}, which auto detects if
|
||||
* {@link #writeToViaString(java.io.Writer, String)} is to be used or
|
||||
* {@link #writeToViaSmoosh(java.io.Writer, String)}.
|
||||
*
|
||||
* @param out the JspWriter
|
||||
* @param encoding the encoding
|
||||
* @throws IOException
|
||||
*/
|
||||
void writeToViaString(Writer out, String encoding) throws IOException {
|
||||
byte[] bufferToWrite = buffer; // this is always the last buffer to write
|
||||
int bufferToWriteLen = index; // index points to our place in the last buffer
|
||||
writeToImpl(out, encoding, bufferToWrite, bufferToWriteLen);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is recommended to be used where there's more than 1 buffer to write, instead
|
||||
* use {@link #writeTo(java.io.Writer, String)} which auto detects if
|
||||
* {@link #writeToViaString(java.io.Writer, String)} is to be used or
|
||||
* {@link #writeToViaSmoosh(java.io.Writer, String)}.
|
||||
*
|
||||
* @param out
|
||||
* @param encoding
|
||||
* @throws IOException
|
||||
*/
|
||||
void writeToViaSmoosh(Writer out, String encoding) throws IOException {
|
||||
byte[] bufferToWrite = toByteArray();
|
||||
int bufferToWriteLen = bufferToWrite.length;
|
||||
writeToImpl(out, encoding, bufferToWrite, bufferToWriteLen);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write <code>bufferToWriteLen</code> of bytes from <code>bufferToWrite</code> to
|
||||
* <code>out</code> encoding it at the same time.
|
||||
*
|
||||
* @param out
|
||||
* @param encoding
|
||||
* @param bufferToWrite
|
||||
* @param bufferToWriteLen
|
||||
* @throws IOException
|
||||
*/
|
||||
private void writeToImpl(Writer out, String encoding, byte[] bufferToWrite, int bufferToWriteLen)
|
||||
throws IOException {
|
||||
String writeStr;
|
||||
if (encoding != null) {
|
||||
writeStr = new String(bufferToWrite, 0, bufferToWriteLen, encoding);
|
||||
} else {
|
||||
writeStr = new String(bufferToWrite, 0, bufferToWriteLen);
|
||||
}
|
||||
out.write(writeStr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new buffer and store the
|
||||
* current one in linked list
|
||||
*/
|
||||
protected void addBuffer() {
|
||||
if (buffers == null) {
|
||||
buffers = new LinkedList<byte[]>();
|
||||
}
|
||||
|
||||
buffers.addLast(buffer);
|
||||
|
||||
buffer = new byte[blockSize];
|
||||
size += index;
|
||||
index = 0;
|
||||
}
|
||||
}
|
@ -34,6 +34,8 @@ public abstract class FaweQueue {
|
||||
return sessions == null ? new HashSet<EditSession>() : new HashSet<>(sessions);
|
||||
}
|
||||
|
||||
public void optimize() {}
|
||||
|
||||
public abstract boolean setBlock(final int x, final int y, final int z, final short id, final byte data);
|
||||
|
||||
public abstract boolean setBiome(final int x, final int z, final BaseBiome biome);
|
||||
|
@ -108,6 +108,7 @@ public class SetQueue {
|
||||
public void enqueue(FaweQueue queue) {
|
||||
inactiveQueues.remove(queue);
|
||||
if (queue.size() > 0 && !activeQueues.contains(queue)) {
|
||||
queue.optimize();
|
||||
activeQueues.add(queue);
|
||||
}
|
||||
}
|
||||
@ -132,8 +133,8 @@ public class SetQueue {
|
||||
return new ArrayList<>(inactiveQueues);
|
||||
}
|
||||
|
||||
public FaweQueue getNewQueue(String world, boolean autoqueue) {
|
||||
FaweQueue queue = Fawe.imp().getNewQueue(world);
|
||||
public FaweQueue getNewQueue(String world, boolean fast, boolean autoqueue) {
|
||||
FaweQueue queue = Fawe.imp().getNewQueue(world, fast);
|
||||
if (autoqueue) {
|
||||
inactiveQueues.add(queue);
|
||||
}
|
||||
@ -155,10 +156,8 @@ public class SetQueue {
|
||||
if (Settings.QUEUE_MAX_WAIT >= 0) {
|
||||
long now = System.currentTimeMillis();
|
||||
if (lastSuccess != 0) {
|
||||
long diff = now - lastSuccess;
|
||||
if (diff > Settings.QUEUE_MAX_WAIT) {
|
||||
for (FaweQueue queue : tmp) {
|
||||
if (queue != null && queue.size() > 0) {
|
||||
if (queue != null && queue.size() > 0 && now - queue.modified > Settings.QUEUE_MAX_WAIT) {
|
||||
queue.modified = now;
|
||||
return queue;
|
||||
} else if (now - queue.modified > Settings.QUEUE_DISCARD_AFTER) {
|
||||
@ -168,7 +167,6 @@ public class SetQueue {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Settings.QUEUE_SIZE != -1) {
|
||||
int total = 0;
|
||||
for (FaweQueue queue : tmp) {
|
||||
|
@ -39,12 +39,12 @@ public abstract class TaskManager {
|
||||
public abstract void task(final Runnable r);
|
||||
|
||||
/**
|
||||
* Run a task on either the main thread or asynchronously
|
||||
* Run a task on the current thread or asynchronously
|
||||
* - If it's already the main thread, it will jst call run()
|
||||
* @param r
|
||||
* @param async
|
||||
*/
|
||||
public void task(final Runnable r, boolean async) {
|
||||
public void taskNow(final Runnable r, boolean async) {
|
||||
if (async) {
|
||||
async(r);
|
||||
} else {
|
||||
@ -52,7 +52,12 @@ public abstract class TaskManager {
|
||||
}
|
||||
}
|
||||
|
||||
public void sync(final Runnable r, boolean async) {
|
||||
/**
|
||||
* Run a task as soon as possible on the main thread, or now async
|
||||
* @param r
|
||||
* @param async
|
||||
*/
|
||||
public void taskSyncNow(final Runnable r, boolean async) {
|
||||
if (async) {
|
||||
async(r);
|
||||
} else if (r != null && Thread.currentThread() == Fawe.get().getMainThread()){
|
||||
@ -62,6 +67,19 @@ public abstract class TaskManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run a task on the main thread at the next tick or now async
|
||||
* @param r
|
||||
* @param async
|
||||
*/
|
||||
public void taskSyncSoon(final Runnable r, boolean async) {
|
||||
if (async) {
|
||||
async(r);
|
||||
} else {
|
||||
task(r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run a task later on the main thread
|
||||
|
@ -2,6 +2,7 @@ package com.boydti.fawe.wrappers;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.util.SetQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
import com.sk89q.worldedit.EditSessionFactory;
|
||||
@ -170,7 +171,7 @@ public class PlayerWrapper implements Player {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void floatAt(int x, int y, int z, boolean alwaysGlass) {
|
||||
public void floatAt(final int x, final int y, final int z, final boolean alwaysGlass) {
|
||||
EditSessionFactory factory = WorldEdit.getInstance().getEditSessionFactory();
|
||||
EditSession edit = factory.getEditSession(parent.getWorld(), -1, null, this);
|
||||
try {
|
||||
@ -182,8 +183,13 @@ public class PlayerWrapper implements Player {
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
SetQueue.IMP.addTask(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setPosition(new Vector(x + 0.5, y, z + 0.5));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldVector getBlockIn() {
|
||||
|
@ -234,8 +234,6 @@ public class EditSession implements Extent {
|
||||
this.wrapper = Fawe.imp().getEditSessionWrapper(this);
|
||||
return;
|
||||
}
|
||||
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true);
|
||||
queue.addEditSession(this);
|
||||
// Set the world of the event to the actual world (workaround for CoreProtect)
|
||||
try {
|
||||
Class<? extends EditSessionEvent> eventClass = event.getClass();
|
||||
@ -262,6 +260,8 @@ public class EditSession implements Extent {
|
||||
this.bypassHistory = extent;
|
||||
this.bypassNone = extent;
|
||||
this.changeSet = new NullChangeSet();
|
||||
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true);
|
||||
queue.addEditSession(this);
|
||||
return;
|
||||
}
|
||||
this.changeSet = Settings.STORE_HISTORY_ON_DISK ? new DiskStorageHistory(world, actor.getUniqueId()) : new MemoryOptimizedHistory(actor);
|
||||
@ -270,6 +270,8 @@ public class EditSession implements Extent {
|
||||
final LocalSession session = fp.getSession();
|
||||
this.fastmode = session.hasFastMode();
|
||||
if (fp.hasWorldEditBypass()) {
|
||||
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), true, true);
|
||||
queue.addEditSession(this);
|
||||
// Bypass skips processing and area restrictions
|
||||
extent = (this.faweExtent = new FastWorldEditExtent(world, queue));
|
||||
if (this.hasFastMode()) {
|
||||
@ -283,6 +285,8 @@ public class EditSession implements Extent {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
this.queue = SetQueue.IMP.getNewQueue(Fawe.imp().getWorldName(world), false, true);
|
||||
queue.addEditSession(this);
|
||||
this.limit = fp.getLimit();
|
||||
final HashSet<RegionWrapper> mask = WEManager.IMP.getMask(fp);
|
||||
if (mask.size() == 0) {
|
||||
@ -1533,21 +1537,31 @@ public class EditSession implements Extent {
|
||||
public int fixLiquid(final Vector origin, final double radius, final int moving, final int stationary) throws MaxChangedBlocksException {
|
||||
checkNotNull(origin);
|
||||
checkArgument(radius >= 0, "radius >= 0 required");
|
||||
|
||||
// Our origins can only be liquids
|
||||
final BlockMask liquidMask = new BlockMask(EditSession.this, new BaseBlock(moving, -1), new BaseBlock(stationary, -1));
|
||||
BlockMask liquidMask = new BlockMask(
|
||||
this,
|
||||
new BaseBlock(moving, -1),
|
||||
new BaseBlock(stationary, -1));
|
||||
|
||||
// But we will also visit air blocks
|
||||
final MaskIntersection blockMask = new MaskUnion(liquidMask, new BlockMask(EditSession.this, new BaseBlock(BlockID.AIR)));
|
||||
MaskIntersection blockMask =
|
||||
new MaskUnion(liquidMask,
|
||||
new BlockMask(
|
||||
this,
|
||||
new BaseBlock(BlockID.AIR)));
|
||||
|
||||
// There are boundaries that the routine needs to stay in
|
||||
final MaskIntersection mask = new MaskIntersection(new BoundedHeightMask(0, Math.min(origin.getBlockY(), EditSession.this.getWorld().getMaxY())), new RegionMask(new EllipsoidRegion(
|
||||
null, origin, new Vector(radius, radius, radius))), blockMask);
|
||||
MaskIntersection mask = new MaskIntersection(
|
||||
new BoundedHeightMask(0, Math.min(origin.getBlockY(), getWorld().getMaxY())),
|
||||
new RegionMask(new EllipsoidRegion(null, origin, new Vector(radius, radius, radius))),
|
||||
blockMask);
|
||||
|
||||
final BlockReplace replace = new BlockReplace(EditSession.this, new BlockPattern(new BaseBlock(stationary)));
|
||||
final NonRisingVisitor visitor = new NonRisingVisitor(mask, replace);
|
||||
BlockReplace replace = new BlockReplace(this, new BlockPattern(new BaseBlock(stationary)));
|
||||
NonRisingVisitor visitor = new NonRisingVisitor(mask, replace);
|
||||
|
||||
// Around the origin in a 3x3 block
|
||||
for (final BlockVector position : CuboidRegion.fromCenter(origin, 1)) {
|
||||
for (BlockVector position : CuboidRegion.fromCenter(origin, 1)) {
|
||||
if (liquidMask.test(position)) {
|
||||
visitor.visit(position);
|
||||
}
|
||||
@ -1559,7 +1573,7 @@ public class EditSession implements Extent {
|
||||
EditSession.this.flushQueue();
|
||||
}
|
||||
}, true);
|
||||
return this.changes = visitor.getAffected();
|
||||
return visitor.getAffected();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -52,8 +52,10 @@ import com.sk89q.worldedit.session.request.Request;
|
||||
import com.sk89q.worldedit.world.World;
|
||||
import com.sk89q.worldedit.world.snapshot.Snapshot;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.TimeZone;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@ -76,7 +78,7 @@ public class LocalSession {
|
||||
// Session related
|
||||
private transient RegionSelector selector = new CuboidRegionSelector();
|
||||
private transient boolean placeAtPos1 = false;
|
||||
private transient LinkedList<EditSession> history = new LinkedList<EditSession>();
|
||||
private transient List<EditSession> history = Collections.synchronizedList(new LinkedList<EditSession>());
|
||||
private transient int historyPointer = 0;
|
||||
private transient ClipboardHolder clipboard;
|
||||
private transient boolean toolControl = true;
|
||||
@ -194,10 +196,10 @@ public class LocalSession {
|
||||
* @param editSession the edit session
|
||||
*/
|
||||
public void remember(EditSession editSession) {
|
||||
remember(editSession, history.size());
|
||||
remember(editSession, true);
|
||||
}
|
||||
|
||||
public void remember(EditSession editSession, int index) {
|
||||
public void remember(EditSession editSession, boolean append) {
|
||||
// Enqueue it
|
||||
if (editSession.getQueue() != null) {
|
||||
FaweQueue queue = editSession.getQueue();
|
||||
@ -217,7 +219,11 @@ public class LocalSession {
|
||||
if (set instanceof FaweChangeSet) {
|
||||
((FaweChangeSet) set).flush();
|
||||
}
|
||||
history.add(Math.max(0, Math.min(index, history.size())), editSession);
|
||||
if (append) {
|
||||
history.add(editSession);
|
||||
} else {
|
||||
history.add(0, editSession);
|
||||
}
|
||||
while (history.size() > MAX_HISTORY_SIZE) {
|
||||
history.remove(0);
|
||||
}
|
||||
|
@ -46,12 +46,11 @@ import com.sk89q.worldedit.function.pattern.Pattern;
|
||||
import com.sk89q.worldedit.internal.annotation.Direction;
|
||||
import com.sk89q.worldedit.internal.annotation.Selection;
|
||||
import com.sk89q.worldedit.math.transform.AffineTransform;
|
||||
import com.sk89q.worldedit.math.transform.Transform;
|
||||
import com.sk89q.worldedit.regions.CuboidRegion;
|
||||
import com.sk89q.worldedit.regions.Region;
|
||||
import com.sk89q.worldedit.regions.RegionSelector;
|
||||
import com.sk89q.worldedit.regions.selector.CuboidRegionSelector;
|
||||
import com.sk89q.worldedit.session.ClipboardHolder;
|
||||
import com.sk89q.worldedit.util.Location;
|
||||
import com.sk89q.worldedit.util.command.binding.Switch;
|
||||
import com.sk89q.worldedit.util.command.parametric.Optional;
|
||||
import java.util.Iterator;
|
||||
@ -97,17 +96,18 @@ public class ClipboardCommands {
|
||||
@Selection final Region region, @Switch('e') boolean copyEntities,
|
||||
@Switch('m') Mask mask) throws WorldEditException {
|
||||
|
||||
Vector origin = region.getMinimumPoint();
|
||||
final Vector origin = region.getMinimumPoint();
|
||||
final int mx = origin.getBlockX();
|
||||
final int my = origin.getBlockY();
|
||||
final int mz = origin.getBlockZ();
|
||||
LazyClipboard lazyClipboard = new LazyClipboard() {
|
||||
@Override
|
||||
public BaseBlock getBlock(int x, int y, int z) {
|
||||
int xx = mx + x;
|
||||
int yy = my + y;
|
||||
int zz = mz + z;
|
||||
return editSession.getLazyBlock(xx, yy, zz);
|
||||
return editSession.getLazyBlock(mx + x, my + y, mz + z);
|
||||
}
|
||||
|
||||
public BaseBlock getBlockAbs(int x, int y, int z) {
|
||||
return editSession.getLazyBlock(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -120,10 +120,13 @@ public class ClipboardCommands {
|
||||
Iterator<BlockVector> iter = region.iterator();
|
||||
while (iter.hasNext()) {
|
||||
BlockVector pos = iter.next();
|
||||
BaseBlock block = getBlock((int) pos.x, (int) pos.y, (int) pos.z);
|
||||
BaseBlock block = getBlockAbs((int) pos.x, (int) pos.y, (int) pos.z);
|
||||
if (!air && block == EditSession.nullBlock) {
|
||||
continue;
|
||||
}
|
||||
pos.x -= mx;
|
||||
pos.y -= my;
|
||||
pos.z -= mz;
|
||||
task.run(pos, block);
|
||||
}
|
||||
}
|
||||
@ -269,29 +272,24 @@ public class ClipboardCommands {
|
||||
ClipboardHolder holder = session.getClipboard();
|
||||
Clipboard clipboard = holder.getClipboard();
|
||||
Region region = clipboard.getRegion().clone();
|
||||
Vector origin = clipboard.getOrigin();
|
||||
final Transform transform = holder.getTransform();
|
||||
// Optimize for CuboidRegion
|
||||
if (region instanceof CuboidRegion) {
|
||||
CuboidRegion cuboid = (CuboidRegion) region;
|
||||
Vector min = cuboid.getMinimumPoint();
|
||||
origin = origin.subtract(cuboid.getMinimumPoint());
|
||||
cuboid.setPos2(cuboid.getMaximumPoint().subtract(min));
|
||||
cuboid.setPos1(new Vector(0, 0, 0));
|
||||
}
|
||||
Vector to = atOrigin ? origin : session.getPlacementPosition(player);
|
||||
final int tx = to.getBlockX() - origin.getBlockX();
|
||||
final int ty = to.getBlockY() - origin.getBlockY();
|
||||
final int tz = to.getBlockZ() - origin.getBlockZ();
|
||||
|
||||
|
||||
final Vector bot = clipboard.getMinimumPoint();
|
||||
final Vector origin = clipboard.getOrigin();
|
||||
final Vector to = atOrigin ? origin : session.getPlacementPosition(player);
|
||||
// Optimize for BlockArrayClipboard
|
||||
if (clipboard instanceof BlockArrayClipboard) {
|
||||
// To is relative to the world origin (player loc + small clipboard offset) (As the positions supplied are relative to the clipboard min)
|
||||
final int relx = to.getBlockX() + bot.getBlockX() - origin.getBlockX();
|
||||
final int rely = to.getBlockY() + bot.getBlockY() - origin.getBlockY();
|
||||
final int relz = to.getBlockZ() + bot.getBlockZ() - origin.getBlockZ();
|
||||
BlockArrayClipboard bac = (BlockArrayClipboard) clipboard;
|
||||
bac.IMP.forEach(new RunnableVal2<Vector, BaseBlock>() {
|
||||
@Override
|
||||
public void run(Vector pos, BaseBlock block) {
|
||||
pos.x += tx;
|
||||
pos.y += ty;
|
||||
pos.z += tz;
|
||||
pos.x += relx;
|
||||
pos.y += rely;
|
||||
pos.z += relz;
|
||||
try {
|
||||
editSession.setBlock(pos, block);
|
||||
} catch (MaxChangedBlocksException e) {
|
||||
@ -300,7 +298,10 @@ public class ClipboardCommands {
|
||||
}
|
||||
}, !ignoreAirBlocks);
|
||||
} else {
|
||||
// Generic optimization for unknown region type
|
||||
// To must be relative to the clipboard origin ( player location - clipboard origin ) (as the locations supplied are relative to the world origin)
|
||||
final int relx = to.getBlockX() - origin.getBlockX();
|
||||
final int rely = to.getBlockY() - origin.getBlockY();
|
||||
final int relz = to.getBlockZ() - origin.getBlockZ();
|
||||
Iterator<BlockVector> iter = region.iterator();
|
||||
while (iter.hasNext()) {
|
||||
BlockVector loc = iter.next();
|
||||
@ -308,15 +309,21 @@ public class ClipboardCommands {
|
||||
if (block == EditSession.nullBlock && ignoreAirBlocks) {
|
||||
continue;
|
||||
}
|
||||
loc.x += tx;
|
||||
loc.y += ty;
|
||||
loc.z += tz;
|
||||
editSession.setBlock(transform.apply(loc), block);
|
||||
loc.x += relx;
|
||||
loc.y += rely;
|
||||
loc.z += relz;
|
||||
editSession.setBlock(loc, block);
|
||||
}
|
||||
}
|
||||
// Entity offset is the paste location subtract the clipboard origin (entity's location is already relative to the world origin)
|
||||
final int entityOffsetX = to.getBlockX() - origin.getBlockX();
|
||||
final int entityOffsetY = to.getBlockY() - origin.getBlockY();
|
||||
final int entityOffsetZ = to.getBlockZ() - origin.getBlockZ();
|
||||
// entities
|
||||
for (Entity entity : clipboard.getEntities()) {
|
||||
editSession.createEntity(entity.getLocation(), entity.getState());
|
||||
Location pos = entity.getLocation();
|
||||
Location newPos = new Location(pos.getExtent(), pos.getX() + entityOffsetX, pos.getY() + entityOffsetY, pos.getZ() + entityOffsetZ, pos.getYaw(), pos.getPitch());
|
||||
editSession.createEntity(newPos, entity.getState());
|
||||
}
|
||||
if (selectPasted) {
|
||||
Vector max = to.add(region.getMaximumPoint().subtract(region.getMinimumPoint()));
|
||||
|
@ -122,6 +122,7 @@ public class SelectionCommand extends SimpleCommand<Operation> {
|
||||
final byte data = (byte) block.getData();
|
||||
final FaweChunk<?> fc = queue.getChunk(0, 0);
|
||||
fc.fillCuboid(0, 15, minY, maxY, 0, 15, id, data);
|
||||
fc.optimize();
|
||||
|
||||
int bcx = (current.minX) >> 4;
|
||||
int bcz = (current.minZ) >> 4;
|
||||
|
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* WorldEdit, a Minecraft world manipulation toolkit
|
||||
* Copyright (C) sk89q <http://www.sk89q.com>
|
||||
* Copyright (C) WorldEdit team and contributors
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify it
|
||||
* under the terms of the GNU Lesser General Public License as published by the
|
||||
* Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.sk89q.worldedit.function.operation;
|
||||
|
||||
import com.sk89q.worldedit.WorldEditException;
|
||||
import com.sk89q.worldedit.history.UndoContext;
|
||||
import com.sk89q.worldedit.history.change.Change;
|
||||
import com.sk89q.worldedit.history.changeset.ChangeSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
/**
|
||||
* Performs an undo or redo from a given {@link ChangeSet}.
|
||||
*/
|
||||
public class ChangeSetExecutor implements Operation {
|
||||
|
||||
public enum Type {UNDO, REDO}
|
||||
|
||||
private final Iterator<Change> iterator;
|
||||
private final Type type;
|
||||
private final UndoContext context;
|
||||
|
||||
/**
|
||||
* Create a new instance.
|
||||
*
|
||||
* @param changeSet the change set
|
||||
* @param type type of change
|
||||
* @param context the undo context
|
||||
*/
|
||||
private ChangeSetExecutor(ChangeSet changeSet, Type type, UndoContext context) {
|
||||
checkNotNull(changeSet);
|
||||
checkNotNull(type);
|
||||
checkNotNull(context);
|
||||
this.type = type;
|
||||
this.context = context;
|
||||
if (type == Type.UNDO) {
|
||||
iterator = changeSet.backwardIterator();
|
||||
} else {
|
||||
iterator = changeSet.forwardIterator();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Operation resume(RunContext run) throws WorldEditException {
|
||||
int size = 0;
|
||||
if (type == Type.UNDO) {
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next().undo(context);
|
||||
}
|
||||
} else {
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next().redo(context);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addStatusMessages(List<String> messages) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new undo operation.
|
||||
*
|
||||
* @param changeSet the change set
|
||||
* @param context an undo context
|
||||
* @return an operation
|
||||
*/
|
||||
public static ChangeSetExecutor createUndo(ChangeSet changeSet, UndoContext context) {
|
||||
return new ChangeSetExecutor(changeSet, Type.UNDO, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new redo operation.
|
||||
*
|
||||
* @param changeSet the change set
|
||||
* @param context an undo context
|
||||
* @return an operation
|
||||
*/
|
||||
public static ChangeSetExecutor createRedo(ChangeSet changeSet, UndoContext context) {
|
||||
return new ChangeSetExecutor(changeSet, Type.REDO, context);
|
||||
}
|
||||
|
||||
}
|
@ -53,13 +53,7 @@ public final class Operations {
|
||||
* @throws MaxChangedBlocksException thrown when too many blocks have been changed
|
||||
*/
|
||||
public static void completeLegacy(Operation operation) throws MaxChangedBlocksException {
|
||||
try {
|
||||
while (true) {
|
||||
operation = operation.resume(context);
|
||||
}
|
||||
} catch (final WorldEditException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NullPointerException ignore) {}
|
||||
completeBlindly(operation);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -113,7 +113,7 @@ public class FaweForge implements IFawe {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world) {
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
|
@ -197,15 +197,16 @@ public class ForgeChunk_All extends FaweChunk<Chunk> {
|
||||
case 130:
|
||||
case 76:
|
||||
case 62:
|
||||
case 50:
|
||||
this.relight[i]++;
|
||||
case 54:
|
||||
case 146:
|
||||
case 61:
|
||||
case 65:
|
||||
case 68:
|
||||
if (data < 2) {
|
||||
data = 2;
|
||||
}
|
||||
// if (data < 2) {
|
||||
// data = 2;
|
||||
// }
|
||||
default:
|
||||
vs[j] = (byte) id;
|
||||
NibbleArray dataArray = datas[i];
|
||||
|
@ -2,24 +2,18 @@ package com.boydti.fawe.forge.v0;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.forge.ForgePlayer;
|
||||
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.object.RunnableVal;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.network.NetHandlerPlayServer;
|
||||
@ -38,39 +32,55 @@ import net.minecraft.world.chunk.NibbleArray;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
|
||||
public class ForgeQueue_All extends FaweQueue {
|
||||
|
||||
private World forgeWorld;
|
||||
|
||||
private ConcurrentHashMap<Long, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
|
||||
private LinkedBlockingDeque<FaweChunk<Chunk>> chunks = new LinkedBlockingDeque<>();
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, ExtendedBlockStorage> {
|
||||
|
||||
public ForgeQueue_All(final String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(int x, int z) {
|
||||
return getWorld().getChunkProvider().chunkExists(x, z);
|
||||
public boolean loadChunk(World world, int x, int z, boolean generate) {
|
||||
return getCachedChunk(world, x, z) != null;
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
if (forgeWorld != null) {
|
||||
return forgeWorld;
|
||||
@Override
|
||||
public Chunk getCachedChunk(World world, int cx, int cz) {
|
||||
Chunk chunk = world.getChunkProvider().provideChunk(cx, cz);
|
||||
if (chunk != null && !chunk.isChunkLoaded) {
|
||||
chunk.onChunkLoad();
|
||||
}
|
||||
return chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(ExtendedBlockStorage ls, int x, int y, int z) {
|
||||
byte[] ids = ls.getBlockLSBArray();
|
||||
NibbleArray datasNibble = ls.getBlockMSBArray();
|
||||
int i = FaweCache.CACHE_J[y & 15][x & 15][z & 15];
|
||||
int combined = (ids[i] << 4) + (datasNibble == null ? 0 : datasNibble.get(x & 15, y & 15, z & 15));
|
||||
return combined;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(World world, int x, int z) {
|
||||
return world.getChunkProvider().chunkExists(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld(String world) {
|
||||
WorldServer[] worlds = MinecraftServer.getServer().worldServers;
|
||||
for (WorldServer ws : worlds) {
|
||||
if (ws.provider.getDimensionName().equals(world)) {
|
||||
return forgeWorld = ws;
|
||||
return ws;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(int x, int z) {
|
||||
public boolean regenerateChunk(World world, int x, int z) {
|
||||
try {
|
||||
IChunkProvider provider = getWorld().getChunkProvider();
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
@ -88,7 +98,7 @@ public class ForgeQueue_All extends FaweQueue {
|
||||
u = ChunkProviderServer.class.getDeclaredField("chunksToUnload");
|
||||
}
|
||||
u.setAccessible(true);
|
||||
Set<?> unloadQueue = (Set<?>) u.get(chunkServer);
|
||||
Set unloadQueue = (Set) u.get(chunkServer);
|
||||
Field m;
|
||||
try {
|
||||
m = ChunkProviderServer.class.getDeclaredField("field_73244_f"); // loadedChunkHashMap
|
||||
@ -104,7 +114,7 @@ public class ForgeQueue_All extends FaweQueue {
|
||||
lc = ChunkProviderServer.class.getDeclaredField("loadedChunks");
|
||||
}
|
||||
lc.setAccessible(true);
|
||||
@SuppressWarnings("unchecked") List<Chunk> loaded = (List<Chunk>) lc.get(chunkServer);
|
||||
@SuppressWarnings("unchecked") List loaded = (List) lc.get(chunkServer);
|
||||
Field p;
|
||||
try {
|
||||
p = ChunkProviderServer.class.getDeclaredField("field_73246_d"); // currentChunkProvider
|
||||
@ -134,30 +144,6 @@ public class ForgeQueue_All extends FaweQueue {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTask(int x, int z, Runnable runnable) {
|
||||
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x, z);
|
||||
result.addTask(runnable);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous == null) {
|
||||
chunks.add(result);
|
||||
return;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
}
|
||||
result.addTask(runnable);
|
||||
}
|
||||
|
||||
private int lcx = Integer.MIN_VALUE;
|
||||
private int lcz = Integer.MIN_VALUE;
|
||||
private int lcy = Integer.MIN_VALUE;
|
||||
private net.minecraft.world.chunk.Chunk lc;
|
||||
private ExtendedBlockStorage ls;
|
||||
|
||||
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||
@Override
|
||||
public void run(IntegerPair loc) {
|
||||
@ -170,182 +156,10 @@ public class ForgeQueue_All extends FaweQueue {
|
||||
};
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
||||
if (y < 0 || y > 255) {
|
||||
return 0;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
int cy = y >> 4;
|
||||
if (cx != lcx || cz != lcz) {
|
||||
World world = getWorld();
|
||||
lcx = cx;
|
||||
lcz = cz;
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
Chunk chunk;
|
||||
if (!provider.chunkExists(cx, cz)) {
|
||||
boolean sync = Thread.currentThread() == Fawe.get().getMainThread();
|
||||
if (sync) {
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
} else if (Settings.CHUNK_WAIT > 0) {
|
||||
loadChunk.value = new IntegerPair(cx, cz);
|
||||
TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT);
|
||||
if (!provider.chunkExists(cx, cz)) {
|
||||
throw new FaweException.FaweChunkLoadException();
|
||||
}
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
}
|
||||
lc = chunk;
|
||||
ls = lc.getBlockStorageArray()[cy];
|
||||
} else if (cy != lcy) {
|
||||
if (lc == null) {
|
||||
return 0;
|
||||
}
|
||||
ls = lc.getBlockStorageArray()[cy];
|
||||
}
|
||||
if (ls == null) {
|
||||
ls = null;
|
||||
return 0;
|
||||
}
|
||||
byte[] ids = ls.getBlockLSBArray();
|
||||
NibbleArray datasNibble = ls.getBlockMSBArray();
|
||||
int i = FaweCache.CACHE_J[y & 15][x & 15][z & 15];
|
||||
int combined = (ids[i] << 4) + (datasNibble == null ? 0 : datasNibble.get(x & 15, y & 15, z & 15));
|
||||
return combined;
|
||||
}
|
||||
|
||||
private FaweChunk lastChunk;
|
||||
private int lastX = Integer.MIN_VALUE;
|
||||
private int lastZ = Integer.MIN_VALUE;
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, short id, byte data) {
|
||||
if ((y > 255) || (y < 0)) {
|
||||
return false;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
if (cx != lastX || cz != lastZ) {
|
||||
lastX = cx;
|
||||
lastZ = cz;
|
||||
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
|
||||
lastChunk = this.blocks.get(pair);
|
||||
if (lastChunk == null) {
|
||||
lastChunk = this.getChunk(x >> 4, z >> 4);
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, lastChunk);
|
||||
if (previous == null) {
|
||||
chunks.add(lastChunk);
|
||||
return true;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
lastChunk = previous;
|
||||
}
|
||||
}
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int z, BaseBiome biome) {
|
||||
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x >> 4, z >> 4);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous != null) {
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
} else {
|
||||
chunks.add(result);
|
||||
}
|
||||
}
|
||||
result.setBiome(x & 15, z & 15, biome);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> next() {
|
||||
lastX = Integer.MIN_VALUE;
|
||||
lastZ = Integer.MIN_VALUE;
|
||||
try {
|
||||
if (this.blocks.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
synchronized (blocks) {
|
||||
FaweChunk<Chunk> chunk = chunks.poll();
|
||||
if (chunk != null) {
|
||||
blocks.remove(chunk.longHash());
|
||||
this.execute(chunk);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return chunks.size();
|
||||
}
|
||||
|
||||
private LinkedBlockingDeque<FaweChunk<Chunk>> toUpdate = new LinkedBlockingDeque<>();
|
||||
|
||||
public boolean execute(FaweChunk<Chunk> fc) {
|
||||
if (fc == null) {
|
||||
return false;
|
||||
}
|
||||
// Load chunk
|
||||
Chunk chunk = fc.getChunk();
|
||||
if (!chunk.isChunkLoaded) {
|
||||
chunk.onChunkLoad();
|
||||
}
|
||||
// Set blocks / entities / biome
|
||||
if (!this.setComponents(fc)) {
|
||||
return false;
|
||||
}
|
||||
fc.executeTasks();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.blocks.clear();
|
||||
this.chunks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(FaweChunk<?> chunk) {
|
||||
FaweChunk<Chunk> previous = this.blocks.put(chunk.longHash(), (FaweChunk<Chunk>) chunk);
|
||||
if (previous != null) {
|
||||
chunks.remove(previous);
|
||||
}
|
||||
chunks.add((FaweChunk<Chunk>) chunk);
|
||||
}
|
||||
|
||||
public void sendChunk(final FaweChunk<Chunk> fc) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
|
||||
TaskManager.IMP.sync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
}
|
||||
Chunk chunk = fc.getChunk();
|
||||
public void refreshChunk(World world, Chunk chunk) {
|
||||
if (!chunk.isChunkLoaded) {
|
||||
return;
|
||||
}
|
||||
World world = chunk.worldObj;
|
||||
ChunkCoordIntPair pos = chunk.getChunkCoordIntPair();
|
||||
int cx = pos.chunkXPos;
|
||||
int cz = pos.chunkZPos;
|
||||
@ -371,14 +185,10 @@ public class ForgeQueue_All extends FaweQueue {
|
||||
// Try bulk chunk packet
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}, Settings.ASYNC_LIGHTING);
|
||||
}
|
||||
|
||||
public boolean setComponents(FaweChunk<Chunk> fc) {
|
||||
public boolean setComponents(FaweChunk fc) {
|
||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||
Chunk forgeChunk = fc.getChunk();
|
||||
Chunk forgeChunk = fs.getChunk();
|
||||
net.minecraft.world.World nmsWorld = forgeChunk.worldObj;
|
||||
try {
|
||||
boolean flag = !nmsWorld.provider.hasNoSky;
|
||||
@ -485,12 +295,12 @@ public class ForgeQueue_All extends FaweQueue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getChunk(int x, int z) {
|
||||
public FaweChunk getChunk(int x, int z) {
|
||||
return new ForgeChunk_All(this, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(FaweChunk<?> chunk, boolean fixAll) {
|
||||
public boolean fixLighting(FaweChunk chunk, boolean fixAll) {
|
||||
try {
|
||||
ForgeChunk_All fc = (ForgeChunk_All) chunk;
|
||||
Chunk forgeChunk = fc.getChunk();
|
||||
|
@ -114,7 +114,7 @@ public class FaweForge implements IFawe {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world) {
|
||||
public FaweQueue getNewQueue(String world, boolean dontCareIfFast) {
|
||||
return new ForgeQueue_All(world);
|
||||
}
|
||||
|
||||
|
@ -1,256 +1,25 @@
|
||||
package com.boydti.fawe.forge.v0;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.MainUtil;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.Arrays;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
public class ForgeChunk_All extends FaweChunk<Chunk> {
|
||||
|
||||
public char[][] ids;
|
||||
public short[] count;
|
||||
public short[] air;
|
||||
public short[] relight;
|
||||
public byte[][] biomes;
|
||||
public Chunk chunk;
|
||||
|
||||
public class ForgeChunk_All extends CharFaweChunk<Chunk> {
|
||||
/**
|
||||
* A FaweSections object represents a chunk and the blocks that you wish to change in it.
|
||||
*
|
||||
* @param parent
|
||||
* @param x
|
||||
* @param z
|
||||
*/
|
||||
public ForgeChunk_All(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
this.ids = new char[16][];
|
||||
this.count = new short[16];
|
||||
this.air = new short[16];
|
||||
this.relight = new short[16];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Chunk getChunk() {
|
||||
if (this.chunk == null) {
|
||||
public Chunk getNewChunk() {
|
||||
World world = ((ForgeQueue_All) getParent()).getWorld();
|
||||
this.chunk = world.getChunkProvider().provideChunk(getX(), getZ());
|
||||
}
|
||||
return this.chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoc(final FaweQueue parent, int x, int z) {
|
||||
super.setLoc(parent, x, z);
|
||||
this.chunk = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getCount(int i) {
|
||||
return this.count[i];
|
||||
}
|
||||
|
||||
public int getAir(int i) {
|
||||
return this.air[i];
|
||||
}
|
||||
|
||||
public void setCount(int i, short value) {
|
||||
this.count[i] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getRelight(int i) {
|
||||
return this.relight[i];
|
||||
}
|
||||
|
||||
public int getTotalCount() {
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.count[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public int getTotalRelight() {
|
||||
if (getTotalCount() == 0) {
|
||||
Arrays.fill(this.count, (short) 1);
|
||||
Arrays.fill(this.relight, Short.MAX_VALUE);
|
||||
return Short.MAX_VALUE;
|
||||
}
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.relight[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw data for a section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public char[] getIdArray(int i) {
|
||||
return this.ids[i];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, int id, byte data) {
|
||||
int i = FaweCache.CACHE_I[y][x][z];
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
char[] vs = this.ids[i];
|
||||
if (vs == null) {
|
||||
vs = this.ids[i] = new char[4096];
|
||||
this.count[i]++;
|
||||
} else if (vs[j] == 0) {
|
||||
this.count[i]++;
|
||||
}
|
||||
switch (id) {
|
||||
case 0:
|
||||
this.air[i]++;
|
||||
vs[j] = (char) 1;
|
||||
return;
|
||||
case 10:
|
||||
case 11:
|
||||
case 39:
|
||||
case 40:
|
||||
case 51:
|
||||
case 74:
|
||||
case 89:
|
||||
case 122:
|
||||
case 124:
|
||||
case 138:
|
||||
case 169:
|
||||
this.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] = (char) (id << 4);
|
||||
return;
|
||||
case 130:
|
||||
case 76:
|
||||
case 62:
|
||||
this.relight[i]++;
|
||||
case 54:
|
||||
case 146:
|
||||
case 61:
|
||||
case 65:
|
||||
case 68:
|
||||
if (data < 2) {
|
||||
data = 2;
|
||||
}
|
||||
default:
|
||||
vs[j] = (char) ((id << 4) + data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, BaseBiome biome) {
|
||||
if (this.biomes == null) {
|
||||
this.biomes = new byte[16][];
|
||||
}
|
||||
byte[] index = this.biomes[x];
|
||||
if (index == null) {
|
||||
index = this.biomes[x] = new byte[16];
|
||||
}
|
||||
index[z] = (byte) biome.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk clone() {
|
||||
ForgeChunk_All toReturn = new ForgeChunk_All(getParent(), getX(), getZ());
|
||||
toReturn.air = this.air.clone();
|
||||
toReturn.count = this.count.clone();
|
||||
toReturn.relight = this.relight.clone();
|
||||
toReturn.ids = new char[this.ids.length][];
|
||||
for (int i = 0; i < this.ids.length; i++) {
|
||||
char[] matrix = this.ids[i];
|
||||
if (matrix != null) {
|
||||
toReturn.ids[i] = new char[matrix.length];
|
||||
System.arraycopy(matrix, 0, toReturn.ids[i], 0, matrix.length);
|
||||
}
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> copy(boolean shallow) {
|
||||
ForgeChunk_All copy = new ForgeChunk_All(getParent(), getX(), getZ());
|
||||
if (shallow) {
|
||||
copy.ids = ids;
|
||||
copy.air = air;
|
||||
copy.biomes = biomes;
|
||||
copy.chunk = chunk;
|
||||
copy.count = count;
|
||||
copy.relight = relight;
|
||||
} else {
|
||||
copy.ids = (char[][]) MainUtil.copyNd(ids);
|
||||
copy.air = air.clone();
|
||||
copy.biomes = biomes.clone();
|
||||
copy.chunk = chunk;
|
||||
copy.count = count.clone();
|
||||
copy.relight = relight.clone();
|
||||
}
|
||||
return copy;
|
||||
return world.getChunkProvider().provideChunk(getX(), getZ());
|
||||
}
|
||||
}
|
||||
|
@ -2,23 +2,15 @@ package com.boydti.fawe.forge.v0;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.forge.ForgePlayer;
|
||||
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.object.RunnableVal;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
@ -36,12 +28,7 @@ import net.minecraft.world.chunk.IChunkProvider;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
|
||||
public class ForgeQueue_All extends FaweQueue {
|
||||
|
||||
private World forgeWorld;
|
||||
|
||||
private ConcurrentHashMap<Long, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
|
||||
private LinkedBlockingDeque<FaweChunk<Chunk>> chunks = new LinkedBlockingDeque<>();
|
||||
public class ForgeQueue_All extends NMSMappedFaweQueue<World, Chunk, Chunk, char[]> {
|
||||
|
||||
public ForgeQueue_All(final String world) {
|
||||
super(world);
|
||||
@ -52,22 +39,19 @@ public class ForgeQueue_All extends FaweQueue {
|
||||
return getWorld().getChunkProvider().chunkExists(x, z);
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
if (forgeWorld != null) {
|
||||
return forgeWorld;
|
||||
}
|
||||
public World getWorld(String world) {
|
||||
WorldServer[] worlds = MinecraftServer.getServer().worldServers;
|
||||
for (WorldServer ws : worlds) {
|
||||
if (ws.provider.getDimensionName().equals(world)) {
|
||||
return forgeWorld = ws;
|
||||
return ws;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(int x, int z) {
|
||||
IChunkProvider provider = getWorld().getChunkProvider();
|
||||
public boolean regenerateChunk(World world, int x, int z) {
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
@ -100,240 +84,33 @@ public class ForgeQueue_All extends FaweQueue {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTask(int x, int z, Runnable runnable) {
|
||||
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x, z);
|
||||
result.addTask(runnable);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous == null) {
|
||||
chunks.add(result);
|
||||
return;
|
||||
public boolean loadChunk(World world, int x, int z, boolean generate) {
|
||||
return getCachedChunk(world, x, z) != null;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
}
|
||||
result.addTask(runnable);
|
||||
}
|
||||
|
||||
private int lcx = Integer.MIN_VALUE;
|
||||
private int lcz = Integer.MIN_VALUE;
|
||||
private int lcy = Integer.MIN_VALUE;
|
||||
private net.minecraft.world.chunk.Chunk lc;
|
||||
private char[] ls;
|
||||
|
||||
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||
@Override
|
||||
public void run(IntegerPair loc) {
|
||||
getWorld().getChunkProvider().provideChunk(loc.x, loc.z);
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
||||
if (y < 0 || y > 255) {
|
||||
return 0;
|
||||
public Chunk getCachedChunk(World world, int x, int z) {
|
||||
Chunk chunk = world.getChunkProvider().provideChunk(x, z);
|
||||
if (chunk != null && !chunk.isLoaded()) {
|
||||
chunk.onChunkLoad();
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
int cy = y >> 4;
|
||||
if (cx != lcx || cz != lcz) {
|
||||
World world = getWorld();
|
||||
lcx = cx;
|
||||
lcz = cz;
|
||||
IChunkProvider provider = world.getChunkProvider();
|
||||
Chunk chunk;
|
||||
if (!provider.chunkExists(lcx, lcz)) {
|
||||
boolean sync = Thread.currentThread() == Fawe.get().getMainThread();
|
||||
if (sync) {
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
} else if (Settings.CHUNK_WAIT > 0) {
|
||||
loadChunk.value = new IntegerPair(cx, cz);
|
||||
TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT);
|
||||
if (!provider.chunkExists(cx, cz)) {
|
||||
throw new FaweException.FaweChunkLoadException();
|
||||
return chunk;
|
||||
}
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
chunk = provider.provideChunk(cx, cz);
|
||||
}
|
||||
lc = chunk;
|
||||
} else if (cy == lcy) {
|
||||
return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0;
|
||||
}
|
||||
ExtendedBlockStorage storage = lc.getBlockStorageArray()[cy];
|
||||
if (storage == null) {
|
||||
ls = null;
|
||||
return 0;
|
||||
}
|
||||
ls = storage.getData();
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(char[] ls, int x, int y, int z) {
|
||||
return ls[FaweCache.CACHE_J[y][x & 15][z & 15]];
|
||||
}
|
||||
|
||||
private FaweChunk lastChunk;
|
||||
private int lastX = Integer.MIN_VALUE;
|
||||
private int lastZ = Integer.MIN_VALUE;
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, int y, int z, short id, byte data) {
|
||||
if ((y > 255) || (y < 0)) {
|
||||
return false;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
if (cx != lastX || cz != lastZ) {
|
||||
lastX = cx;
|
||||
lastZ = cz;
|
||||
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
|
||||
lastChunk = this.blocks.get(pair);
|
||||
if (lastChunk == null) {
|
||||
lastChunk = this.getChunk(x >> 4, z >> 4);
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, lastChunk);
|
||||
if (previous == null) {
|
||||
chunks.add(lastChunk);
|
||||
return true;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
lastChunk = previous;
|
||||
}
|
||||
}
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
return true;
|
||||
public boolean isChunkLoaded(World world, int x, int z) {
|
||||
return world.getChunkProvider().chunkExists(x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int z, BaseBiome biome) {
|
||||
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x >> 4, z >> 4);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous != null) {
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
} else {
|
||||
chunks.add(result);
|
||||
}
|
||||
}
|
||||
result.setBiome(x & 15, z & 15, biome);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> next() {
|
||||
lastX = Integer.MIN_VALUE;
|
||||
lastZ = Integer.MIN_VALUE;
|
||||
try {
|
||||
if (this.blocks.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
synchronized (blocks) {
|
||||
FaweChunk<Chunk> chunk = chunks.poll();
|
||||
if (chunk != null) {
|
||||
blocks.remove(chunk.longHash());
|
||||
this.execute(chunk);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return chunks.size();
|
||||
}
|
||||
|
||||
private LinkedBlockingDeque<FaweChunk<Chunk>> toUpdate = new LinkedBlockingDeque<>();
|
||||
|
||||
public boolean execute(FaweChunk<Chunk> fc) {
|
||||
if (fc == null) {
|
||||
return false;
|
||||
}
|
||||
// Load chunk
|
||||
Chunk chunk = fc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
chunk.onChunkLoad();
|
||||
}
|
||||
// Set blocks / entities / biome
|
||||
if (!this.setComponents(fc)) {
|
||||
return false;
|
||||
}
|
||||
fc.executeTasks();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.blocks.clear();
|
||||
this.chunks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(FaweChunk<?> chunk) {
|
||||
FaweChunk<Chunk> previous = this.blocks.put(chunk.longHash(), (FaweChunk<Chunk>) chunk);
|
||||
if (previous != null) {
|
||||
chunks.remove(previous);
|
||||
}
|
||||
chunks.add((FaweChunk<Chunk>) chunk);
|
||||
}
|
||||
|
||||
public void sendChunk(FaweChunk<Chunk> fc) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
|
||||
TaskManager.IMP.sync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
}
|
||||
Chunk chunk = fc.getChunk();
|
||||
if (!chunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
World world = chunk.getWorld();
|
||||
ChunkCoordIntPair pos = chunk.getChunkCoordIntPair();
|
||||
int cx = pos.chunkXPos;
|
||||
int cz = pos.chunkZPos;
|
||||
for (FawePlayer fp : Fawe.get().getCachedPlayers()) {
|
||||
ForgePlayer forgePlayer = (ForgePlayer) fp;
|
||||
EntityPlayerMP player = forgePlayer.parent;
|
||||
if (!player.worldObj.equals(world)) {
|
||||
continue;
|
||||
}
|
||||
int view = MinecraftServer.getServer().getConfigurationManager().getViewDistance();
|
||||
EntityPlayerMP nmsPlayer = (EntityPlayerMP) player;
|
||||
BlockPos loc = player.getPosition();
|
||||
int px = loc.getX() >> 4;
|
||||
int pz = loc.getZ() >> 4;
|
||||
int dx = Math.abs(cx - (loc.getX() >> 4));
|
||||
int dz = Math.abs(cz - (loc.getZ() >> 4));
|
||||
if ((dx > view) || (dz > view)) {
|
||||
continue;
|
||||
}
|
||||
NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler;
|
||||
con.sendPacket(new S21PacketChunkData(chunk, false, 65535));
|
||||
// Try sending true, 0 first
|
||||
// Try bulk chunk packet
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}, Settings.ASYNC_LIGHTING);
|
||||
}
|
||||
|
||||
public boolean setComponents(FaweChunk<Chunk> fc) {
|
||||
public boolean setComponents(FaweChunk fc) {
|
||||
ForgeChunk_All fs = (ForgeChunk_All) fc;
|
||||
Chunk forgeChunk = fc.getChunk();
|
||||
Chunk forgeChunk = fs.getChunk();
|
||||
net.minecraft.world.World nmsWorld = forgeChunk.getWorld();
|
||||
try {
|
||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||
@ -407,19 +184,19 @@ public class ForgeQueue_All extends FaweQueue {
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
byte[][] biomes = fs.biomes;
|
||||
int[][] biomes = fs.biomes;
|
||||
if (biomes != null) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
byte[] array = biomes[x];
|
||||
int[] array = biomes[x];
|
||||
if (array == null) {
|
||||
continue;
|
||||
}
|
||||
for (int z = 0; z < 16; z++) {
|
||||
byte biome = array[z];
|
||||
int biome = array[z];
|
||||
if (biome == 0) {
|
||||
continue;
|
||||
}
|
||||
forgeChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = biome;
|
||||
forgeChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -427,13 +204,44 @@ public class ForgeQueue_All extends FaweQueue {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshChunk(World world, Chunk chunk) {
|
||||
if (!chunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
ChunkCoordIntPair pos = chunk.getChunkCoordIntPair();
|
||||
int cx = pos.chunkXPos;
|
||||
int cz = pos.chunkZPos;
|
||||
for (FawePlayer fp : Fawe.get().getCachedPlayers()) {
|
||||
ForgePlayer forgePlayer = (ForgePlayer) fp;
|
||||
EntityPlayerMP player = forgePlayer.parent;
|
||||
if (!player.worldObj.equals(world)) {
|
||||
continue;
|
||||
}
|
||||
int view = MinecraftServer.getServer().getConfigurationManager().getViewDistance();
|
||||
EntityPlayerMP nmsPlayer = (EntityPlayerMP) player;
|
||||
BlockPos loc = player.getPosition();
|
||||
int px = loc.getX() >> 4;
|
||||
int pz = loc.getZ() >> 4;
|
||||
int dx = Math.abs(cx - (loc.getX() >> 4));
|
||||
int dz = Math.abs(cz - (loc.getZ() >> 4));
|
||||
if ((dx > view) || (dz > view)) {
|
||||
continue;
|
||||
}
|
||||
NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler;
|
||||
con.sendPacket(new S21PacketChunkData(chunk, false, 65535));
|
||||
// Try sending true, 0 first
|
||||
// Try bulk chunk packet
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> getChunk(int x, int z) {
|
||||
return new ForgeChunk_All(this, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(FaweChunk<?> chunk, boolean fixAll) {
|
||||
public boolean fixLighting(FaweChunk chunk, boolean fixAll) {
|
||||
try {
|
||||
ForgeChunk_All fc = (ForgeChunk_All) chunk;
|
||||
Chunk forgeChunk = fc.getChunk();
|
||||
|
@ -1,3 +1,3 @@
|
||||
rootProject.name = 'FastAsyncWorldEdit'
|
||||
|
||||
include 'core', 'bukkit', 'forge189', 'forge1710', 'sponge'
|
||||
include 'core', 'bukkit0', 'bukkit19', 'bukkit18', 'forge189', 'forge1710', 'sponge'
|
||||
|
@ -2,13 +2,14 @@ package com.boydti.fawe.sponge;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.IFawe;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.SpongeCommand;
|
||||
import com.boydti.fawe.v1_8.SpongeQueue_1_8;
|
||||
import com.boydti.fawe.config.BBC;
|
||||
import com.boydti.fawe.object.EditSessionWrapper;
|
||||
import com.boydti.fawe.object.FaweCommand;
|
||||
import com.boydti.fawe.object.FawePlayer;
|
||||
import com.boydti.fawe.regions.FaweMaskManager;
|
||||
import com.boydti.fawe.sponge.v1_8.SpongeQueue_1_8;
|
||||
import com.boydti.fawe.sponge.v1_8.SpongeQueue_ALL;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.sk89q.worldedit.EditSession;
|
||||
@ -112,8 +113,15 @@ public class FaweSponge implements IFawe {
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweQueue getNewQueue(String world) {
|
||||
public FaweQueue getNewQueue(String world, boolean fast) {
|
||||
if (fast) {
|
||||
try {
|
||||
return new SpongeQueue_1_8(world);
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return new SpongeQueue_ALL(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,19 @@
|
||||
package com.boydti.fawe.sponge.v1_8;
|
||||
|
||||
import com.boydti.fawe.example.CharFaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
public class SpongeChunk_1_8 extends CharFaweChunk<net.minecraft.world.chunk.Chunk> {
|
||||
|
||||
public SpongeChunk_1_8(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraft.world.chunk.Chunk getNewChunk() {
|
||||
World world = Sponge.getServer().getWorld(getParent().world).get();
|
||||
return (net.minecraft.world.chunk.Chunk) world.loadChunk(getX(), 0, getZ(), true).get();
|
||||
}
|
||||
}
|
@ -1,23 +1,14 @@
|
||||
package com.boydti.fawe.v1_8;
|
||||
package com.boydti.fawe.sponge.v1_8;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.config.Settings;
|
||||
import com.boydti.fawe.sponge.SpongeUtil;
|
||||
import com.boydti.fawe.v0.SpongeQueue_0;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.IntegerPair;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import com.boydti.fawe.object.RunnableVal;
|
||||
import com.boydti.fawe.object.exception.FaweException;
|
||||
import com.boydti.fawe.util.TaskManager;
|
||||
import com.flowpowered.math.vector.Vector3i;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
@ -38,101 +29,18 @@ import org.spongepowered.api.world.Chunk;
|
||||
import org.spongepowered.api.world.Location;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
|
||||
public World spongeWorld;
|
||||
|
||||
public class SpongeQueue_1_8 extends NMSMappedFaweQueue<World, net.minecraft.world.chunk.Chunk, ExtendedBlockStorage[], char[]> {
|
||||
public SpongeQueue_1_8(String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
private final RunnableVal<IntegerPair> loadChunk = new RunnableVal<IntegerPair>() {
|
||||
@Override
|
||||
public void run(IntegerPair loc) {
|
||||
if (spongeWorld == null) {
|
||||
spongeWorld = Sponge.getServer().getWorld(world).get();
|
||||
}
|
||||
Chunk chunk = spongeWorld.getChunk(loc.x, 0, loc.z).orElse(null);
|
||||
if (chunk == null || !chunk.isLoaded()) {
|
||||
spongeWorld.loadChunk(loc.x, 0, loc.z, true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(int x, int y, int z) throws FaweException.FaweChunkLoadException {
|
||||
if (y < 0 || y > 255) {
|
||||
return 0;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
int cy = y >> 4;
|
||||
if (cx != lcx || cz != lcz) {
|
||||
if (spongeWorld == null) {
|
||||
spongeWorld = Sponge.getServer().getWorld(world).get();
|
||||
}
|
||||
lcx = cx;
|
||||
lcz = cz;
|
||||
Chunk chunk = spongeWorld.getChunk(cx, 0, cz).orElse(null);
|
||||
if (chunk == null || !chunk.isLoaded()) {
|
||||
boolean sync = Thread.currentThread() == Fawe.get().getMainThread();
|
||||
if (sync) {
|
||||
chunk = spongeWorld.loadChunk(cx, 0, cz, true).orElse(null);
|
||||
} else if (Settings.CHUNK_WAIT > 0) {
|
||||
loadChunk.value = new IntegerPair(cx, cz);
|
||||
TaskManager.IMP.sync(loadChunk, Settings.CHUNK_WAIT);
|
||||
chunk = spongeWorld.getChunk(cx, 0, cz).orElse(null);
|
||||
if (chunk == null || !chunk.isLoaded()) {
|
||||
throw new FaweException.FaweChunkLoadException();
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
lc = (net.minecraft.world.chunk.Chunk) chunk;
|
||||
} else if (cy == lcy) {
|
||||
return ls != null ? ls[FaweCache.CACHE_J[y][x & 15][z & 15]] : 0;
|
||||
}
|
||||
ExtendedBlockStorage storage = lc.getBlockStorageArray()[cy];
|
||||
if (storage == null) {
|
||||
ls = null;
|
||||
return 0;
|
||||
}
|
||||
ls = storage.getData();
|
||||
return ls[FaweCache.CACHE_J[y][x & 15][z & 15]];
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<FaweChunk<Chunk>> sendChunk(Collection<FaweChunk<Chunk>> fcs) {
|
||||
if (fcs.isEmpty()) {
|
||||
return fcs;
|
||||
}
|
||||
for (FaweChunk<Chunk> chunk : fcs) {
|
||||
sendChunk(chunk);
|
||||
}
|
||||
fcs.clear();
|
||||
return fcs;
|
||||
}
|
||||
|
||||
public void sendChunk(FaweChunk<Chunk> fc) {
|
||||
TaskManager.IMP.task(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final boolean result = fixLighting(fc, Settings.FIX_ALL_LIGHTING) || !Settings.ASYNC_LIGHTING;
|
||||
TaskManager.IMP.sync(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (!result) {
|
||||
fixLighting(fc, Settings.FIX_ALL_LIGHTING);
|
||||
}
|
||||
Chunk chunk = fc.getChunk();
|
||||
public void refreshChunk(World world, net.minecraft.world.chunk.Chunk chunk) {
|
||||
if (!chunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
World world = chunk.getWorld();
|
||||
Vector3i pos = chunk.getBlockMin();
|
||||
int cx = pos.getX() >> 4;
|
||||
int cz = pos.getZ() >> 4;
|
||||
int cx = chunk.xPosition;
|
||||
int cz = chunk.zPosition;
|
||||
for (Player player : Sponge.getServer().getOnlinePlayers()) {
|
||||
if (!player.getWorld().equals(world)) {
|
||||
continue;
|
||||
@ -154,34 +62,81 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
// Try bulk chunk packet
|
||||
}
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
}, Settings.ASYNC_LIGHTING);
|
||||
}
|
||||
|
||||
private int lcx = Integer.MIN_VALUE;
|
||||
private int lcz = Integer.MIN_VALUE;
|
||||
private int lcy = Integer.MIN_VALUE;
|
||||
private net.minecraft.world.chunk.Chunk lc;
|
||||
private char[] ls;
|
||||
|
||||
@Override
|
||||
public boolean setComponents(FaweChunk<Chunk> fc) {
|
||||
public char[] getCachedSection(ExtendedBlockStorage[] chunk, int cy) {
|
||||
ExtendedBlockStorage value = chunk[cy];
|
||||
return value == null ? null : value.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld(String world) {
|
||||
return Sponge.getServer().getWorld(this.world).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(World world, int x, int z) {
|
||||
Chunk chunk = world.getChunk(x << 4, 0, z << 4).orElse(null);
|
||||
return chunk != null && chunk.isLoaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(World world, int x, int z) {
|
||||
try {
|
||||
net.minecraft.world.World nmsWorld = (net.minecraft.world.World) world;
|
||||
IChunkProvider provider = nmsWorld.getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
Field chunkProviderField = chunkServer.getClass().getDeclaredField("field_73246_d");
|
||||
chunkProviderField.setAccessible(true);
|
||||
IChunkProvider chunkProvider = (IChunkProvider) chunkProviderField.get(chunkServer);
|
||||
long pos = ChunkCoordIntPair.chunkXZ2Int(x, z);
|
||||
net.minecraft.world.chunk.Chunk mcChunk;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b");
|
||||
droppedChunksSetField.setAccessible(true);
|
||||
Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer);
|
||||
droppedChunksSet.remove(pos);
|
||||
Field id2ChunkMapField = chunkServer.getClass().getDeclaredField("field_73244_f");
|
||||
id2ChunkMapField.setAccessible(true);
|
||||
LongHashMap<net.minecraft.world.chunk.Chunk> id2ChunkMap = (LongHashMap<net.minecraft.world.chunk.Chunk>) id2ChunkMapField.get(chunkServer);
|
||||
id2ChunkMap.remove(pos);
|
||||
mcChunk = chunkProvider.provideChunk(x, z);
|
||||
id2ChunkMap.add(pos, mcChunk);
|
||||
List<net.minecraft.world.chunk.Chunk> loadedChunks = chunkServer.func_152380_a();
|
||||
loadedChunks.add(mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onChunkLoad();
|
||||
mcChunk.populateChunk(chunkProvider, chunkProvider, x, z);
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComponents(FaweChunk fc) {
|
||||
SpongeChunk_1_8 fs = (SpongeChunk_1_8) fc;
|
||||
Chunk spongeChunk = fc.getChunk();
|
||||
net.minecraft.world.World nmsWorld = (net.minecraft.world.World) spongeChunk.getWorld();
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
|
||||
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
||||
try {
|
||||
boolean flag = !nmsWorld.provider.getHasNoSky();
|
||||
// Sections
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) spongeChunk;
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
Map<BlockPos, TileEntity> tiles = nmsChunk.getTileEntityMap();
|
||||
ClassInheritanceMultiMap<Entity>[] entities = nmsChunk.getEntityLists();
|
||||
// Trim tiles
|
||||
Set<Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||
Set<Map.Entry<BlockPos, TileEntity>> entryset = tiles.entrySet();
|
||||
Iterator<Map.Entry<BlockPos, TileEntity>> iterator = entryset.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||
Map.Entry<BlockPos, TileEntity> tile = iterator.next();
|
||||
BlockPos pos = tile.getKey();
|
||||
int lx = pos.getX() & 15;
|
||||
int ly = pos.getY();
|
||||
@ -204,7 +159,8 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
}
|
||||
// Efficiently merge sections
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
if (fs.getCount(j) == 0) {
|
||||
int count = fs.getCount(j);
|
||||
if (count == 0) {
|
||||
continue;
|
||||
}
|
||||
char[] newArray = fs.getIdArray(j);
|
||||
@ -212,14 +168,20 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
continue;
|
||||
}
|
||||
ExtendedBlockStorage section = sections[j];
|
||||
if ((section == null) || (fs.getCount(j) >= 4096)) {
|
||||
|
||||
if ((section == null)) {
|
||||
section = new ExtendedBlockStorage(j << 4, flag);
|
||||
section.setData(newArray);
|
||||
sections[j] = section;
|
||||
continue;
|
||||
} else if (count >= 4096){
|
||||
section.setData(newArray);
|
||||
setCount(0, count - fs.getAir(j), section);
|
||||
continue;
|
||||
}
|
||||
char[] currentArray = section.getData();
|
||||
boolean fill = true;
|
||||
int solid = 0;
|
||||
for (int k = 0; k < newArray.length; k++) {
|
||||
char n = newArray[k];
|
||||
switch (n) {
|
||||
@ -228,18 +190,22 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
continue;
|
||||
case 1:
|
||||
fill = false;
|
||||
if (currentArray[k] > 1) {
|
||||
solid++;
|
||||
}
|
||||
currentArray[k] = 0;
|
||||
continue;
|
||||
default:
|
||||
solid++;
|
||||
currentArray[k] = n;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
setCount(0, solid, section);
|
||||
if (fill) {
|
||||
fs.setCount(j, Short.MAX_VALUE);
|
||||
}
|
||||
}
|
||||
// // Clear
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@ -255,7 +221,7 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
if (biome == 0) {
|
||||
continue;
|
||||
}
|
||||
spongeChunk.setBiome(x, z, SpongeUtil.getBiome(biome));
|
||||
nmsChunk.getBiomeArray()[((z & 0xF) << 4 | x & 0xF)] = (byte) biome;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -263,24 +229,29 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* This should be overridden by any specialized queues.
|
||||
* @param x
|
||||
* @param z
|
||||
*/
|
||||
@Override
|
||||
public SpongeChunk_1_8 getChunk(int x, int z) {
|
||||
return new SpongeChunk_1_8(this, x, z);
|
||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
|
||||
Class<? extends ExtendedBlockStorage> clazz = section.getClass();
|
||||
Field fieldTickingBlockCount = clazz.getDeclaredField("field_76683_c");
|
||||
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("field_76682_b");
|
||||
fieldTickingBlockCount.setAccessible(true);
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
fieldTickingBlockCount.set(section, tickingBlockCount);
|
||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(FaweChunk<?> pc, boolean fixAll) {
|
||||
public FaweChunk<net.minecraft.world.chunk.Chunk> getChunk(int x, int z) {
|
||||
return new SpongeChunk_1_8(this, x, z);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(FaweChunk fc, boolean fixAll) {
|
||||
try {
|
||||
SpongeChunk_1_8 bc = (SpongeChunk_1_8) pc;
|
||||
Chunk spongeChunk = bc.getChunk();
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) spongeChunk;
|
||||
if (!spongeChunk.isLoaded()) {
|
||||
if (!spongeChunk.loadChunk(false)) {
|
||||
SpongeChunk_1_8 bc = (SpongeChunk_1_8) fc;
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk();
|
||||
if (!nmsChunk.isLoaded()) {
|
||||
if (!((Chunk) nmsChunk).loadChunk(false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -291,8 +262,8 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
||||
|
||||
int X = pc.getX() << 4;
|
||||
int Z = pc.getZ() << 4;
|
||||
int X = bc.getX() << 4;
|
||||
int Z = bc.getZ() << 4;
|
||||
|
||||
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
@ -355,50 +326,6 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(int x, int z) {
|
||||
if (spongeWorld == null) {
|
||||
spongeWorld = Sponge.getServer().getWorld(world).get();
|
||||
}
|
||||
try {
|
||||
net.minecraft.world.World nmsWorld = (net.minecraft.world.World) spongeWorld;
|
||||
IChunkProvider provider = nmsWorld.getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
Field chunkProviderField = chunkServer.getClass().getDeclaredField("field_73246_d");
|
||||
chunkProviderField.setAccessible(true);
|
||||
IChunkProvider chunkProvider = (IChunkProvider) chunkProviderField.get(chunkServer);
|
||||
long pos = ChunkCoordIntPair.chunkXZ2Int(x, z);
|
||||
net.minecraft.world.chunk.Chunk mcChunk;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b");
|
||||
droppedChunksSetField.setAccessible(true);
|
||||
Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer);
|
||||
droppedChunksSet.remove(pos);
|
||||
Field id2ChunkMapField = chunkServer.getClass().getDeclaredField("field_73244_f");
|
||||
id2ChunkMapField.setAccessible(true);
|
||||
LongHashMap<net.minecraft.world.chunk.Chunk> id2ChunkMap = (LongHashMap<net.minecraft.world.chunk.Chunk>) id2ChunkMapField.get(chunkServer);
|
||||
id2ChunkMap.remove(pos);
|
||||
mcChunk = chunkProvider.provideChunk(x, z);
|
||||
id2ChunkMap.add(pos, mcChunk);
|
||||
List<net.minecraft.world.chunk.Chunk> loadedChunks = chunkServer.func_152380_a();
|
||||
loadedChunks.add(mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onChunkLoad();
|
||||
mcChunk.populateChunk(chunkProvider, chunkProvider, x, z);
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSurrounded(ExtendedBlockStorage[] sections, int x, int y, int z) {
|
||||
return isSolid(getId(sections, x, y + 1, z))
|
||||
&& isSolid(getId(sections, x + 1, y - 1, z))
|
||||
@ -427,4 +354,20 @@ public class SpongeQueue_1_8 extends SpongeQueue_0 {
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
return array[j] >> 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadChunk(World world, int x, int z, boolean generate) {
|
||||
return getCachedChunk(world, x, z) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getCachedChunk(World world, int cx, int cz) {
|
||||
Chunk chunk = world.loadChunk(cx, 0, cz, true).orElse(null);
|
||||
return ((net.minecraft.world.chunk.Chunk) chunk).getBlockStorageArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(char[] chars, int x, int y, int z) {
|
||||
return chars[FaweCache.CACHE_J[y][x & 15][z & 15]];
|
||||
}
|
||||
}
|
@ -0,0 +1,310 @@
|
||||
package com.boydti.fawe.sponge.v1_8;
|
||||
|
||||
import com.boydti.fawe.Fawe;
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.example.NMSMappedFaweQueue;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.object.PseudoRandom;
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.EntityPlayerMP;
|
||||
import net.minecraft.network.NetHandlerPlayServer;
|
||||
import net.minecraft.network.play.server.S21PacketChunkData;
|
||||
import net.minecraft.util.BlockPos;
|
||||
import net.minecraft.util.LongHashMap;
|
||||
import net.minecraft.world.ChunkCoordIntPair;
|
||||
import net.minecraft.world.chunk.IChunkProvider;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.block.BlockState;
|
||||
import org.spongepowered.api.block.BlockTypes;
|
||||
import org.spongepowered.api.entity.living.player.Player;
|
||||
import org.spongepowered.api.world.Chunk;
|
||||
import org.spongepowered.api.world.Location;
|
||||
import org.spongepowered.api.world.World;
|
||||
import org.spongepowered.api.world.extent.UnmodifiableBlockVolume;
|
||||
import org.spongepowered.api.world.extent.worker.MutableBlockVolumeWorker;
|
||||
import org.spongepowered.api.world.extent.worker.procedure.BlockVolumeMapper;
|
||||
|
||||
public class SpongeQueue_ALL extends NMSMappedFaweQueue<World, net.minecraft.world.chunk.Chunk, ExtendedBlockStorage[], char[]> {
|
||||
public SpongeQueue_ALL(String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void refreshChunk(World world, net.minecraft.world.chunk.Chunk chunk) {
|
||||
if (!chunk.isLoaded()) {
|
||||
return;
|
||||
}
|
||||
int cx = chunk.xPosition;
|
||||
int cz = chunk.zPosition;
|
||||
for (Player player : Sponge.getServer().getOnlinePlayers()) {
|
||||
if (!player.getWorld().equals(world)) {
|
||||
continue;
|
||||
}
|
||||
int view = player.getViewDistance();
|
||||
EntityPlayerMP nmsPlayer = (EntityPlayerMP) player;
|
||||
Location<World> loc = player.getLocation();
|
||||
int px = loc.getBlockX() >> 4;
|
||||
int pz = loc.getBlockZ() >> 4;
|
||||
int dx = Math.abs(cx - (loc.getBlockX() >> 4));
|
||||
int dz = Math.abs(cz - (loc.getBlockZ() >> 4));
|
||||
if ((dx > view) || (dz > view)) {
|
||||
continue;
|
||||
}
|
||||
NetHandlerPlayServer con = nmsPlayer.playerNetServerHandler;
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = (net.minecraft.world.chunk.Chunk) chunk;
|
||||
con.sendPacket(new S21PacketChunkData(nmsChunk, false, 65535));
|
||||
// Try sending true, 0 first
|
||||
// Try bulk chunk packet
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public char[] getCachedSection(ExtendedBlockStorage[] chunk, int cy) {
|
||||
ExtendedBlockStorage value = chunk[cy];
|
||||
return value == null ? null : value.getData();
|
||||
}
|
||||
|
||||
@Override
|
||||
public World getWorld(String world) {
|
||||
return Sponge.getServer().getWorld(this.world).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(World world, int x, int z) {
|
||||
Chunk chunk = world.getChunk(x << 4, 0, z << 4).orElse(null);
|
||||
return chunk != null && chunk.isLoaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean regenerateChunk(World world, int x, int z) {
|
||||
try {
|
||||
net.minecraft.world.World nmsWorld = (net.minecraft.world.World) world;
|
||||
IChunkProvider provider = nmsWorld.getChunkProvider();
|
||||
if (!(provider instanceof ChunkProviderServer)) {
|
||||
return false;
|
||||
}
|
||||
ChunkProviderServer chunkServer = (ChunkProviderServer) provider;
|
||||
Field chunkProviderField = chunkServer.getClass().getDeclaredField("field_73246_d");
|
||||
chunkProviderField.setAccessible(true);
|
||||
IChunkProvider chunkProvider = (IChunkProvider) chunkProviderField.get(chunkServer);
|
||||
long pos = ChunkCoordIntPair.chunkXZ2Int(x, z);
|
||||
net.minecraft.world.chunk.Chunk mcChunk;
|
||||
if (chunkServer.chunkExists(x, z)) {
|
||||
mcChunk = chunkServer.loadChunk(x, z);
|
||||
mcChunk.onChunkUnload();
|
||||
}
|
||||
Field droppedChunksSetField = chunkServer.getClass().getDeclaredField("field_73248_b");
|
||||
droppedChunksSetField.setAccessible(true);
|
||||
Set droppedChunksSet = (Set) droppedChunksSetField.get(chunkServer);
|
||||
droppedChunksSet.remove(pos);
|
||||
Field id2ChunkMapField = chunkServer.getClass().getDeclaredField("field_73244_f");
|
||||
id2ChunkMapField.setAccessible(true);
|
||||
LongHashMap<net.minecraft.world.chunk.Chunk> id2ChunkMap = (LongHashMap<net.minecraft.world.chunk.Chunk>) id2ChunkMapField.get(chunkServer);
|
||||
id2ChunkMap.remove(pos);
|
||||
mcChunk = chunkProvider.provideChunk(x, z);
|
||||
id2ChunkMap.add(pos, mcChunk);
|
||||
List<net.minecraft.world.chunk.Chunk> loadedChunks = chunkServer.func_152380_a();
|
||||
loadedChunks.add(mcChunk);
|
||||
if (mcChunk != null) {
|
||||
mcChunk.onChunkLoad();
|
||||
mcChunk.populateChunk(chunkProvider, chunkProvider, x, z);
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private BlockState AIR = BlockTypes.AIR.getDefaultState();
|
||||
|
||||
@Override
|
||||
public boolean setComponents(FaweChunk fc) {
|
||||
SpongeChunk_1_8 fs = (SpongeChunk_1_8) fc;
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = fs.getChunk();
|
||||
Chunk spongeChunk = (Chunk) nmsChunk;
|
||||
|
||||
char[][] ids = ((SpongeChunk_1_8) fc).getIdArrays();
|
||||
MutableBlockVolumeWorker<? extends Chunk> blockWorker = spongeChunk.getBlockWorker();
|
||||
blockWorker.map(new BlockVolumeMapper() {
|
||||
@Override
|
||||
public BlockState map(UnmodifiableBlockVolume volume, int xx, int y, int zz) {
|
||||
int x = xx & 15;
|
||||
int z = zz & 15;
|
||||
int i = FaweCache.CACHE_I[y][x][z];
|
||||
char[] array = ids[i];
|
||||
if (array == null) {
|
||||
return null;
|
||||
}
|
||||
int combinedId = array[FaweCache.CACHE_J[y][x][z]];
|
||||
switch (combinedId) {
|
||||
case 0:
|
||||
return null;
|
||||
case 1:
|
||||
return AIR;
|
||||
default:
|
||||
int id = combinedId >> 4;
|
||||
Block block = Block.getBlockById(id);
|
||||
int data = combinedId & 0xf;
|
||||
IBlockState ibd;
|
||||
if (data != 0) {
|
||||
ibd = block.getStateFromMeta(data);
|
||||
} else {
|
||||
ibd = block.getDefaultState();
|
||||
}
|
||||
return (BlockState) ibd;
|
||||
}
|
||||
}
|
||||
});
|
||||
sendChunk(fs);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setCount(int tickingBlockCount, int nonEmptyBlockCount, ExtendedBlockStorage section) throws NoSuchFieldException, IllegalAccessException {
|
||||
Class<? extends ExtendedBlockStorage> clazz = section.getClass();
|
||||
Field fieldTickingBlockCount = clazz.getDeclaredField("field_76683_c");
|
||||
Field fieldNonEmptyBlockCount = clazz.getDeclaredField("field_76682_b");
|
||||
fieldTickingBlockCount.setAccessible(true);
|
||||
fieldNonEmptyBlockCount.setAccessible(true);
|
||||
fieldTickingBlockCount.set(section, tickingBlockCount);
|
||||
fieldNonEmptyBlockCount.set(section, nonEmptyBlockCount);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<net.minecraft.world.chunk.Chunk> getChunk(int x, int z) {
|
||||
return new SpongeChunk_1_8(this, x, z);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean fixLighting(FaweChunk fc, boolean fixAll) {
|
||||
try {
|
||||
SpongeChunk_1_8 bc = (SpongeChunk_1_8) fc;
|
||||
net.minecraft.world.chunk.Chunk nmsChunk = bc.getChunk();
|
||||
if (!nmsChunk.isLoaded()) {
|
||||
if (!((Chunk) nmsChunk).loadChunk(false)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
nmsChunk.generateSkylightMap();
|
||||
if (bc.getTotalRelight() == 0 && !fixAll) {
|
||||
return true;
|
||||
}
|
||||
ExtendedBlockStorage[] sections = nmsChunk.getBlockStorageArray();
|
||||
net.minecraft.world.World nmsWorld = nmsChunk.getWorld();
|
||||
|
||||
int X = bc.getX() << 4;
|
||||
int Z = bc.getZ() << 4;
|
||||
|
||||
|
||||
for (int j = 0; j < sections.length; j++) {
|
||||
ExtendedBlockStorage 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;
|
||||
}
|
||||
char[] array = section.getData();
|
||||
int l = PseudoRandom.random.random(2);
|
||||
for (int k = 0; k < array.length; k++) {
|
||||
int i = array[k];
|
||||
if (i < 16) {
|
||||
continue;
|
||||
}
|
||||
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:
|
||||
int x = FaweCache.CACHE_X[j][k];
|
||||
int y = FaweCache.CACHE_Y[j][k];
|
||||
int z = FaweCache.CACHE_Z[j][k];
|
||||
if (isSurrounded(sections, x, y, z)) {
|
||||
continue;
|
||||
}
|
||||
BlockPos pos = new BlockPos(X + x, y, Z + z);
|
||||
nmsWorld.checkLight(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} catch (Throwable e) {
|
||||
if (Thread.currentThread() == Fawe.get().getMainThread()) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSurrounded(ExtendedBlockStorage[] 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 && Block.getBlockById(i).isOpaqueCube();
|
||||
}
|
||||
|
||||
public int getId(ExtendedBlockStorage[] 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];
|
||||
ExtendedBlockStorage section = sections[i];
|
||||
if (section == null) {
|
||||
return 0;
|
||||
}
|
||||
char[] array = section.getData();
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
return array[j] >> 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean loadChunk(World world, int x, int z, boolean generate) {
|
||||
return getCachedChunk(world, x, z) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExtendedBlockStorage[] getCachedChunk(World world, int cx, int cz) {
|
||||
Chunk chunk = world.loadChunk(cx, 0, cz, true).orElse(null);
|
||||
return ((net.minecraft.world.chunk.Chunk) chunk).getBlockStorageArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getCombinedId4Data(char[] chars, int x, int y, int z) {
|
||||
return chars[FaweCache.CACHE_J[y][x & 15][z & 15]];
|
||||
}
|
||||
}
|
@ -1,166 +0,0 @@
|
||||
package com.boydti.fawe.v0;
|
||||
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.LinkedBlockingDeque;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.world.Chunk;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
public abstract class SpongeQueue_0 extends FaweQueue {
|
||||
|
||||
/**
|
||||
* Map of chunks in the queue
|
||||
*/
|
||||
private final ConcurrentHashMap<Long, FaweChunk<Chunk>> blocks = new ConcurrentHashMap<>();
|
||||
private LinkedBlockingDeque<FaweChunk<Chunk>> chunks = new LinkedBlockingDeque<>();
|
||||
|
||||
public SpongeQueue_0(String world) {
|
||||
super(world);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChunkLoaded(int x, int z) {
|
||||
World world = Sponge.getServer().getWorld(this.world).get();
|
||||
Chunk chunk = world.getChunk(x << 4, 0, z << 4).orElse(null);
|
||||
return chunk != null && chunk.isLoaded();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addTask(int x, int z, Runnable runnable) {
|
||||
long pair = (long) (x) << 32 | (z) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x, z);
|
||||
result.addTask(runnable);
|
||||
final FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous == null) {
|
||||
chunks.add(result);
|
||||
return;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
}
|
||||
result.addTask(runnable);
|
||||
}
|
||||
|
||||
private FaweChunk lastChunk;
|
||||
private int lastX = Integer.MIN_VALUE;
|
||||
private int lastZ = Integer.MIN_VALUE;
|
||||
|
||||
@Override
|
||||
public boolean setBlock(int x, final int y, int z, final short id, final byte data) {
|
||||
if ((y > 255) || (y < 0)) {
|
||||
return false;
|
||||
}
|
||||
int cx = x >> 4;
|
||||
int cz = z >> 4;
|
||||
if (cx != lastX || cz != lastZ) {
|
||||
lastX = cx;
|
||||
lastZ = cz;
|
||||
long pair = (long) (cx) << 32 | (cz) & 0xFFFFFFFFL;
|
||||
lastChunk = this.blocks.get(pair);
|
||||
if (lastChunk == null) {
|
||||
lastChunk = this.getChunk(x >> 4, z >> 4);
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
FaweChunk<Chunk> previous = this.blocks.put(pair, lastChunk);
|
||||
if (previous == null) {
|
||||
chunks.add(lastChunk);
|
||||
return true;
|
||||
}
|
||||
this.blocks.put(pair, previous);
|
||||
lastChunk = previous;
|
||||
}
|
||||
}
|
||||
lastChunk.setBlock(x & 15, y, z & 15, id, data);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setBiome(int x, int z, final BaseBiome biome) {
|
||||
long pair = (long) (x >> 4) << 32 | (z >> 4) & 0xFFFFFFFFL;
|
||||
FaweChunk<Chunk> result = this.blocks.get(pair);
|
||||
if (result == null) {
|
||||
result = this.getChunk(x >> 4, z >> 4);
|
||||
final FaweChunk<Chunk> previous = this.blocks.put(pair, result);
|
||||
if (previous != null) {
|
||||
this.blocks.put(pair, previous);
|
||||
result = previous;
|
||||
}
|
||||
}
|
||||
result.setBiome(x & 15, z & 15, biome);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> next() {
|
||||
lastX = Integer.MIN_VALUE;
|
||||
lastZ = Integer.MIN_VALUE;
|
||||
try {
|
||||
if (this.blocks.size() == 0) {
|
||||
return null;
|
||||
}
|
||||
synchronized (blocks) {
|
||||
FaweChunk<Chunk> chunk = chunks.poll();
|
||||
if (chunk != null) {
|
||||
blocks.remove(chunk.longHash());
|
||||
this.execute(chunk);
|
||||
return chunk;
|
||||
}
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return chunks.size();
|
||||
}
|
||||
|
||||
private final LinkedBlockingDeque<FaweChunk<Chunk>> toUpdate = new LinkedBlockingDeque<>();
|
||||
|
||||
public boolean execute(final FaweChunk<Chunk> fc) {
|
||||
if (fc == null) {
|
||||
return false;
|
||||
}
|
||||
// Load chunk
|
||||
final Chunk chunk = fc.getChunk();
|
||||
chunk.loadChunk(true);
|
||||
// Set blocks / entities / biome
|
||||
if (!this.setComponents(fc)) {
|
||||
return false;
|
||||
}
|
||||
fc.executeTasks();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.blocks.clear();
|
||||
this.chunks.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setChunk(final FaweChunk<?> chunk) {
|
||||
FaweChunk<Chunk> previous = this.blocks.put(chunk.longHash(), (FaweChunk<Chunk>) chunk);
|
||||
if (previous != null) {
|
||||
chunks.remove(previous);
|
||||
}
|
||||
chunks.add((FaweChunk<Chunk>) chunk);
|
||||
}
|
||||
|
||||
public abstract Collection<FaweChunk<Chunk>> sendChunk(final Collection<FaweChunk<Chunk>> fcs);
|
||||
|
||||
public abstract boolean setComponents(final FaweChunk<Chunk> fc);
|
||||
|
||||
@Override
|
||||
public abstract FaweChunk<Chunk> getChunk(int x, int z);
|
||||
|
||||
@Override
|
||||
public abstract boolean fixLighting(final FaweChunk<?> fc, final boolean fixAll);
|
||||
}
|
@ -1,244 +0,0 @@
|
||||
package com.boydti.fawe.v1_8;
|
||||
|
||||
import com.boydti.fawe.FaweCache;
|
||||
import com.boydti.fawe.object.FaweChunk;
|
||||
import com.boydti.fawe.util.FaweQueue;
|
||||
import com.sk89q.worldedit.world.biome.BaseBiome;
|
||||
import java.util.Arrays;
|
||||
import org.spongepowered.api.Sponge;
|
||||
import org.spongepowered.api.world.Chunk;
|
||||
import org.spongepowered.api.world.World;
|
||||
|
||||
public class SpongeChunk_1_8 extends FaweChunk<Chunk> {
|
||||
|
||||
public char[][] ids;
|
||||
public short[] count;
|
||||
public short[] air;
|
||||
public short[] relight;
|
||||
public int[][] biomes;
|
||||
public Chunk chunk;
|
||||
|
||||
public SpongeChunk_1_8(FaweQueue parent, int x, int z) {
|
||||
super(parent, x, z);
|
||||
this.ids = new char[16][];
|
||||
this.count = new short[16];
|
||||
this.air = new short[16];
|
||||
this.relight = new short[16];
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Chunk getChunk() {
|
||||
if (this.chunk == null) {
|
||||
World world = Sponge.getServer().getWorld(getParent().world).get();
|
||||
this.chunk = world.loadChunk(getX(), 0, getZ(), true).get();
|
||||
}
|
||||
return this.chunk;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoc(final FaweQueue parent, int x, int z) {
|
||||
super.setLoc(parent, x, z);
|
||||
this.chunk = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getCount(int i) {
|
||||
return this.count[i];
|
||||
}
|
||||
|
||||
public int getAir(int i) {
|
||||
return this.air[i];
|
||||
}
|
||||
|
||||
public void setCount(int i, short value) {
|
||||
this.count[i] = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of block changes in a specified section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public int getRelight(int i) {
|
||||
return this.relight[i];
|
||||
}
|
||||
|
||||
public int getTotalCount() {
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.count[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
public int getTotalRelight() {
|
||||
if (getTotalCount() == 0) {
|
||||
Arrays.fill(this.count, (short) 1);
|
||||
Arrays.fill(this.relight, Short.MAX_VALUE);
|
||||
return Short.MAX_VALUE;
|
||||
}
|
||||
int total = 0;
|
||||
for (int i = 0; i < 16; i++) {
|
||||
total += this.relight[i];
|
||||
}
|
||||
return total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw data for a section.
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public char[] getIdArray(int i) {
|
||||
return this.ids[i];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBlock(int x, int y, int z, int id, byte data) {
|
||||
int i = FaweCache.CACHE_I[y][x][z];
|
||||
int j = FaweCache.CACHE_J[y][x][z];
|
||||
char[] vs = this.ids[i];
|
||||
if (vs == null) {
|
||||
vs = this.ids[i] = new char[4096];
|
||||
this.count[i]++;
|
||||
} else if (vs[j] == 0) {
|
||||
this.count[i]++;
|
||||
}
|
||||
switch (id) {
|
||||
case 0:
|
||||
this.air[i]++;
|
||||
vs[j] = (char) 1;
|
||||
return;
|
||||
case 10:
|
||||
case 11:
|
||||
case 39:
|
||||
case 40:
|
||||
case 51:
|
||||
case 74:
|
||||
case 89:
|
||||
case 122:
|
||||
case 124:
|
||||
case 138:
|
||||
case 169:
|
||||
this.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] = (char) (id << 4);
|
||||
return;
|
||||
case 130:
|
||||
case 76:
|
||||
case 62:
|
||||
this.relight[i]++;
|
||||
case 54:
|
||||
case 146:
|
||||
case 61:
|
||||
case 65:
|
||||
case 68:
|
||||
if (data < 2) {
|
||||
data = 2;
|
||||
}
|
||||
default:
|
||||
vs[j] = (char) ((id << 4) + data);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setBiome(int x, int z, BaseBiome biome) {
|
||||
if (this.biomes == null) {
|
||||
this.biomes = new int[16][];
|
||||
}
|
||||
int[] index = this.biomes[x];
|
||||
if (index == null) {
|
||||
index = this.biomes[x] = new int[16];
|
||||
}
|
||||
index[z] = biome.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public FaweChunk<Chunk> copy(boolean shallow) {
|
||||
SpongeChunk_1_8 toReturn = new SpongeChunk_1_8(getParent(), getX(), getZ());
|
||||
if (shallow) {
|
||||
toReturn.ids = ids;
|
||||
toReturn.air = air;
|
||||
toReturn.biomes = biomes;
|
||||
toReturn.chunk = chunk;
|
||||
toReturn.count = count;
|
||||
toReturn.relight = relight;
|
||||
} else {
|
||||
toReturn.air = this.air.clone();
|
||||
toReturn.count = this.count.clone();
|
||||
toReturn.relight = this.relight.clone();
|
||||
toReturn.ids = new char[this.ids.length][];
|
||||
for (int i = 0; i < this.ids.length; i++) {
|
||||
char[] matrix = this.ids[i];
|
||||
if (matrix != null) {
|
||||
toReturn.ids[i] = new char[matrix.length];
|
||||
System.arraycopy(matrix, 0, toReturn.ids[i], 0, matrix.length);
|
||||
}
|
||||
}
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user